<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>

          攔截器(Interceptor)與過濾器(Filter)

          共 15875字,需瀏覽 32分鐘

           ·

          2021-05-23 09:27

          點(diǎn)擊上方“程序員大白”,選擇“星標(biāo)”公眾號(hào)

          重磅干貨,第一時(shí)間送達(dá)

          一、用戶的普通Http請(qǐng)求執(zhí)行順序

          二、過濾器、攔截器添加后的執(zhí)行順序

          三、攔截器(Interceptor)的基本定義

            攔截器是面向切面(AOP)編程中應(yīng)用的一種統(tǒng)一處理方案,就是在你的Controller、Servie或者一個(gè)Method調(diào)用一個(gè)Method,或者在Method調(diào)用一個(gè)Method之后,統(tǒng)一的進(jìn)行處理的方案,基于Java的反射機(jī)制。

            攔截器,在AOP(Aspect-Oriented Programming)中可以用于在某個(gè)方法或者字段被訪問之前,進(jìn)行攔截,然后在之前或者之后加入某些統(tǒng)一的處理方法。攔截是AOP的一種具象的實(shí)現(xiàn)方式。

            攔截器將很多service或者Controller中共有的行為提煉出來,在某些方法執(zhí)行的前后執(zhí)行,提煉為通用的處理方式,讓被攔截的方法都能享受這一共有的功能,讓代碼更加簡(jiǎn)潔,同時(shí),當(dāng)共有的功能需要發(fā)生調(diào)整、變動(dòng)的時(shí)候,不必修改很多的類或者方法,只要修改這個(gè)攔截器就可以了,可復(fù)用性很強(qiáng)。

            Spring MVC 中的Interceptor攔截請(qǐng)求是通過HandlerInterceptor來實(shí)現(xiàn)的。

          四、攔截器(Interceptor)必須實(shí)現(xiàn)的三個(gè)方法

            1)總覽

            2)preHandle(HttpServletRequest request, HttpServletResponse response, Object handle)方法

              該方法將在請(qǐng)求處理之前進(jìn)行調(diào)用。SpringMVC 中的Interceptor 是鏈?zhǔn)降恼{(diào)用的,在一個(gè)應(yīng)用中或者說是在一個(gè)請(qǐng)求中可以同時(shí)存在多個(gè)Interceptor 。每個(gè)Interceptor 的調(diào)用會(huì)依據(jù)它的聲明順序依次執(zhí)行,而且最先執(zhí)行的都是Interceptor 中的preHandle 方法,所以可以在這個(gè)方法中進(jìn)行一些前置初始化操作或者是對(duì)當(dāng)前請(qǐng)求的一個(gè)預(yù)處理,也可以在這個(gè)方法中進(jìn)行一些判斷來決定請(qǐng)求是否要繼續(xù)進(jìn)行下去。該方法的返回值是布爾值Boolean類型的,當(dāng)它返回為false 時(shí),表示請(qǐng)求結(jié)束,后續(xù)的Interceptor 和Controller 都不會(huì)再執(zhí)行;當(dāng)返回值為true 時(shí)就會(huì)繼續(xù)調(diào)用下一個(gè)Interceptor 的preHandle 方法,如果已經(jīng)是最后一個(gè)Interceptor 的時(shí)候就會(huì)是調(diào)用當(dāng)前請(qǐng)求的Controller 方法。

            3)  postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法  【前提:在當(dāng)前所屬的Interceptor 的preHandle 方法的返回值為true 時(shí)才能被調(diào)用】

              在當(dāng)前請(qǐng)求進(jìn)行處理之后,也就是Controller 方法調(diào)用之后執(zhí)行,但是它會(huì)在DispatcherServlet 進(jìn)行視圖返回渲染之前被調(diào)用,所以我們可以在這個(gè)方法中對(duì)Controller 處理之后的ModelAndView 對(duì)象進(jìn)行操作。postHandle 方法被調(diào)用的方向跟preHandle 是相反的,也就是說先聲明的Interceptor 的postHandle 方法反而會(huì)后執(zhí)行,這和Struts2 里面的Interceptor 的執(zhí)行過程有點(diǎn)類型。Struts2 里面的Interceptor 的執(zhí)行過程也是鏈?zhǔn)降模皇窃赟truts2 里面需要手動(dòng)調(diào)用ActionInvocation 的invoke 方法來觸發(fā)對(duì)下一個(gè)Interceptor 或者是Action 的調(diào)用,然后每一個(gè)Interceptor 中在invoke 方法調(diào)用之前的內(nèi)容都是按照聲明順序執(zhí)行的,而invoke 方法之后的內(nèi)容就是反向的。  

            4)afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)方法  【前提:在當(dāng)前所屬的Interceptor 的preHandle 方法的返回值為true 時(shí)才能被調(diào)用】

              該方法將在整個(gè)請(qǐng)求結(jié)束之后,也就是在DispatcherServlet 渲染了對(duì)應(yīng)的視圖之后執(zhí)行。這個(gè)方法的主要作用是用于進(jìn)行資源清理工作的?! ?/span>

          五、單個(gè)攔截器(Interceptor)的Demo實(shí)現(xiàn)

            1)初始化攔截器

          @Component
          public class UserAccessInterceptor implements HandlerInterceptor {

              private final Logger logger = LoggerFactory.getLogger(UserAccessInterceptor.class);

              @Resource
              private UserService userService;

              @Override
              public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
                  //1.獲取headers里的author-Cookie
               //2.根據(jù)cookie使用userService查找當(dāng)前user
               //3.存在且激活 當(dāng)前用戶信息設(shè)置到ThreadLocal return true;
               //4.不存在 或 未激活 return false;
              }

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

              @Override
              public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
                  //銷毀ThreadLocal的用戶信息
              }

            2)攔截器配置類

          @Configuration
          public class WebInterceptorConfig extends WebMvcConfigurationSupport {

              @Autowired
              private UserAccessInterceptor userAccessInterceptor;

            //不攔截的URL集合
              private static List<String> exclusionUrlList=new ArrayList<>();

              static {
                  exclusionUrlList.add("/favicon.ico");
                  exclusionUrlList.add("/**/*.css");
                  exclusionUrlList.add("/**/*.js");
                  exclusionUrlList.add("/ok");
                  exclusionUrlList.add("/");
                  exclusionUrlList.add("/console/**");
                  exclusionUrlList.add("/index");
              }

              @Override
              protected void addInterceptors(InterceptorRegistry registry
          {
                  registry.addInterceptor(this.userAccessInterceptor)
                          .addPathPatterns("/**")
                          .excludePathPatterns(exclusionUrlList);
                  super.addInterceptors(registry);
              }

          }

          六、攔截器(Interceptor)的兩種配置方式

            1)同上 -> Demo實(shí)現(xiàn)

            2)Spring MVC使用mvc:interceptors標(biāo)簽

          <mvc:interceptors>  
          <!-- 使用bean定義一個(gè)Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請(qǐng)求 -->  
          <bean class="com.baidu.interceptor.UserAccessInterceptor"/>  
              <mvc:interceptor>  
                   <mvc:mapping path="/**"/>  
                   <mvc:exclude-mapping path="/parent/**"/>  
                   <bean class="com.baidu.interceptor.UserAccessInterceptor" />  
              </mvc:interceptor>  
          </mvc:interceptors>

          七、過濾器(Filter)的基本定義

            Filter可以認(rèn)為是Servlet的一種“加強(qiáng)版”,它主要用于對(duì)用戶請(qǐng)求進(jìn)行預(yù)處理,也可以對(duì)HttpServletResponse進(jìn)行后處理,是個(gè)典型的處理鏈。Filter也可以對(duì)用戶請(qǐng)求生成響應(yīng),這一點(diǎn)與Servlet相同,但實(shí)際上很少會(huì)使用Filter向用戶請(qǐng)求生成響應(yīng)。使用Filter完整的流程是:Filter對(duì)用戶請(qǐng)求進(jìn)行預(yù)處理,接著將請(qǐng)求交給Servlet進(jìn)行處理并生成響應(yīng),最后Filter再對(duì)服務(wù)器響應(yīng)進(jìn)行后處理。

            在Web中稱之為Filter,通過配置多個(gè)過濾器,Web系統(tǒng)可以對(duì)所有的Servlet請(qǐng)求進(jìn)行一層一層的過濾,以完成一些特殊的功能。例如常用的資源訪問權(quán)限控制、特殊字符以及敏感詞過濾、響應(yīng)信息壓縮等功能。

            Servlet中的過濾器Filter是實(shí)現(xiàn)了javax.servlet.Filter接口的服務(wù)器端程序,主要的用途是設(shè)置字符集、控制權(quán)限、控制轉(zhuǎn)向、做一些業(yè)務(wù)邏輯判斷等。其工作原理是,只要你在web.xml文件配置好要攔截的客戶端請(qǐng)求,它都會(huì)幫你攔截到請(qǐng)求,此時(shí)你就可以對(duì)請(qǐng)求或響應(yīng)(Request、Response)統(tǒng)一設(shè)置編碼,簡(jiǎn)化操作;同時(shí)還可進(jìn)行邏輯判斷,如用戶是否已經(jīng)登陸、有沒有權(quán)限訪問該頁(yè)面等等工作。它是隨你的web應(yīng)用啟動(dòng)而啟動(dòng)的,只初始化一次,以后就可以攔截相關(guān)請(qǐng)求,只有當(dāng)你的web應(yīng)用停止或重新部署的時(shí)候才銷毀。

          八、過濾器(Filter)必須實(shí)現(xiàn)的三個(gè)方法

            1)總覽

            2)default void init(FilterConfig filterConfig) throws ServletException {}

              用于完成Filter的初始化?!   ?/span>

            3)void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

              實(shí)現(xiàn)過濾功能,該方法就是對(duì)每個(gè)請(qǐng)求及響應(yīng)增加的額外處理。該方法可以實(shí)現(xiàn)對(duì)用戶請(qǐng)求進(jìn)行預(yù)處理(ServletRequest request),也可實(shí)現(xiàn)對(duì)服務(wù)器響應(yīng)進(jìn)行后處理(ServletResponse response)—它們的分界線為是否調(diào)用了chain.doFilter(),執(zhí)行該方法之前,即對(duì)用戶請(qǐng)求進(jìn)行預(yù)處理;執(zhí)行該方法之后,即對(duì)服務(wù)器響應(yīng)進(jìn)行后處理。

            4)  default void destroy() {}

              用于Filter銷毀前,完成某些資源的回收。

          九、單個(gè)過濾器(Filter)的Demo實(shí)現(xiàn)

            1)TestFilter初始化

          public class TestFilter implements Filter {
              @Override
              public void init(FilterConfig filterConfig) throws ServletException {

              }

              @Override
              public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
                  System.out.println("我是Filter,執(zhí)行filterChain.doFilter(request,response)之前。");
                  filterChain.doFilter(request,response);
                  System.out.println("我是Filter,執(zhí)行filterChain.doFilter(request,response)之后。");
              }

              @Override
              public void destroy() {

              }

            2)Filter配置類

          @Slf4j
          @Configuration
          public class TestFilterConfiguration {//不攔截路徑
              private static List<String> exclusionUrlList=new ArrayList<>();
              //攔截路徑
              private static List<String> inclusionUrlList=new ArrayList<>();

              static {
                  exclusionUrlList.add("/favicon.ico");
                  exclusionUrlList.add("/**/*.css");
                  exclusionUrlList.add("/**/*.js");
                  exclusionUrlList.add("/ok");
                  inclusionUrlList.add("/api/**");
              }

              @Bean
              public FilterRegistrationBean filterRegistration() 
          {
                  FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
                  registration.setFilter(new TestFilter());
                  registration.addInitParameter(FILTER_INIT_PARAM_EXCLUSION_URLS,String.join(",", exclusionUrlList));
                  registration.addInitParameter(AJAX_URL_PATTERNS,String.join(",", inclusionUrlList));
                  registration.addUrlPatterns("/*");
                  registration.setName("testFilter");
               return registration;
              }

          }

          十、過濾器(Filter)的三種配置方式

            1)通過@WebFilter注解配置

          1.初始化Filter

          @WebFilter(urlPatterns = "/test001")
          @Order(1//order值越小,過濾器越靠前,此處配置無效
          public class TestFilter implements Filter {
              @Override
              public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
                  System.out.println("##############TestFilter init##############");
              }

              @Override
              public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                  //在DispatcherServlet之前執(zhí)行
                  System.out.println("##############doFilter before##############");
                  filterChain.doFilter(servletRequest, servletResponse);
                  // 在視圖頁(yè)面返回給客戶端之前執(zhí)行,但是執(zhí)行順序在Interceptor之后
                  System.out.println("##############doFilter after##############");
              }

              @Override
              public void destroy() {
                  System.out.println("##############TestFilter destroy##############");
              }
          }

          //2.在啟動(dòng)類添加 @ServletComponentScan

          @SpringBootApplication 
          @ServletComponentScan 
          public class TestbootApplication 
            public static void main(String[] args) 
              SpringApplication.run(TestbootApplication.class, args); 
            } 
          }

            2)通過@Bean來配置

          //1.初始化Filter

          @Component
          public class TestFilter3 implements Filter{
              @Override
              public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
                  System.out.println("##############Filter3 init##############");
              }

              @Override
              public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                  //在DispatcherServlet之前執(zhí)行
                  System.out.println("##############doFilter3 before##############");
                  filterChain.doFilter(servletRequest, servletResponse);
                  // 在視圖頁(yè)面返回給客戶端之前執(zhí)行,但是執(zhí)行順序在Interceptor之后
                  System.out.println("##############doFilter3 after##############");
              }

              @Override
              public void destroy() {
                  System.out.println("##############Filter3 destroy##############");
              }
          }


          //2.注冊(cè)到config

          @Configuration
          public class FilterConfig {

              @Bean
              public FilterRegistrationBean testFilter3RegistrationBean() {
                  FilterRegistrationBean registration = new FilterRegistrationBean(new TestFilter3());
                  registration.addUrlPatterns("/hello");
                  registration.setOrder(1); // 值越小越靠前,此處配置有效
                  return registration;
              }

              @Bean
              public FilterRegistrationBean testFilter4RegistrationBean() {
                  FilterRegistrationBean registration = new FilterRegistrationBean(new TestFilter4());
                  registration.addUrlPatterns("/hello");
                  registration.setOrder(2);
                  return registration;
              }
          }

            3)Spring MVC在web.xml進(jìn)行配置

              1.初始化Filter

              2.web.xml文件中配置Filter

          <filter>
              <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
              <url-pattern>/*</url-pattern>
          </filter-mapping>

          十一、攔截器和過濾器的區(qū)別

          十二、攔截器和過濾器的作用/用途

            過濾器用途:用于設(shè)置字符編碼、URL級(jí)別的權(quán)限控制,敏感詞匯的過濾

            攔截器用途:攔截未登錄的用戶,攔截器和過濾器的功能相近

          十三、總結(jié)

            1.過濾器:所謂過濾器顧名思義是用來過濾的,在java web中,你傳入的request,response提前過濾掉一些信息,或者提前設(shè)置一些參數(shù),然后再傳入servlet或者struts的action進(jìn)行業(yè)務(wù)邏輯,比如過濾掉非法url(不是login.do的地址請(qǐng)求,如果用戶沒有登陸都過濾掉),或者在傳入servlet或者struts的action前統(tǒng)一設(shè)置字符集,或者去除掉一些非法字符(聊天室經(jīng)常用到的,一些罵人的話)。filter 流程是線性的, url傳來之后,檢查之后,可保持原來的流程繼續(xù)向下執(zhí)行,被下一個(gè)filter, servlet接收等.

            2.java的攔截器 主要是用在插件上,擴(kuò)展件上比如 hibernate spring struts2等 有點(diǎn)類似面向切片的技術(shù),在用之前先要在配置文件即xml文件里聲明一段的那個(gè)東西。

          source:https://www.cnblogs.com/l3306/p/14779295.html


          國(guó)產(chǎn)小眾瀏覽器因屏蔽視頻廣告,被索賠100萬(后續(xù))

          年輕人“不講武德”:因看黃片上癮,把網(wǎng)站和786名女主播起訴了

          中國(guó)聯(lián)通官網(wǎng)被發(fā)現(xiàn)含木馬腳本,可向用戶推廣色情APP

          張一鳴:每個(gè)逆襲的年輕人,都具備的底層能力


          關(guān)


          ,學(xué),西學(xué)學(xué)運(yùn)營(yíng)護(hù)號(hào),質(zhì),結(jié)識(shí),關(guān)[],學(xué)習(xí)進(jìn)!


          瀏覽 124
          點(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>
                  日本在线一级片 | 爽 好紧 别夹 喷水网站 | 日本在线播放 | 日韩午夜在线 | 婷婷aV无码|