@WebFilter和@Component一起使用导致urlPatterns不起作用

  • @WebFilter和@Component
    • @WebFilter
    • @Component
    • 采坑记录

@WebFilter和@Component

本文你主要讲解@WebFilter注解和@Component以及在使用过程中遇到的坑

@WebFilter

1.基本概念:
@WebFilter用于将一个类声明为过滤器,该注解将会在部署时候被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。该注解具有下表给出的常用属性(以下所有属性均为可选属性,但是value、urlPatterns、servletNames三者必须至少包含一个,且value和urlPatterns不能共存,如果同同时制定,通常忽略value的值)

属性名 类型 描述
filterName String 指定过滤器的name属性,等价于< filter-name>
value String[] 该属性等价于urlPatterns属性,但是两个不应该同时使用
urlPatterns String[] 指定一组过滤器的URL匹配模式。等价于< url-pattern>
sevletNames String[] 指定过滤器将用于哪些servlet。取值是@WebServlet中的name属性的取值,或者是web.xml中< servlet-name>
dispatcherTypes DispatcheType 指定过滤器的转发模式。具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST
initParams WebInitParam[] 指定一组过滤器初始化参数,等价于< init-param>
asyncSupported boolean 声明过滤器是否支持异步操作模式,等价于< async-supported>标签
description String 该过滤器的描述信息,等价于< description>
displayName String 该过滤器的显示名,通常配合工具使用,等价于< display-name>

2.正确示例:
a.过滤器如下

@WebFilter(filterName = "useTokenRequestFilter", urlPatterns = {"/v1/quote/*"})
public class MyFilter implements Filter{@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {//TODOchain.doFilter(req, resp);}@Overridepublic void destroy() {}
}

b.在启动类添加@ServletComponentScan

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableAspectJAutoProxy
@EnableDiscoveryClient
@ServletComponentScan(basePackages = {"填写自己的过滤器包名"})
@EnableFeignClients
@EnableCaching
public class123Application {public static void main(String[] args) {System.setProperty("com.alibaba.nacos.client.naming.tls.enable","true");SpringApplication.run(OrderServiceApplication.class);}
}

@Component

@component: 标注一个类为Spring容器的Bean,(把普通pojo实例化到spring容器中,相当于配置文件中的)

采坑记录

由于业务需要使用Filter。大体逻辑如下:
①通过WebFilter进行Filter声明,这样容器在进行部署的时候就会处理该Filter,创建实例并创建配置对象FilterConfig,然后会将该Filter应用到urlPatterns所指定的url;
②在init方法中获取到初始化参数,自定义的excludedUrls,作为成员在后续执行过滤逻辑的时候使用;
③在doFilter中进行url的鉴定,如果需要执行认证鉴权处理,则执行相应逻辑。不满足条件的情况下重定向到登录页;
④Filter类增加Component注解,让该Filter被容器管理。
问题就出在第一步和第四步。urlPatterns指定的URL不起作用,所有的请求都会经过过滤器,

@Component
@WebFilter(filterName = "1212121", urlPatterns = {"/v1/9874/*"})
public class MyFilter implements Filter{@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {//TODOchain.doFilter(req, resp);}@Overridepublic void destroy() {}
}

然后在SpringBoot的Application中增加注解@ServletComponentScan,这样容器会扫描到@Component注解的Filter。

问题出现

出现的问题是:访问的url为/user/*或者/product/*的时候,该过滤器也执行了!
也就是说,WebFilter注解配置的urlPatterns没有起作用。

问题定位:
在查看容器启动日志的时候,发现WebAuthFilter被两次注册,两次映射,分别为WebAuthFilter和webAuthFilter

问题原因:
WebAuthFilter的第一次映射容易理解,是我们自己通过@WebFilter定义的。那么webAuthFilter是谁给映射的呢?必然是Spring容器处理的。在跟踪源码的时候找到AbstractFilterRegistrationBean抽象类,该类中有一个方法onStartup,应该是容器启动的时候执行的,做的是一些Bean注册的工作。该方法最后调用了configure,在该方法中进行了映射处理。

if (servletNames.isEmpty() && this.urlPatterns.isEmpty()) {this.logger.info("Mapping filter: '" + registration.getName() + "' to: "+ Arrays.asList(DEFAULT_URL_MAPPINGS));registration.addMappingForUrlPatterns(dispatcherTypes, this.matchAfter,DEFAULT_URL_MAPPINGS);
}else {if (!servletNames.isEmpty()) {this.logger.info("Mapping filter: '" + registration.getName()+ "' to servlets: " + servletNames);registration.addMappingForServletNames(dispatcherTypes, this.matchAfter,servletNames.toArray(new String[servletNames.size()]));}if (!this.urlPatterns.isEmpty()) {this.logger.info("Mapping filter: '" + registration.getName()+ "' to urls: " + this.urlPatterns);registration.addMappingForUrlPatterns(dispatcherTypes, this.matchAfter,this.urlPatterns.toArray(new String[this.urlPatterns.size()]));}}

在servletNames和urlPatterns为空的情况下,进行了缺省映射,即映射到“/*”。置于servletNames和urlPatterns为空的情况,这里没有深究了。那么,为什么会出现定义的WebAuthFilter被两次注册的情况呢?仔细分析了一下,认为可能的原因是:@Component和@WebFilter双重注册导致的。
解决方法:
解决办法一@WebFilter
在这种情况下,去掉了@Component注解,再次启动服务。查看日志,发现该Filter仅被映射一次,通过浏览器访问相应的url也表现正确。

解决办法二@Component

这种情况下,保留了@Component注解,那么要进行配置的urlPatterns怎么处理呢?
通过FilterRegistrationBean进行@Bean声明,查看源码知道,onStartup进行注册的时候,实际上也是找到了各类RegistrationBean然后分别注册,配置映射。
有各种类型的RegistrationBean:
①AbstractFilterRegistrationBean;
②FilterRegistrationBean;
③ServletListenerRegistrationBean;
④ServletRegistrationBean;
那么我们自然可以通过自声明一个FilterRegistrationBean来进行注册。这种处理方式如下:
去掉FIlter上的@WebFilter注解,增加如下的Configuration类:

@Configuration
public class WebAuthFilterConfig {@Beanpublic FilterRegistrationBean webAuthFilterRegistration() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(webAuthFilter());registration.setName("WebAuthFilter");registration.addUrlPatterns("/web/*");registration.addInitParameter("excludeUrls", "/web/login");registration.setOrder(0);return registration;}@Beanpublic Filter webAuthFilter() {return new WebAuthFilter();}
}

如此处理,也能达到同样的效果。
经过对比,当然第一种解决方案更直白,更简洁。
参考链接:https://www.cnblogs.com/muxi0407/p/11950627.html

@WebFilter和@Component一起使用导致urlPatterns不起作用相关推荐

  1. html5shiv:用于解决IE9以下版本浏览器对HTML5新增标签不识别,并导致CSS不起作用的问题...

    由于IE6/IE7/IE8还有很大一部分用户,为了让网站浏览者都能正常的访问HTML5网站,解决方案就有下面两个: 1. 为网站创建多套模板,通过程序对User-Agent的判断给不同的浏览器用户显示 ...

  2. xss漏洞修复踩坑总结

    一.前言 最近测试发现系统某个接口有个xss漏洞,比如,保存数据入库时,会把<a>标签保存入库:然后查看列表时,会把<a>标签显示出来: 说是这个漏洞可以构建恶意链接,点击会跳 ...

  3. 使用@WebFilter指定urlPatterns失效问题

    springboot项目使用拦截器实现Filter解接口,在类上同时使用@WebFilter与@Component注解,导致urlPatterns指定的拦截路径无法生效,出现拦截所有接口情况. 解决方 ...

  4. 使用@WebFilter指定urlPatterns失效问题排查

    springboot项目使用过滤器实现Filter接口,在类上同时使用@WebFilter与@Component注解,导致urlPatterns指定的拦截路径无法生效,出现拦截所有接口情况. 解决方案 ...

  5. 浅谈Vue内置component组件的应用场景

    官方的说明 渲染一个"元组件"为动态组件.依 is 的值,来决定哪个组件被渲染. <!-- 动态组件由 vm 实例的属性值 `componentId` 控制 --> & ...

  6. SpringBoot入门-源码解析(雷神)

    一.Spring Boot入门 视频学习资料(雷神): https://www.bilibili.com/video/BV19K4y1L7MT?p=1 github: https://github.c ...

  7. 【身份认证及权限控制一】单点登录

    官方介绍:单点登录,简称为 SSO,是目前比较流行的企业业务整合的解决方案之一. SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.是指在多系统应用群中登录一个系统, ...

  8. SpringBoot之Filter过滤器的实现及排序问题

    相关文章: SpringBoot 之AOP切面的使用 SpringBoot之Listener注册到Spring容器中的多种方法 SpringBoot之Interceptor拦截器注入使用 Spring ...

  9. 别小看“Spring过滤器”,这些知识点你必须得掌握

    容器启动时过滤器初始化以及排序注册相关逻辑. 1 @WebFilter过滤器使用@Order无效 启动程序: ​Controller: 实现俩过滤器: AuthFilter TimeCostFilte ...

最新文章

  1. Android socket 编程 实现消息推送(二)
  2. [Swift]LeetCode388. 文件的最长绝对路径 | Longest Absolute File Path
  3. 【GAN优化】一览IPM框架下的各种GAN
  4. 阶段1 语言基础+高级_1-3-Java语言高级_02-继承与多态_第1节 继承_6_继承中方法的覆盖重写_概念...
  5. 程序员如何优雅地使用 Mac?
  6. 永不丢失照片:防弹照片备份的完整指南
  7. 热冗余冷冗余_冗余支架
  8. win2003负载均衡设置
  9. Xcode无法启动模拟器或者真机
  10. python和java哪个好-Python和Java哪个薪资更高、远景更好?
  11. 【拆机】小米路由器4
  12. python3.6 scrapy模块查询POS后台获取指定时间和状态的订单存入到excel表格中
  13. 【ArcGIS】Packaging succeeded,but publishing failed ERROR001487
  14. 【Java定时器】每天凌晨12点执行一次
  15. 解决 Navicat 无法导入带外键的json 亲测有效!
  16. 【调剂】浙江大学计算机学院机械专业2023年硕士研究生招生调剂通知
  17. 魔兽世界9.0主播最多的服务器,魔兽世界9.0新人服务器选什么好?
  18. wordnet数据文件整理小结
  19. 热爱NBA:阿里扎被莫雷骗了
  20. 摩克机器人_乐克乐克2全素材入手方法详解

热门文章

  1. 【论文精读】Shape-optimizing hybrid warping for image stitching
  2. 论文解读:Prefix-Tuning: Optimizing Continuous Prompts for Generation
  3. MATLAB官方权威免费视频教程(入门+深度学习)
  4. XX系统XX版本 测试报告
  5. 【IPTV】烽火通信再次中标上海电信高清视讯平台项目
  6. 实景三维建设背景下,三维GIS面临哪些挑战?
  7. Mysql索引的原理、调优及其相关基础知识
  8. 邮箱开启授权码(配置邮件客户端)
  9. 用C/C++实现输入IQ数据,计算时差(IQ数据互相关),完成TDOA定位(Chan算法)
  10. 阿里大鱼短信接口教程php,ECSHOP短信接口【ECSHOP阿里大鱼短信】ECSHOP短信插件手机短信服务设置教程-ECSHOP教程网...