1. 程式人生 > >Spring Boot乾貨系列:(六)靜態資源和攔截器處理

Spring Boot乾貨系列:(六)靜態資源和攔截器處理

正文

    前面章節我們也有簡單介紹過SpringBoot中對靜態資源的預設支援,今天詳細的來介紹下預設的支援,以及自定義擴充套件如何實現。

預設資源對映

Spring Boot 預設為我們提供了靜態資源處理,使用 WebMvcAutoConfiguration 中的配置各種屬性。

建議大家使用Spring Boot的預設配置方式,提供的靜態資源對映如下:

  • classpath:/META-INF/resources
  • classpath:/resources
  • classpath:/static
  • classpath:/public

在工程裡面路徑是這樣:

sprngboot6-1.jpg

        上面這幾個都是靜態資源的對映路徑,優先順序順序為:META-INF/resources > resources > static > public
        大家可以自己在上面4個路徑下都放一張同名的圖片,訪問一下即可驗證。
還有,你可以隨機在上面一個路徑下面放上index.html,當我們訪問應用根目錄http://lcoalhost:8080 時,會直接對映到index.html頁面。

對應的配置檔案配置如下:

# 預設值為 /**
spring.mvc.static-path-pattern=
# 預設值為 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
spring.resources.static-locations=這裡設定要指向的路徑,多個使用英文逗號隔開

       我們可以通過修改spring.mvc.static-path-pattern來修改預設的對映,例如我改成/dudu/**,那執行的時候訪問 http://lcoalhost:8080/dudu/index.html 才對應到index.html頁面。

接管Spring Boot的Web配置

        如果Spring Boot提供的Sping MVC不符合要求,則可以通過一個配置類(註解有@Configuration的類)加上@EnableWebMvc註解來實現完全自己控制的MVC配置。

        當然,通常情況下,Spring Boot的自動配置是符合我們大多數需求的。在你既需要保留Spring Boot提供的便利,有需要增加自己的額外的配置的時候,可以定義一個配置類並繼承WebMvcConfigurerAdapter,無需使用@EnableWebMvc註解。

       這裡我們提到這個WebMvcConfigurerAdapter這個類,重寫這個類中的方法可以讓我們增加額外的配置,這裡我們就介紹幾個常用的。

自定義資源對映addResourceHandlers

比如,我們想自定義靜態資源對映目錄的話,只需重寫addResourceHandlers方法即可。

@Configuration
public class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
    /**
     * 配置靜態訪問資源
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/my/**").addResourceLocations("classpath:/my/");
        super.addResourceHandlers(registry);
    }
}

    通過addResourceHandler新增對映路徑,然後通過addResourceLocations來指定路徑。我們訪問自定義my資料夾中的elephant.jpg 圖片的地址為 http://localhost:8080/my/elephant.jpg

如果你想指定外部的目錄也很簡單,直接addResourceLocations指定即可,程式碼如下:

@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/my/**").addResourceLocations("file:E:/my/");
        super.addResourceHandlers(registry);
    }

addResourceLocations指的是檔案放置的目錄,addResoureHandler指的是對外暴露的訪問路徑

頁面跳轉addViewControllers

     以前寫SpringMVC的時候,如果需要訪問一個頁面,必須要寫Controller類,然後再寫一個方法跳轉到頁面,感覺好麻煩,其實重寫WebMvcConfigurerAdapter中的addViewControllers方法即可達到效果了

/**
     * 以前要訪問一個頁面需要先建立個Controller控制類,再寫方法跳轉到頁面
     * 在這裡配置後就不需要那麼麻煩了,直接訪問http://localhost:8080/toLogin就跳轉到login.htm頁面了
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/toLogin").setViewName("login");
        super.addViewControllers(registry);
    }

      值的指出的是,在這裡重寫addViewControllers方法,並不會覆蓋WebMvcAutoConfiguration中的addViewControllers(在此方法中,Spring Boot將“/”對映至index.html),這也就意味著我們自己的配置和Spring Boot的自動配置同時有效,這也是我們推薦新增自己的MVC配置的方式。

攔截器addInterceptors

攔截器在我們專案中經常使用的,這裡就來介紹下最簡單的判斷是否登入的使用。
要實現攔截器功能需要完成以下2個步驟:

  • 建立我們自己的攔截器類並實現 HandlerInterceptor 介面
  • 其實重寫WebMvcConfigurerAdapter中的addInterceptors方法把自定義的攔截器類新增進來即可

首先,自定義攔截器程式碼:

package com.dudu.interceptor;
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        boolean flag =true;
        User user=(User)request.getSession().getAttribute("user");
        if(null==user){
            response.sendRedirect("toLogin");
            flag = false;
        }else{
            flag = true;
        }
        return flag;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

這裡我們簡單實現了根據session中是否有User物件來判斷是否登入,為空就跳轉到登入頁,不為空就通過。

接著,重寫WebMvcConfigurerAdapter中的addInterceptors方法如下:

/**
* 攔截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
    // addPathPatterns 用於新增攔截規則
    // excludePathPatterns 使用者排除攔截
    registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/toLogin","/login");
    super.addInterceptors(registry);
}

addPathPatterns("/**")對所有請求都攔截,但是排除了/toLogin/login請求的攔截。

頁面登入關鍵程式碼

//簡單登入操作
$("#doLogin").click(function (e) {
    $.ajax({
    type : "POST",
    url : "/login",
    data : {
        "userName" : $("#userName").val(),
        "password" : $("#password").val()
    },
    dataType : "json",
    success : function(data) {
        if (data.result == "1") {
        window.location.href ="/learn";
        } else {
        alert("賬號密碼不能為空!");
        }
    }
    });
});

控制器程式碼:

package com.dudu.controller;
@Controller
public class LearnController {
    /**
    *登入操作
    **/
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    @ResponseBody
    public Map<String,Object> login(HttpServletRequest request, HttpServletResponse response){
        Map<String,Object> map =new HashMap<String,Object>();
        String userName=request.getParameter("userName");
        String password=request.getParameter("password");
        if(!userName.equals("") && password!=""){
            User user =new User(userName,password);
            request.getSession().setAttribute("user",user);
            map.put("result","1");
        }else{
            map.put("result","0");
        }
        return map;
    }

    @RequestMapping("/learn")
    public ModelAndView index(){
        List<LearnResouce> learnList =new ArrayList<LearnResouce>();
        LearnResouce bean =new LearnResouce("官方參考文件","Spring Boot Reference Guide","http://docs.spring.io/spring-boot/docs/1.5.1.RELEASE/reference/htmlsingle/#getting-started-first-application");
        learnList.add(bean);
        bean =new LearnResouce("官方SpriongBoot例子","官方SpriongBoot例子","https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples");
        learnList.add(bean);
        bean =new LearnResouce("龍國學院","Spring Boot 教程系列學習","http://www.roncoo.com/article/detail/125488");
        learnList.add(bean);
        bean =new LearnResouce("嘟嘟MD獨立部落格","Spring Boot乾貨系列 ","http://tengj.top/");
        learnList.add(bean);
        bean =new LearnResouce("後端程式設計嘟","Spring Boot教程和視訊 ","http://www.toutiao.com/m1559096720023553/");
        learnList.add(bean);
        bean =new LearnResouce("程式猿DD","Spring Boot系列","http://www.roncoo.com/article/detail/125488");
        learnList.add(bean);
        bean =new LearnResouce("純潔的微笑","Sping Boot系列文章","http://www.ityouknow.com/spring-boot");
        learnList.add(bean);
        bean =new LearnResouce("CSDN——小當部落格專欄","Sping Boot學習","http://blog.csdn.net/column/details/spring-boot.html");
        learnList.add(bean);
        bean =new LearnResouce("樑桂釗的部落格","Spring Boot 揭祕與實戰","http://blog.csdn.net/column/details/spring-boot.html");
        learnList.add(bean);
        bean =new LearnResouce("林祥纖部落格系列","從零開始學Spring Boot ","http://412887952-qq-com.iteye.com/category/356333");
        learnList.add(bean);
        ModelAndView modelAndView = new ModelAndView("/template");
        modelAndView.addObject("learnList", learnList);
        return modelAndView;
    }
}

       這樣訪問的時候,如果未登入就會跳轉到login.html頁面,而訪問http://localhost:8080/toLogin 和http://localhost:8080/login 不會被攔截。
springboot6.gif

 

更多配置可以檢視WebMvcConfigurerAdapter的類的API。因其是WebMvcConfigurer介面的實現,所以WebMvcConfigurer的API方法也可以用來配置MVC。
只是實現這個介面的話,要實現所有的方法,這個就尷尬了。
所以還是推薦使用繼承WebMvcConfigurerAdapter類來處理。