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

          SpringBoot中filter的使用詳解及原理

          共 7434字,需瀏覽 15分鐘

           ·

          2020-11-02 05:06

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

          ? 作者?|??SUPERUSR

          來源 |? urlify.cn/nIrqyu

          66套java從入門到精通實(shí)戰(zhàn)課程分享

          ?首先還是老生常談,我先把SpringBoot中filter的使用示例寫出來,然后再解釋下代碼、說一下運(yùn)行的順序,最后講一下filter的原理(其實(shí)就是責(zé)任鏈設(shè)計(jì)模式,從馬士兵老師那里偷來的。。。)。

          ? ? ? ? 要想使用filter,需要寫一個(gè)方法繼承Filter類,我們寫如下兩個(gè)自己的Filter類,首先是FirstFilter類,其中@Order里邊的數(shù)字越小代表越先被該Filter過濾,@WebFilter代表這是個(gè)Filter類并把這個(gè)類注入到容器中:

          package?com.example.executor_test.filter;
          ?
          import?java.io.IOException;
          ?
          import?javax.servlet.Filter;
          import?javax.servlet.FilterChain;
          import?javax.servlet.FilterConfig;
          import?javax.servlet.ServletException;
          import?javax.servlet.ServletRequest;
          import?javax.servlet.ServletResponse;
          import?javax.servlet.annotation.WebFilter;
          ?
          import?org.springframework.core.annotation.Order;
          ?
          @Order(1)
          @WebFilter(filterName="firstFilter",?urlPatterns="/*")
          public?class?FirstFilter?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("first?filter?1");
          ????????chain.doFilter(request,?response);
          ????????System.out.println("first?filter?2");
          ????}
          ?
          ????@Override
          ????public?void?destroy()?{
          ????????
          ????}
          }

          ?然后是第二個(gè)Filter,SecondFilter類:

          package?com.example.executor_test.filter;
          ?
          import?java.io.IOException;
          ?
          import?javax.servlet.Filter;
          import?javax.servlet.FilterChain;
          import?javax.servlet.FilterConfig;
          import?javax.servlet.ServletException;
          import?javax.servlet.ServletRequest;
          import?javax.servlet.ServletResponse;
          import?javax.servlet.annotation.WebFilter;
          ?
          import?org.springframework.core.annotation.Order;
          ?
          @Order(2)
          @WebFilter(filterName="secondFilter",?urlPatterns="/*")
          public?class?SecondFilter?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("second?filter?1");
          ????????System.out.println("before:"?+?response);
          ????????chain.doFilter(request,?response);
          ????????System.out.println("after:"?+?response);
          ????????System.out.println("second?filter?2");
          ????????
          ????}
          ?
          ????@Override
          ????public?void?destroy()?{
          ????????
          ????}
          }

          然后我們把Controller類也寫出來吧:

          package?com.example.executor_test.controller;
          ?
          import?java.text.DateFormat;
          import?java.text.SimpleDateFormat;
          import?java.util.Date;
          ?
          import?javax.annotation.Resource;
          ?
          import?org.springframework.beans.factory.annotation.Autowired;
          import?org.springframework.web.bind.annotation.GetMapping;
          import?org.springframework.web.bind.annotation.RestController;
          ?
          import?com.example.executor_test.task.OldTask;
          import?com.example.executor_test.task.OldTaskThread;
          ?
          @RestController
          public?class?TestController?{
          ????
          ????@GetMapping("/test1")
          ????public?String?test1()?{
          ????????System.out.println("method?in?controller");
          ????????return?"test1";
          ????}
          ?
          }

          ? ? 最后是springboot的主方法入口,注意,由于我們使用注解注入的Filter,所以要在下邊這個(gè)Application類中加入@ServletComponentScan注解:

          package?com.example.executor_test;
          ?
          import?org.omg.CORBA.PRIVATE_MEMBER;
          import?org.springframework.beans.factory.annotation.Autowired;
          import?org.springframework.boot.SpringApplication;
          import?org.springframework.boot.autoconfigure.SpringBootApplication;
          import?org.springframework.boot.web.servlet.ServletComponentScan;
          import?org.springframework.context.ConfigurableApplicationContext;
          ?
          import?com.example.executor_test.task.OldTaskThread;
          ?
          @SpringBootApplication
          @ServletComponentScan
          public?class?ExecutorTestApplication?{
          ?
          ????public?static?void?main(String[]?args)?{????
          ????????ConfigurableApplicationContext?applicationContext?=?SpringApplication.run(ExecutorTestApplication.class,?args);
          ????}
          }

          ? 首先我們先來看一下執(zhí)行結(jié)果,啟動后訪問127.0.0.1:8080/test1,在后臺中打印如下信息:

          ?

          ?我們可以看出代碼執(zhí)行的流程,首先請求被firstfilter截獲,打印出first filter 1,然后去執(zhí)行chain.doFilter(request, response),這句話代表著請求會轉(zhuǎn)發(fā)給過濾器鏈上下一個(gè)對象,也就是secondfilter,所以打印出secondfilter里的second filter 1,接下來再執(zhí)行secondfilter里的chain.dofilter()方法,請求再轉(zhuǎn)發(fā)給下一個(gè)對象,由于沒有其他的filter了,所以會轉(zhuǎn)發(fā)給controller,打印出了controller類中的method in controller,接下來再去內(nèi)存棧里調(diào)用secondfilter的print("second filter 2"),然后再去內(nèi)存棧里調(diào)用firstfilter的print("first filter 1")。所以如果在自己實(shí)現(xiàn)的Filter類的doFilter方法里不加chain.doFilter(req, rep)是萬萬不行的,那樣會導(dǎo)致請求到了這個(gè)filter里就不再往下走了,永遠(yuǎn)進(jìn)不了controller中。

          ? ? ? ? 我們也可以在print("before:" + response)和print("after:" + response)這兩個(gè)地方打上斷點(diǎn),然后調(diào)試一下,你會發(fā)現(xiàn)在before那里的response里是什么都么有的,而在after那里的response里則是已經(jīng)有了test1字符串,也就是說controller類test1方法的返回值已經(jīng)添加進(jìn)了response,所以如果你想對請求的response做一下過濾處理,那么一定要在chain.doFilter(res, rep)之后寫你的邏輯。

          ? ? ? ? 接下來講一下這個(gè)Filter和FilterChain都是怎么用責(zé)任鏈模式實(shí)現(xiàn)的,如果不太需要了解原理的話,往下的部分就可以不看了。。。好了,我們來模擬一下簡單的實(shí)現(xiàn)SpringBoot中的Filter接口和FilterChain類:

          首先是我們自己寫的Filter接口,里邊就一個(gè)doFilter方法:

          package?filterchain_pattern;

          public?interface?Filter?{

          public?void?doFilter(Request?request,?Response?response,?FilterChain?chain);

          }

          接下來是我們自己寫的FilterChain類:

          package?filterchain_pattern;
          ?
          ?
          ?
          import?java.util.ArrayList;
          ?
          import?java.util.List;
          ?
          ?
          ?
          public?class?FilterChain?implements?Filter?{
          ?
          ?
          ?
          private?List?filters?=?new?ArrayList<>();
          ?
          int?index?=?0;
          ?
          ?
          ?
          public?FilterChain?addFilter(Filter?filter)?{
          ?
          filters.add(filter);
          ?
          return?this;
          ?
          }
          ?
          ?
          ?
          @Override
          ?
          public?void?doFilter(Request?request,?Response?response,?FilterChain?chain)?{
          ?
          ?
          ?
          if(index?==?filters.size())?{
          ?
          return;
          ?
          }
          ?
          Filter?filter?=?filters.get(index);
          ?
          index++;
          ?
          filter.doFilter(request,?response,?chain);
          ?
          }
          ?
          ?
          ?
          }


          接下來模擬Request類和Response類:

          package?filterchain_pattern;
          ?
          ?
          ?
          public?class?Request?{
          ?
          ?
          ?
          public?String?requestStr;
          ?
          ?
          ?
          }
          package?filterchain_pattern;
          ?
          ?
          ?
          public?class?Response?{
          ?
          ?
          ?
          public?String?responseStr;
          ?
          ?
          ?
          }

          然后我們下一個(gè)Filter接口的實(shí)現(xiàn)類HTMLFilter類,該類會將requestStr中的<>替換成[],并給responseStr添加------------HTML response filter字符串,并在控制臺打印出來:

          package?filterchain_pattern;
          ?
          ?
          ?
          public?class?HTMLFilter?implements?Filter?{
          ?
          ?
          ?
          @Override
          ?
          public?void?doFilter(Request?request,?Response?response,?FilterChain?chain)?{
          ?
          request.requestStr?=?request.requestStr.replace("<",?"[").replace(">",?"]")?+?"--------HTML?Request?Filter";
          ?
          System.out.println("HTML?Filter?request?Str:"?+?request.requestStr);
          ?
          chain.doFilter(request,?response,?chain);
          ?
          response.responseStr?=?response.responseStr?+?"-------------HTML?response?filter";
          ?
          System.out.println("HTML?Filter?response?Str:"?+?response.responseStr);
          ?
          }
          ?
          }


          然后是另外一個(gè)Filter接口的實(shí)現(xiàn)類SensitiveFilter類, 該類會給requestStr添加一段字符串,給responseStr添加一段字符串,并在控制臺打印出來:

          package?filterchain_pattern;
          ?
          ?
          ?
          public?class?SensitiveFilter?implements?Filter?{
          ?
          ?
          ?
          @Override
          ?
          public?void?doFilter(Request?request,?Response?response,?FilterChain?chain)?{
          ?
          request.requestStr?=?request.requestStr?+?"---------------Sensitive?request?Filter";
          ?
          System.out.println("sensitiveFilter?request?str:"?+?request.requestStr);
          ?
          chain.doFilter(request,?response,?chain);
          ?
          response.responseStr?=?response.responseStr?+?"---------------------sensitive?response?filter";
          ?
          System.out.println("sensitiveFilter?response?str:"?+?response.responseStr);
          ?
          }
          ?
          ?
          ?
          }


          最后使我們的Main方法類:

          package?filterchain_pattern;
          ?
          ?
          ?
          public?class?MainTest?{
          ?
          ?
          ?
          public?static?void?main(String[]?args)?{
          ?
          ?
          ?
          String?msg?=?"testMsg";
          ?
          Request?request?=?new?Request();
          ?
          request.requestStr?=?msg;
          ?
          Response?response?=?new?Response();
          ?
          response.responseStr?=?"responseStr";
          ?
          ?
          ?
          FilterChain?fc?=?new?FilterChain();
          ?
          fc.addFilter(new?HTMLFilter()).addFilter(new?SensitiveFilter());
          ?
          fc.doFilter(request,?response,?fc);
          ?
          ?
          ?
          }
          ?
          ?
          ?
          }


          打印結(jié)果如下,這就是責(zé)任鏈模式的實(shí)際應(yīng)用了:





          粉絲福利:實(shí)戰(zhàn)springboot+CAS單點(diǎn)登錄系統(tǒng)視頻教程免費(fèi)領(lǐng)取

          ???

          ?長按上方微信二維碼?2 秒
          即可獲取資料



          感謝點(diǎn)贊支持下哈?

          瀏覽 43
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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中文 | 99精品全国免费观看 | 国产午夜在线 | 护士AV无码A片在线观看 | 国产无遮挡又黄又爽在线观看 |