1. 手寫web服務(wù)器:實(shí)現(xiàn)簡單filter攔截邏輯

        共 6351字,需瀏覽 13分鐘

         ·

        2021-06-12 06:33

        前言

        今天早上起床的時(shí)候,我還在想應(yīng)該實(shí)現(xiàn)哪個(gè)組件,想了半天,發(fā)現(xiàn)基本上常用的注解組件都被我們給實(shí)現(xiàn)了(當(dāng)然,雖然都實(shí)現(xiàn)了,但是基本上都是簡易版),最后想來想去覺得filter可以實(shí)現(xiàn)下,畢竟沒有這個(gè)模塊,項(xiàng)目中的就沒法實(shí)現(xiàn)權(quán)限控制了。

        在開始的時(shí)候,我已經(jīng)知道filter的難點(diǎn)是地址的匹配,也就是如何把我們配置的地址轉(zhuǎn)換為正則表達(dá)式,最后發(fā)現(xiàn)這塊涉及的知識(shí)點(diǎn)有點(diǎn)多,所以今天就只演示通配地址,即/*

        好了,我們一起來看下吧。

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

        定義注解

        這里依然很輕車熟路,注解的配置我增加了很多屬性,最核心的就是urlPatterns,也就是我們的攔截地址。

        @Target(ElementType.TYPE)
        @Retention(RetentionPolicy.RUNTIME)
        public @interface WebFilter {
            String[] value() default {};

            String description() default "";

            String displayName() default "";

            String[] urlPatterns() default {};
        }

        定義Filter接口

        這里參考了javaEEfilter接口

        public interface Filter {
            default void init() {}

            void doFilter(Request request, Response response, FilterChain filterChain) throws IOException;

            default void destrory() {}
        }

        public interface FilterChain {
            /**
             * filter調(diào)用鏈
             * @param request
             * @param response
             * @throws IOException
             */

            void doFilter(Request request, Response response) throws IOException;
        }

        定義filter

        加上webFilter,并配置攔截地址,實(shí)現(xiàn)doFilter方法

        @WebFilter(urlPatterns = {"/*"}, description = "test filter")
        public class TestFilter implements Filter{
            @Override
            public void doFilter(Request request, Response response, FilterChain filterChain) throws IOException {
                System.out.println(String.format("過濾器TestFilter被訪問,攔截地址:%s", request.getRequestHear().getRequestMapping()));
                if (Objects.nonNull(filterChain)) {
                    filterChain.doFilter(request, response);
                }
            }
        }

        過濾器初始化

        這里主要是配合IoC,拿到過濾器的配置信息,并實(shí)例化filter

        private static Map<Filter, String[]> filterUrlPatternsMap = Maps.newHashMap();

            private static LinkedList<Filter> filterLinkedList = Lists.newLinkedList();

            public static Map<Filter, String[]> getFilterUrlPatternsMap() {
                return filterUrlPatternsMap;
            }

            public static LinkedList<Filter> getFilterLinkedList() {
                return filterLinkedList;
            }

            public static void init(Class zClass) throws IllegalAccessException, InstantiationException {
                Annotation webFilter = zClass.getAnnotation(WebFilter.class);
                if (Objects.nonNull(webFilter)) {
                    String[] urlPatterns = ((WebFilter) webFilter).urlPatterns();
                    Filter filter = (Filter)zClass.newInstance();
                    filterUrlPatternsMap.put(filter, urlPatterns);
                    filterLinkedList.add(filter);
                }
            }

        修改disPatcher方法

        這里就是對(duì)請(qǐng)求地址進(jìn)行過濾,當(dāng)匹配到請(qǐng)求時(shí),執(zhí)行匹配到過濾器的doFilter方法

        Map<Filter, String[]> filterUrlPatternsMap = FilterHandler.getFilterUrlPatternsMap();
                    LinkedList<Filter> filterLinkedList = FilterHandler.getFilterLinkedList();
                    ListIterator<Filter> filterListIterator = filterLinkedList.listIterator();
                    while (filterListIterator.hasNext()) {
                        Filter filter = filterListIterator.next();
                        String[] values = filterUrlPatternsMap.get(filter);
                        for (String value : values) {
                            if(Pattern.matches(value.replace('/''.'), requestMapping)) {
                                filter.doFilter(request, response, null);
                            }

                        }
                    }

        測(cè)試

        我們用瀏覽器訪問任意地址,比如/testAutowire,會(huì)看到doFilter方法被執(zhí)行了,控制臺(tái)打印如下信息:

        說明,我們的filter已經(jīng)起作用了,是不是很簡單呀。

        總結(jié)

        雖然filter的核心功能實(shí)現(xiàn)了,但作為一個(gè)合格的web服務(wù)器,攔截器也得夠健壯,夠靈活,所以還有很多工作要做:

        比如要實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,就是實(shí)現(xiàn)多個(gè)過濾器的順序調(diào)用,層層調(diào)用,層層返回,形成調(diào)用鏈,這一塊后面要進(jìn)一步實(shí)現(xiàn);

        另外一個(gè)問題就是,我們要實(shí)現(xiàn)更靈活的地址匹配,前面我也說了,目前的地址只實(shí)現(xiàn)了通配和嚴(yán)格匹配兩種,正則表達(dá)式支持的也不夠完美,這一塊也是后面要優(yōu)化的點(diǎn)。

        好了,核心內(nèi)容到這里就結(jié)束了,但我想說兩句閑話,這兩天在刷一個(gè)制作精良的劇——《覺醒年代》,這應(yīng)該是這幾年,我看過最有價(jià)值的電視劇了,讓我對(duì)很多革命先烈有了更深刻的認(rèn)識(shí),有興趣的小伙伴可以去看下,真的很贊。

        下面是項(xiàng)目的開源倉庫,有興趣的小伙伴可以去看看,如果有想法的小伙伴,我真心推薦你自己動(dòng)個(gè)手,自己寫一下,真的感覺不錯(cuò):

        https://github.com/Syske/syske-boot
        - END -


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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. av国产av一区二区三区 | 深夜办公室老板揉我胸摸下边 | 国产成人一级 | 少妇不卡视频 | 日韩美女在线观看 |