自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

過濾器Filter和攔截器Interceptor的聯(lián)系和區(qū)別

開發(fā) 前端
本文將對攔截器Interceptor進(jìn)行簡單講解,并通過幾個例子對它們的差異進(jìn)行簡要分析。

本文將對攔截器Interceptor進(jìn)行簡單講解,并通過幾個例子對它們的差異進(jìn)行簡要分析。

攔截器Interceptor簡介

一個應(yīng)用中可以定義多個攔截器,spring在項目啟動時,會將這些攔截器注冊進(jìn)來,并按照默認(rèn)規(guī)則進(jìn)行排序。如果是自定義的攔截器,可手動設(shè)置攔截器調(diào)用的先后順序。

各攔截器是鏈?zhǔn)秸{(diào)用,一個請求可以觸發(fā)多個攔截器,每個攔截器的調(diào)用會按照它加載到spring中的順序依次執(zhí)行。

攔截器中有3個方法,功能如下:

  • preHandle:該方法在調(diào)用Controller方法或獲取靜態(tài)資源前被調(diào)用(靜態(tài)資源包括html、js等)。
  • postHandle:該方法在調(diào)用Controller方法或獲取靜態(tài)資源后,但是視圖還沒有被渲染前調(diào)用。
  • afterCompletion:該方法在視圖渲染后進(jìn)行調(diào)用,主要用來清除資源。

自定義攔截器Interceptor 

  1. public class MyInterceptor implements HandlerInterceptor { 
  2.     @Override 
  3.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
  4.         System.out.println("調(diào)用preHandle"); 
  5.         return true
  6.     } 
  7.  
  8.     @Override 
  9.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 
  10.         System.out.println("調(diào)用postHandle"); 
  11.     } 
  12.  
  13.     @Override 
  14.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 
  15.         System.out.println("調(diào)用afterCompletion"); 
  16.     } 

注冊自定義攔截器Interceptor

編寫配置類并實現(xiàn)WebMvcConfigurer接口。 

  1. @Configuration 
  2. public class MyWebConfig implements WebMvcConfigurer { 
  3.     @Override 
  4.     public void addInterceptors(InterceptorRegistry registry) { 
  5.         registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); 
  6.     } 

過濾器Filter和攔截器Interceptor區(qū)別

過濾器和攔截器都可以實現(xiàn)例如編碼設(shè)置、日志記錄、權(quán)限控制等功能,但是二者還是有很多區(qū)別的。

(1)實現(xiàn)原理不同

Filter是基于函數(shù)回調(diào)實現(xiàn)的:

每個自定義過濾器都會實現(xiàn)一個doFilter()方法,這個方法有一個關(guān)鍵參數(shù)FilterChain。它是一個回調(diào)接口,ApplicationFilterChain是它的具體實現(xiàn)類,該類內(nèi)部也有一個doFilter()方法,這個方法就是回調(diào)方法(ps:可以理解為方法遞歸調(diào)用,查看源碼比較容易理解)。

假設(shè)有2個濾器,調(diào)用流程圖如下(ps:畫的比較抽象): 

兩個過濾器執(zhí)行流程 

Interceptor是基于反射實現(xiàn)的:

為什么說攔截器是基于反射實現(xiàn)的呢?個人理解在攔截器內(nèi)部的三個方法中,都有一個共同的參數(shù)handler,這個參數(shù)里包含的信息比較豐富。包含該請求所對應(yīng)的方法、方法所在的Controller、方法參數(shù)等信息,而這些信息都是spring通過反射加載進(jìn)來的。正是由于這些豐富的參數(shù),使得攔截的功能相比過濾器功能更強大。 

 handler參數(shù)信息 

(2)使用范圍不同

過濾器Filter實現(xiàn)了javax.servlet.Filter接口,也就是說過濾器的使用要依賴于Tomcat等容器,所以它只能在web程序中使用。

攔截器Interceptor實現(xiàn)了

org.springframework.web.servlet接口,它是由Spring容器進(jìn)行管理,并不依賴Tomcat等容器,既可以應(yīng)用在web程序中,也可以應(yīng)用在非web程序中。

(3)觸發(fā)時機不同

過濾器Filter是在請求進(jìn)入Tomcat等容器后,servlet處理之前進(jìn)行調(diào)用的。

攔截器Interceptor是在請求進(jìn)入servlet后,執(zhí)行Controller之前進(jìn)行調(diào)用的。

(4)攔截范圍不同

過濾器Filter幾乎可以攔截所有進(jìn)入容器的請求。

攔截器Interceptor只會對Controller請求或訪問static目錄下的靜態(tài)資源請求起作用。

(5)初始化時機不同

過濾器Filter是隨著Tomcat等web容器啟動時而進(jìn)行初始化。

攔截器Interceptor時隨著spring啟動而進(jìn)行初始化。

過濾器和攔截器如何注入依賴服務(wù)

在實際開發(fā)中,當(dāng)使用到過濾器或攔截器時,難免會引入一些依賴的service服務(wù)。下面就通過例子進(jìn)行簡要說明:

Filter依賴service:直接采用注解@Autowired即可。 

  1. @WebFilter(urlPatterns = {"/user/*"}) 
  2. @Log4j2 
  3. public class MyFilter implements Filter { 
  4.     @Autowired 
  5.     private UserService userService; 
  6.      
  7.     @Override 
  8.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { 
  9.         HttpServletRequest httpServletRequest = (HttpServletRequest) request; 
  10.         log.info("Filter獲取到請求地址:" + httpServletRequest.getServletPath()); 
  11.         filterChain.doFilter(request, response); 
  12.  
  13.         HttpServletResponse httpServletResponse = (HttpServletResponse) response; 
  14.         log.info("Filter獲取到響應(yīng)類型:" + httpServletResponse.getContentType()); 
  15.     } 
  16.  
  17.     @Override 
  18.     public void init(FilterConfig filterConfig) throws ServletException { 
  19.         System.out.println("Filter隨著項目的啟動而啟動,只初始化一次"); 
  20.     } 
  21.  
  22.     @Override 
  23.     public void destroy() { 
  24.         System.out.println("Filter隨著web項目的停止而銷毀,完成資源回收"); 
  25.     } 

Interceptor依賴service:直接采用注解@Autowired,但是在將攔截器注入到spring容器中時,不能自己通過new來進(jìn)行創(chuàng)建。需要將攔截器當(dāng)做一個普通的bean注入到spring容器中,這樣就可以將service注入到攔截器中。 

  1. public class MyInterceptor implements HandlerInterceptor { 
  2.     @Autowired 
  3.     private UserService userService; 
  4.      
  5.     @Override 
  6.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
  7.         System.out.println("調(diào)用preHandle"); 
  8.         return true
  9.     } 
  10.  
  11.     @Override 
  12.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 
  13.         System.out.println("調(diào)用postHandle"); 
  14.     } 
  15.  
  16.     @Override 
  17.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 
  18.         System.out.println("調(diào)用afterCompletion"); 
  19.     } 

 

  1. @Configuration 
  2. public class MyWebConfig implements WebMvcConfigurer { 
  3.  
  4.     @Bean 
  5.     public MyInterceptor getMyInterceptor(){ 
  6.         return new MyInterceptor(); 
  7.     } 
  8.  
  9.     @Override 
  10.     public void addInterceptors(InterceptorRegistry registry) { 
  11.         // getMyInterceptor()這種注冊方式可以在攔截器里注入bean 
  12.         registry.addInterceptor(getMyInterceptor()).addPathPatterns("/**"); 
  13.         // 這種注冊方式由于是自己new出來的,所以在攔截器里注冊的bean都為null 
  14.         registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**"); 
  15.     } 

過濾器和攔截器如何指定加載順序

(1)Filter:需要通過配置類指定加載順序,值越小,越先執(zhí)行。采用@WebFilter無法指定順序。 

  1. @Bean 
  2. public FilterRegistrationBean myFilter(){ 
  3.     MyFilter myFilter = new MyFilter(); 
  4.     FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter); 
  5.     filterRegistrationBean.setUrlPatterns(Arrays.asList("/user/*")); 
  6.     filterRegistrationBean.setOrder(2); 
  7.     return filterRegistrationBean; 

(2)Interceptor:需要通過配置類指定加載順序,值越小,越先執(zhí)行。 

  1. @Configuration 
  2. public class MyWebConfig implements WebMvcConfigurer { 
  3.     @Override 
  4.     public void addInterceptors(InterceptorRegistry registry) { 
  5.         // getMyInterceptor()這種注冊方式可以在攔截器里注入bean 
  6.         registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").order(1); 
  7.         // 這種注冊方式由于是自己new出來的,所以在攔截器里注冊的bean都為null 
  8.         registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**").order(2); 
  9.     } 

過濾器Filter和攔截器Interceptor使用場景

二者相比攔截器功能更強大些,F(xiàn)ilter能做的事情,它都能做,而且可以在請求前,請求后執(zhí)行,比較靈活。Filter主要用來設(shè)置字符編碼、過濾敏感詞匯和URL級別的簡單權(quán)限控制。如果需要記錄比較詳細(xì)的信息或比較復(fù)雜的權(quán)限管理,還是建議用攔截器實現(xiàn)。

拓展

Servlet和Controller的區(qū)別是什么?

使用Servlet可以收集來自網(wǎng)頁表單的用戶輸入,還可以動態(tài)創(chuàng)建網(wǎng)頁。DispatcherServlet是SpringMVC中唯一的Servlet,Servlet容器(Tomcat)把所有的請求都轉(zhuǎn)發(fā)到DispatcherServlet,然后通過HandlerMapping把請求路由到具體的Controller中。因此,Controller只是一個普通的Java Bean。

 

責(zé)任編輯:未麗燕 來源: 今日頭條
相關(guān)推薦

2023-02-20 07:19:14

2023-05-29 07:36:04

Java過濾器攔截器

2020-06-04 07:45:07

過濾器和攔截器

2020-09-14 12:46:25

過濾器攔截器Filter

2021-11-03 17:04:11

攔截器操作Servlet

2024-01-17 08:56:31

2016-12-07 09:56:13

JavaFilter過濾器

2024-11-04 08:45:48

布隆過濾器元數(shù)據(jù)指紋值

2024-01-08 08:33:53

AOPSpring攔截器

2011-01-12 19:31:54

IP FilterUnix數(shù)據(jù)包過濾器

2023-09-15 11:26:16

2022-05-13 08:23:07

Zuul微服務(wù)Zuul過濾器

2022-03-21 08:31:07

布隆過濾器Redis過濾器原理

2009-06-24 16:00:00

2021-07-05 15:22:03

Servlet過濾器客戶端

2023-09-05 08:58:07

2009-06-22 11:28:00

Filter結(jié)構(gòu)建立過濾器

2024-01-05 09:04:35

隆過濾器數(shù)據(jù)結(jié)構(gòu)哈希函數(shù)

2009-07-08 16:10:36

Servlet和JSPJSP頁面

2009-06-18 10:13:00

Hibernate過濾
點贊
收藏

51CTO技術(shù)棧公眾號