1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        SpringBoot中filter的使用詳解及原理

        共 7434字,需瀏覽 15分鐘

         ·

        2020-11-02 05:06

        點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hà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é)果,啟動(dòng)后訪問127.0.0.1:8080/test1,在后臺(tái)中打印如下信息:

        ?

        ?我們可以看出代碼執(zhí)行的流程,首先請(qǐng)求被firstfilter截獲,打印出first filter 1,然后去執(zhí)行chain.doFilter(request, response),這句話代表著請(qǐng)求會(huì)轉(zhuǎn)發(fā)給過濾器鏈上下一個(gè)對(duì)象,也就是secondfilter,所以打印出secondfilter里的second filter 1,接下來再執(zhí)行secondfilter里的chain.dofilter()方法,請(qǐng)求再轉(zhuǎn)發(fā)給下一個(gè)對(duì)象,由于沒有其他的filter了,所以會(huì)轉(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)是萬萬不行的,那樣會(huì)導(dǎo)致請(qǐng)求到了這個(gè)filter里就不再往下走了,永遠(yuǎn)進(jìn)不了controller中。

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

        ? ? ? ? 接下來講一下這個(gè)Filter和FilterChain都是怎么用責(zé)任鏈模式實(shí)現(xiàn)的,如果不太需要了解原理的話,往下的部分就可以不看了。。。好了,我們來模擬一下簡(jiǎ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類,該類會(huì)將requestStr中的<>替換成[],并給responseStr添加------------HTML response filter字符串,并在控制臺(tái)打印出來:

        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類, 該類會(huì)給requestStr添加一段字符串,給responseStr添加一段字符串,并在控制臺(tái)打印出來:

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

        ???

        ?長(zhǎng)按上方微信二維碼?2 秒
        即可獲取資料



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

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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            噜噜私人影院 | 国产伦子伦视频在线观看 | 久久久久久久久免费视频 | 精品人妻无码一区二区三区电影 | 欧美老妇高潮潮喷视频 | 孕妇裸体网站 | 天天操综合视频 | 色天堂综合| 黄色小说在线读 | 国产久久久久久久久 |