Filter、Interceptor、Aspect攔截機制的區別

    在使用Spring MVC開發TEST API的時候,咱們進場會使用Java的攔截機制來處理請求,Filter是Java自己自帶攔過濾器,Interceptor則是Spring自帶的攔截器,而Aspect是Spring AOP主要的使用場景有:日誌記錄、事務控制和異常處理,該篇文章主要說說它們是如何實現以及他們之間的差異。java

Filter

    我對Filter過濾器作了如下總結:web

Filter的實現方式

@Component
public class TimeFilter implements Filter {
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化TimeFilter...");
    }

 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("-------TimeFilter Start--------");
        long start = new Date().getTime();
        filterChain.doFilter(request, response);
        System.out.println("TimeFilter執行耗時:" + (new Date().getTime() - start));
        System.out.println("-------TimeFilter End--------");
    }

    @Override
    public void destroy() {
        System.out.println("銷燬TimeFilter...");
    }
}

    注意:關於filterChain.doFilter(request,response,filterChain),執行filterChain.doFilter的意思是將請求轉發給過濾器臉上的下一個對象,若是沒有filter那就是你請求的資源。 通常filter都是一個鏈,web.xml 裏面配置了幾個就有幾個。一個一個的連在一塊兒 這裏指的是下一個Filter,request->filter1->filter2->filter3->...->response。app

    咱們定義完Filter以後,若是咱們不使用@Component註解注入,可使用另外一種方式將Filter注入到咱們的容器中,這裏使用@Bean的形式定義,經過繼承WebMvcConfigurerAdapter抽象類來實現配置,最後返回registrationBean,這個方法主要有兩個好處就是第一咱們能夠經過 registrationBean.setUrlPatterns(urls) 來指明filter在哪些路徑下起做用,第二咱們可使用該方法區注入第三方的filter,緣由的不少地方放的filter並並非以@Component注入方式,這時候咱們就不能使用@Component第一種方式來注入了:ide

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Autowired
    TimeInterceptor timeInterceptor;

    @Bean
    public FilterRegistrationBean charsetFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();

        TimeFilter timeFilter = new TimeFilter();
        CharsetFilter charsetFilter = new CharsetFilter();
        registrationBean.setFilter(charsetFilter);
        registrationBean.setFilter(timeFilter);

        //至關於@webFilter的@WebInitParam()註解的做用
        Map<String,String> paramMap = new HashMap<>();
        paramMap.put("charset","utf-8");
        registrationBean.setInitParameters(paramMap);

        //至關於@webFilter的 urlPatterns = "/*"的做用
        List<String> urls = new ArrayList<>();
        urls.add("/*");
        //urls.add("/user/*");
        registrationBean.setUrlPatterns(urls);

        return registrationBean;
    }

咱們在controller中定義一個getInfo()方法:post

//請求路徑的{id}回傳到方法裏也就是傳到(@PathVariable String id)的id裏
    @RequestMapping(value = "/user/{id:\\d+}",method = RequestMethod.GET)
    @JsonView(User.UserDetailView.class)    //這裏由於UserDetailView繼承了UserSimpleView全部會返回username和password
    @ApiOperation("獲取用戶信息")
    public User getInfo(@PathVariable Integer id) {

//        throw new UserNotExistException(id);
        System.out.println("進入getInfo()服務");
        User user = new User();
        user.setId(1);
        user.setUsername("jacklin");
        user.setPassword("123");
        return user;
    }

當咱們調用controller中的getInfo()方法的時候,看看請求響應是否成以及控制檯的輸出:url

GET請求發送成功,返回200,控制檯輸出以下:spa

從上述結果,咱們能夠分析得出,當客戶端發送請求,到達Controller方法以前,先執行Filter初始化操做,接着進入Controller的方法體,最後執行完成,經過分析咱們明白了Filter的工做原理和方法的執行順序!3d

Interceptor

    我對Interceptor過濾器作了如下總結(導圖中加粗部分是重點):日誌

Interceptor攔截器的實現方式

**
 * @Author 林必昭
 * @Date 2019/7/4 13:15
 */

@Component
public class TimeInterceptor implements HandlerInterceptor {

    /**
     * preHandle方法的返回值是boolean值,當返回的是false時候,不會進入controller裏的方法
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("------->preHandle");
        System.out.println(((HandlerMethod)handler).getBean().getClass().getName());    //獲取類名
        System.out.println(((HandlerMethod)handler).getMethod().getName());             //獲取類中方法名
        request.setAttribute("startTime",new Date().getTime());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("------->postHandle");
        long start = new Date().getTime();
        System.out.println("TimeInterceptor執行耗時:"+" "+(new Date().getTime()-start));
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) throws Exception {
        System.out.println("------->afterCompletion");
        long start = new Date().getTime();
        System.out.println("TimeInterceptor執行耗時:"+" "+(new Date().getTime()-start));
        System.out.println("Exception is "+ e);
    }
}

一樣,咱們經過發送請求,觀察控制檯的輸出,來分析結果:code

從TimeInterceptor攔截器結果,咱們能夠分析得出,當客戶端發送請求,到達Controller方法以前,先執行Interceptor的preHandler方法,接着進入Controller的方法體,咱們能夠獲取到對應的Controller,接着執行postHandler方法,最後執行完成!

Aspect

    我對Aspect過濾器作了如下總結:

相關文章
相關標籤/搜索