WEB三大组件之Filter

03-19 1937阅读 0评论

在很多项目中通常需要用到filter来实现用户身份识别,并将识别出来的用户信息,保存到ThreadLocal对应的上下文,这样在后续的请求链路中,在任何地方都可以直接获取当前的登录用户了。

WEB三大组件之Filter,WEB三大组件之Filter,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,注册,第1张
(图片来源网络,侵删)

来看一下Java WEB三大组件之一的过滤器Filter,是如何在技术派中发挥作用的

使用场景

实现类路径:com/github/paicoding/forum/web/hook/filter/ReqRecordFilter.java

WEB三大组件之Filter

1.Filter基础知识点

来了解一下Filter的基础把。

WEB三大组件之Filter

WEB三大组件之Filter,WEB三大组件之Filter,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,注册,第4张
(图片来源网络,侵删)

Filter称为过滤器,主要用来拦截http请求,来做一些其他的事情

流程说明

一个http请求过来之后

  •         首先进入filter,执行相关的业务逻辑
  •         若判定通行,则进入Servlet逻辑,Servlet执行完毕后,又返回Filter,最后在返回给请求方
  •         判定失败,直接返回,不需要将请求发给Servlet

    应用场景

    通过上面的流程,可以推算下具体的使用场景:

    •         在filter层,来获取用户的身份
    •         可以考虑在filter层做一些常规的校验(如参数校验。referer校验、权限控制等)
    •         可以在filter层做运维、安全防护相关的工作(如全链路打点,可以在filter层分配一个traceId;也可以在这一层做限流等)

      2. 实现说明:

      filter的基本使用比较简单,实现Filter接口即可,如;

      @Slf4j
      @WebFilter(urlPatterns = "/*", filterName = "reqRecordFilter", asyncSupported = true)
      public class ReqRecordFilter implements Filter {
          private static Logger REQ_LOG = LoggerFactory.getLogger("req");
          /**
           * 返回给前端的traceId,用于日志追踪
           */
          private static final String GLOBAL_TRACE_ID_HEADER = "g-trace-id";
          @Autowired
          private GlobalInitService globalInitService;
          @Autowired
          private StatisticsSettingService statisticsSettingService;
          @Override
          public void init(FilterConfig filterConfig) {
          }
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              long start = System.currentTimeMillis();
              HttpServletRequest request = null;
              StopWatch stopWatch = new StopWatch("请求耗时");
              try {
                  stopWatch.start("请求参数构建");
                  request = this.initReqInfo((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
                  stopWatch.stop();
                  stopWatch.start("cors");
                  CrossUtil.buildCors(request, (HttpServletResponse) servletResponse);
                  stopWatch.stop();
                  stopWatch.start("业务执行");
                  filterChain.doFilter(request, servletResponse);
                  stopWatch.stop();
              } finally {
                  stopWatch.start("输出请求日志");
                  buildRequestLog(ReqInfoContext.getReqInfo(), request, System.currentTimeMillis() - start);
                  // 一个链路请求完毕,清空MDC相关的变量(如GlobalTraceId,用户信息)
                  MdcUtil.clear();
                  ReqInfoContext.clear();
                  stopWatch.stop();
                  if (!isStaticURI(request) && !EnvUtil.isPro()) {
                      log.info("{} - cost:\n{}", request.getRequestURI(), stopWatch.prettyPrint(TimeUnit.MILLISECONDS));
                  }
              }
          }
          @Override
          public void destroy() {
          }
      

      上面有三个方法:

      •         init: 初始化执行
      •         destory: 销毁时执行
      •         dofilter: 重点关注这个,filter规则命中请求,都会走进来

                        三个参数,注意第三个FilterChain,这里是经典的责任链模式

        WEB三大组件之Filter,WEB三大组件之Filter,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,注册,第5张
        (图片来源网络,侵删)

                        执行filterChain.doFilter(request, servletResponse); 表示会继续将请求执行下去;若不执行这一句,表示这一次的http请求到此为止,后面免得不走下去了。

        3.filter注册

        过滤注册到Spring容器有多种使用姿势,除上面使用的@WebFilter之外还有其他的使用姿势。

        3.1 WebFilter注解

        使用WebFilter注解,标注到实现自己额的过滤器上,有几个参数需要注意,其中urlPatterns最为常用,表示这个filter使用与那些url请求(默认场景下全部都被拦截)

        属性名 

        类型

        描述

        filterNameString指定过滤器的name属性,等价于

        value

        String[]该属性等价于urlPatterns属性。但是两者不应该同时使用。
        urlPatternsString[]指定一组过滤器的URL匹配模式。等价于标签
        servletNamesString[]

        指定过滤器将应用于哪些Servlet。取值是@WebServlet中的name属性的取值,或者是web.xml中的取值

        dispatcherTypesDispatcherTypes指定过滤器的转发模式。具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST
        initParamsWebInitParm[]指定一组过滤器初始化参数。等价于标签
        asyncSupportedboolean声明过滤器是否支持异步操作模式,等价于标签
        descriptionString该过滤器的描述信息,等价于
        displayNameString该过滤器的显示名,通常配合工具使用,等价于

        使用这个注解时,请注意,需要在启动类/配置类添加@ServletComponentScan注解来启用

        如:

        WEB三大组件之Filter

        3.2 FilterRegistrationBean

        上面这一种比较简单,但是再指定Filter的优先级的时候比较麻烦,不如下面这种方式简单

        WEB三大组件之Filter

        4.实例说明

        接下来我们看一下,filter在技术派中的具体表现,干了那几件事:

        身份识别 ,并保存身份到ReqInfoContext上下文中:

        WEB三大组件之Filter

        WEB三大组件之Filter

        记录请求记录:

        Filter实现请求日志记录-CSDN博客等。

        请求日志的case:

        WEB三大组件之Filter

        小结

        1. Filter使用

        自定义Filter的实现

                实现Filter接口

                doFilter方法中,显示调用chain.doFilter(request , response); 表示请求继续;否则表示请求被过滤。

        注册生效

        @ServletComponentScan自动扫描带有@WebFilter注解的Filter

        创建Bean: FilterRegistrationBean来包装自定义的Filter

        2. IoC/DI

        在SpringBoot中Filter可以和一般的Bean一样使用,直接通过Autowired注入其依赖的Spring Bean对象。

        3.优先级

        通过创建FilterRegistrationBean的时候指定优先级,如下

        WEB三大组件之Filter

        此外注意,@WebFilter申明的Filter,优先级为2147483647(优先级最低)

        @Order注解不能指定Filter优先级


免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,1937人围观)

还没有评论,来说两句吧...

目录[+]