1. 程式人生 > >SpringBoot 自定義filter 和 interceptor,自定義靜態檔案存放位置

SpringBoot 自定義filter 和 interceptor,自定義靜態檔案存放位置

上篇分享我們已經有了一個最基礎具有登陸驗證功能 的SpringBoot web專案,本篇對照之前SpringMVC 的xml配置,闡述SpringBoot 中的filter 和 interceptor。

一、web.xml中的filter 和 SpringBoot filter 比較。

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter
-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true
</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

在SpringBoot 中我們定義一個filter:

package cn.pw.pf.web.filter;


import org.springframework.core.annotation.Order;

import
javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; /** * 自定義Filter * Login Filter * @Description: * @Author:libin * @Date: Created in 16:40 2017/11/13 */ @WebFilter(filterName = "myFilter",urlPatterns = "/*") @Order(1) public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("filter======> 我是過濾器!"); chain.doFilter(request,response); } @Override public void destroy() { } }

@WebFilter 是自定義Filter的關鍵註解,屬性filterName 相當於web.xml中的 <filter-name>;屬性urlPatterns 相當於web.xml中的<url-pattern>
@Order(1)在定義多個Filter時,用於決定執行順序的,數字越小,越先執行。

說明:本篇以web.xml的CharacterEncodingFilter為例,但在SpringBoot中CharacterEncodingFilter有更簡單的配置,在application.xml中做如下配置便可 :

spring:
  http:
    encoding:
      charset: UTF-8
      enabled: true
      force: true

言歸正傳,我們啟動專案測試一下過濾器是否 生效:
在瀏覽器分別開啟 http://localhost:8680/hellohttp://localhost:8680/login ,觀察控制檯輸出,如果不出意外,控制檯連續輸出了 “filter======> 我是過濾器!”,看來我們的過濾器生效了,我們還可以將urlPatterns 設定 為 /hello ,這樣只有訪問 http://localhost:8680/hello 時,控制檯才會輸出 “filter======> 我是過濾器!”。

二、spring-mvc.xml中的 interceptor 和SpringBoot interceptor 比較

<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/static/**" />           
            <bean class="cn.pw.pf.web.filter.MyInterceptor" />
        </mvc:interceptor>
</mvc:interceptors>

上面的配置不用解釋,先在filter包下編寫一個MyInterceptor類。

package cn.pw.pf.web.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定義攔截器
 * @Description:
 * @Author:libin
 * @Date: Created in 17:46 2017/11/13
 */
@Component
public class MyInterceptor implements HandlerInterceptor {

    Logger logger = LoggerFactory.getLogger(MyInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("執行preHandle==============》");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        logger.info("執行postHandle==============》");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        logger.info("執行afterCompletion==============》");
    }
}

下面我們看在SpringBoot中如何讓自定義的攔截器MyInterceptor 生效

package cn.pw.pf.web.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 配置自定義攔截器
 * @Description:
 * @Author:libin
 * @Date: Created in 17:41 2017/11/13
 */
@Configuration
public class MyWebConfig extends WebMvcConfigurerAdapter{

    @Autowired
    private MyInterceptor myInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
                           registry.addInterceptor(myInterceptor).addPathPatterns("/*").excludePathPatterns("/hello/**");
        super.addInterceptors(registry);
    }
}

閱讀上面的程式碼,我們不難發現,主要在重寫WebMvcConfigurerAdapter的addInterceptors方法上,addPathPatterns添加了要攔截的路徑,excludePathPatterns添加了排除的路徑。
我們重啟專案,測試一下,訪問 http://localhost:8680/login ,也可以在login介面點選登入。
測試結果,我們分析任何一次訪問都經過了filter和interceptor。

filter======> 我是過濾器!
cn.pw.pf.web.filter.MyInterceptor : 執行preHandle==============》
cn.pw.pf.web.filter.MyInterceptor : 執行postHandle==============》
cn.pw.pf.web.filter.MyInterceptor : 執行afterCompletion==============》
filter======> 我是過濾器!

我們排除掉的”/hello/**”,攔截器不再攔截它,測試順利通過!
有同學就問了,你為什麼不按spring-mvc.xml中一樣 ,排除 static 資源。原因很簡單,SpringBoot預設不攔截所有的靜態資源,如果不信,可以 直接訪問 http://localhost:8680/css/common.css 試試。

說明:SpringBoot把類路徑下的/static,/public,/resources和META-INF/resources檔案下的靜態檔案對映為了 “/”,可以直接訪問,我們也可以根據下面的方法自定義靜態檔案的存放位置。

三、自定義靜態檔案存放 位置,只需在MyWebConfig 中,重寫addResourceHandlers方法。

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

這樣,我們就定義了一個和static平級的資料夾img用來存放圖片,隨便丟一張 圖片no.jpg進去,然後帶上路徑訪問:
http://localhost:8680/img/no.jpg

OK,今天的分享就到此結束了,SpringBoot的基礎使用就分享這麼多,很簡單。

到今天網際網路迸發的時代,微服務已是大勢所趨,只有在 SpringCloud 微服務架構下,使用SpringBoot才是開發人員值得研究的方向。如果有人想深入瞭解SpringBoot ,我推薦《java EE 開發的顛覆者 Spring Boot 實戰》這本書。但是,初學的讀者一定要注意,這本書是在SpringBoot 1.3版本的基礎上講解的,想實踐書中的例子,一定要用對版本,要不會很苦惱。

後面的分享,我將開啟新的篇章,結合SpringCloud 、Eureka、等,逐步由簡入深,來完成一個基於微服務框架的簡單demo,幫助初學者快速上手。