1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

手写web服务器:实现简单filter逻辑

前言

今天早上起床的时候,我还在想应该实现哪个组件,想了半天,发现基本上常用的注解组件都被我们給实现了(当然,虽然都实现了,但是基本上都是简易版),最后想来想去觉得filter可以实现下,毕竟没有这个模块,项目中的就没法实现权限控制了。

在开始的时候,我已经知道filter的难点是地址的匹配,也就是如何把我们配置的地址转换为正则表达式,最后发现这块涉及的知识点有点多,所以今天就只演示通配地址,即/*

好了,我们一起来看下吧。

过滤器实现过程

定义注解

这里依然很轻车熟路,注解的配置我增加了很多属性,最核心的就是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调用链
     * @param request
     * @param response
     * @throws IOException
     */
    void doFilter(Request request, Response response) throws IOException;
}

定义filter

加上webFilter,并配置拦截地址,实现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,拿到过滤器的配置信息,并实例化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方法

这里就是对请求地址进行过滤,当匹配到请求时,执行匹配到过滤器的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);
                    }

                }
            }

测试

我们用浏览器访问任意地址,比如/testAutowire,会看到doFilter方法被执行了,控制台打印如下信息:

说明,我们的filter已经起作用了,是不是很简单呀。

总结

虽然filter的核心功能实现了,但作为一个合格的web服务器,拦截器也得够健壮,够灵活,所以还有很多工作要做:

比如要实现链式调用,就是实现多个过滤器的顺序调用,层层调用,层层返回,形成调用链,这一块后面要进一步实现;

另外一个问题就是,我们要实现更灵活的地址匹配,前面我也说了,目前的地址只实现了通配和严格匹配两种,正则表达式支持的也不够完美,这一块也是后面要优化的点。

好了,核心内容到这里就结束了,但我想说两句闲话,这两天在刷一个制作精良的剧——《觉醒年代》,这应该是这几年,我看过最有价值的电视剧了,让我对很多革命先烈有了更深刻的认识,有兴趣的小伙伴可以去看下,真的很赞。

下面是项目的开源仓库,有兴趣的小伙伴可以去看看,如果有想法的小伙伴,我真心推荐你自己动个手,自己写一下,真的感觉不错:

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

posted @ 2021-06-11 08:03  云中志  阅读(88)  评论(0编辑  收藏  举报