<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          過濾器和攔截器的 5 個(gè)區(qū)別!

          共 6752字,需瀏覽 14分鐘

           ·

          2022-10-20 03:48

          作者 | 磊哥

          來源 | Java面試真題解析(ID:aimianshi666)

          轉(zhuǎn)載請(qǐng)聯(lián)系授權(quán)(微信ID:GG_Stone)

          過濾器(Filter)和攔截器(Interceptor)都是基于 AOP(Aspect Oriented Programming,面向切面編程)思想實(shí)現(xiàn)的,用來解決項(xiàng)目中某一類問題的兩種“工具”,但二者有著明顯的差距,接下來我們一起來看。

          實(shí)現(xiàn)過濾器和攔截器

          首先,我們先來看一下二者在 Spring Boot 項(xiàng)目中的具體實(shí)現(xiàn),這對(duì)后續(xù)理解二者的區(qū)別有很大的幫助。

          實(shí)現(xiàn)過濾器

          過濾器可以使用 Servlet 3.0 提供的 @WebFilter 注解,配置過濾的 URL 規(guī)則,然后再實(shí)現(xiàn) Filter 接口,重寫接口中的 doFilter 方法,具體實(shí)現(xiàn)代碼如下:

          import org.springframework.stereotype.Component;
          import javax.servlet.*;
          import javax.servlet.annotation.WebFilter;
          import java.io.IOException;
          @Component
          @WebFilter(urlPatterns = "/*")
          public class TestFilter implements Filter {
              @Override
              public void init(FilterConfig filterConfig) throws ServletException {
                  System.out.println("過濾器:執(zhí)行 init 方法。");
              }
              @Override
              public void doFilter(ServletRequest servletRequest,
                                   ServletResponse servletResponse,
                                   FilterChain filterChain)
           throws IOException, ServletException 
          {
                  System.out.println("過濾器:開始執(zhí)行 doFilter 方法。");
                  // 請(qǐng)求放行
                  filterChain.doFilter(servletRequest, servletResponse);
                  System.out.println("過濾器:結(jié)束執(zhí)行 doFilter 方法。");
              }
              @Override
              public void destroy() {
                  System.out.println("過濾器:執(zhí)行 destroy 方法。");
              }
          }

          其中:

          • void init(FilterConfig filterConfig):容器啟動(dòng)(初始化 Filter)時(shí)會(huì)被調(diào)用,整個(gè)程序運(yùn)行期只會(huì)被調(diào)用一次。用于實(shí)現(xiàn) Filter 對(duì)象的初始化。

          • void doFilter(ServletRequest request, ServletResponse response,FilterChain chain):具體的過濾功能實(shí)現(xiàn)代碼,通過此方法對(duì)請(qǐng)求進(jìn)行過濾處理,其中 FilterChain 參數(shù)是用來調(diào)用下一個(gè)過濾器或執(zhí)行下一個(gè)流程。

          • void destroy():用于 Filter 銷毀前完成相關(guān)資源的回收工作。

            實(shí)現(xiàn)攔截器

            攔截器的實(shí)現(xiàn)分為兩步,第一步,創(chuàng)建一個(gè)普通的攔截器,實(shí)現(xiàn) HandlerInterceptor 接口,并重寫接口中的相關(guān)方法;第二步,將上一步創(chuàng)建的攔截器加入到 Spring Boot 的配置文件中。接下來,先創(chuàng)建一個(gè)普通攔截器,實(shí)現(xiàn) HandlerInterceptor 接口并重寫 preHandle/postHandle/afterCompletion 方法,具體實(shí)現(xiàn)代碼如下:

          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;
          @Component
          public class TestInterceptor implements HandlerInterceptor {
              @Override
              public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                  System.out.println("攔截器:執(zhí)行 preHandle 方法。");
                  return true;
              }
              @Override
              public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
                  System.out.println("攔截器:執(zhí)行 postHandle 方法。");
              }
              @Override
              public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
                  System.out.println("攔截器:執(zhí)行 afterCompletion 方法。");
              }
          }

          其中:

          • boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle):在請(qǐng)求方法執(zhí)行前被調(diào)用,也就是調(diào)用目標(biāo)方法之前被調(diào)用。比如我們?cè)诓僮鲾?shù)據(jù)之前先要驗(yàn)證用戶的登錄信息,就可以在此方法中實(shí)現(xiàn),如果驗(yàn)證成功則返回 true,繼續(xù)執(zhí)行數(shù)據(jù)操作業(yè)務(wù);否則就返回 false,后續(xù)操作數(shù)據(jù)的業(yè)務(wù)就不會(huì)被執(zhí)行了。
          • void postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView):調(diào)用請(qǐng)求方法之后執(zhí)行,但它會(huì)在 DispatcherServlet 進(jìn)行渲染視圖之前被執(zhí)行。
          • void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex):會(huì)在整個(gè)請(qǐng)求結(jié)束之后再執(zhí)行,也就是在 DispatcherServlet 渲染了對(duì)應(yīng)的視圖之后再執(zhí)行。

          最后,我們?cè)賹⑸厦娴臄r截器注入到項(xiàng)目配置文件中,并設(shè)置相應(yīng)攔截規(guī)則,具體實(shí)現(xiàn)代碼如下:

          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.context.annotation.Configuration;
          import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
          import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

          @Configuration
          public class AppConfig implements WebMvcConfigurer {

              // 注入攔截器
              @Autowired
              private TestInterceptor testInterceptor;

              @Override
              public void addInterceptors(InterceptorRegistry registry) {
                  registry.addInterceptor(testInterceptor) // 添加攔截器
                          .addPathPatterns("/*"); // 攔截所有地址
              }
          }

          了解了二者的使用之后,接下來我們來看二者的區(qū)別。

          過濾器 VS 攔截器

          過濾器和攔截器的區(qū)別主要體現(xiàn)在以下 5 點(diǎn):

          1. 出身不同;
          2. 觸發(fā)時(shí)機(jī)不同;
          3. 實(shí)現(xiàn)不同;
          4. 支持的項(xiàng)目類型不同;
          5. 使用的場(chǎng)景不同。

          接下來,我們一一來看。

          1.出身不同

          過濾器來自于 Servlet,而攔截器來自于 Spring 框架,從上面代碼中我們也可以看出,過濾器在實(shí)現(xiàn)時(shí)導(dǎo)入的是 Servlet 相關(guān)的包,如下圖所示:而攔截器在實(shí)現(xiàn)時(shí),導(dǎo)入的是 Spring 相關(guān)的包,如下圖所示:

          2.觸發(fā)時(shí)機(jī)不同

          請(qǐng)求的執(zhí)行順序是:請(qǐng)求進(jìn)入容器 > 進(jìn)入過濾器 > 進(jìn)入 Servlet > 進(jìn)入攔截器 > 執(zhí)行控制器(Controller),如下圖所示:所以過濾器和攔截器的執(zhí)行時(shí)機(jī)也是不同的,過濾器會(huì)先執(zhí)行,然后才會(huì)執(zhí)行攔截器,最后才會(huì)進(jìn)入真正的要調(diào)用的方法

          3.實(shí)現(xiàn)不同

          過濾器是基于方法回調(diào)實(shí)現(xiàn)的,我們?cè)谏厦鎸?shí)現(xiàn)過濾器的時(shí)候就會(huì)發(fā)現(xiàn),當(dāng)我們要執(zhí)行下一個(gè)過濾器或下一個(gè)流程時(shí),需要調(diào)用 FilterChain 對(duì)象的 doFilter 方法進(jìn)行回調(diào)執(zhí)行,如下圖所示:由此可以看出,過濾器的實(shí)現(xiàn)是基于方法回調(diào)的。而攔截器是基于動(dòng)態(tài)代理(底層是反射)實(shí)現(xiàn)的,它的實(shí)現(xiàn)如下圖所示:代理調(diào)用的效果如下圖所示:

          4.支持的項(xiàng)目類型不同

          過濾器是 Servlet 規(guī)范中定義的,所以過濾器要依賴 Servlet 容器,它只能用在 Web 項(xiàng)目中;而攔截器是 Spring 中的一個(gè)組件,因此攔截器既可以用在 Web 項(xiàng)目中,同時(shí)還可以用在 Application 或 Swing 程序中。

          5.使用的場(chǎng)景不同

          因?yàn)閿r截器更接近業(yè)務(wù)系統(tǒng),所以攔截器主要用來實(shí)現(xiàn)項(xiàng)目中的業(yè)務(wù)判斷的,比如:登錄判斷、權(quán)限判斷、日志記錄等業(yè)務(wù)。而過濾器通常是用來實(shí)現(xiàn)通用功能過濾的,比如:敏感詞過濾、字符集編碼設(shè)置、響應(yīng)數(shù)據(jù)壓縮等功能。

          本文項(xiàng)目源碼下載

          https://gitee.com/mydb/springboot-examples/tree/master/spring-boot-filter

          總結(jié)

          過濾器和攔截器都是基于 AOP 思想實(shí)現(xiàn)的,用來處理某個(gè)統(tǒng)一的功能的,但二者又有 5 點(diǎn)不同:出身不同、觸發(fā)時(shí)機(jī)不同、實(shí)現(xiàn)不同、支持的項(xiàng)目類型不同以及使用的場(chǎng)景不同。過濾器通常是用來進(jìn)行全局過濾的,而攔截器是用來實(shí)現(xiàn)某項(xiàng)業(yè)務(wù)攔截的。

          參考 & 鳴謝

          • blog.csdn.net/wo541075754/article/details/111661213

          • zhuanlan.zhihu.com/p/340397290

          是非審之于己,毀譽(yù)聽之于人,得失安之于數(shù)。

          公眾號(hào):Java面試真題解析

          面試合集:https://gitee.com/mydb/interview


          往期推薦

          面試突擊89:事務(wù)隔離級(jí)別和傳播機(jī)制有什么區(qū)別?


          面試突擊88:加入事務(wù)和嵌套事務(wù)有什么區(qū)別?


          面試突擊87:說一下 Spring 事務(wù)傳播機(jī)制?

          瀏覽 72
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无码看电影 | 国产美女精品视频 | 青青草97 | 欧美日韩亚洲一区二区 | 欧美高清中文字幕精品日韩不卡国产在线 |