SpringBoot filter 责任链
参考:SpringBoot中filter的使用详解及原理_u014627099的博客-CSDN博客_filter springboot
Arthas实践--快速排查Spring Boot应用404/401问题 | 横云断岭的专栏
1. 处理请求流程
Request -》 filter1 -〉 filter2 -》 controller
|
Request《- filter1 《- filter2 《- controller
2. filter原理【本质就是责任链设计】
请求会经过一个个编写的filter,最后进入controller 。然后返回一个个filter,最后给到请求方
3. 源码:https://github.com/bailuoxi66/snapUpDemo/tree/master/springBoot-Redis-Demo/springboot-filter
4. 代码相关
1. 要想使用filter,需要写一个方法继承Filter类。我们自己写了两个Filter类。其中
@Order里面的数字越小代表越先被该filter过滤
@WebFilter代表这是个Filter类,以便于启动类进行扫描的时候确认2. FirstFilter
package com.example.springbootfilter.filterInfo;import org.springframework.core.annotation.Order;import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException;/*** @author :luoyu* @version :1.0* @date : 2021/12/31 10:47 上午* @description*/@Order(1) @WebFilter(filterName = "firstFilter", urlPatterns = "/*") public class FirstFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("first filter 1");filterChain.doFilter(servletRequest, servletResponse);System.out.println("first filter 2");}@Overridepublic void destroy() {} }
3. SecondFilter
package com.example.springbootfilter.filterInfo;import org.springframework.core.annotation.Order;import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException;/*** @author :luoyu* @version :1.0* @date : 2021/12/31 10:47 上午* @description*/@Order(2) @WebFilter(filterName = "secondFilter", urlPatterns = "/*") public class SecondFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("second filter 1");HttpServletRequest request = (HttpServletRequest) servletRequest;System.out.println("before:" + servletRequest);System.out.println(request.getRequestURL());String uri = request.getRequestURI();System.out.println(uri);if (uri.contains("Test")){System.out.println("过滤。。。");servletResponse.getWriter().write("secondfilter already");return;}filterChain.doFilter(servletRequest, servletResponse);System.out.println("after:" + servletResponse);System.out.println("second filter 2");}@Overridepublic void destroy() {} }
4. SessionFilter
package com.example.springbootfilter.filterInfo;import org.springframework.core.annotation.Order;import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;/*** @author :luoyu* @version :1.0* @date : 2021/12/31 12:01 下午* @description*/ @Order(3) @WebFilter(filterName = "sessionFilter",urlPatterns = {"/*"}) public class SessionFilter implements Filter {//不需要登录就可以访问的路径(比如:注册登录等)String[] includeUrls = new String[]{"/login","/test1"};@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;String uri = request.getRequestURI();System.out.println("filter url:"+uri);//是否需要过滤boolean needFilter = isNeedFilter(uri);if (!needFilter) { //不需要过滤直接传给下一个过滤器filterChain.doFilter(servletRequest, servletResponse);} else {response.getWriter().write("sessionFilter already");}}/*** 是否需要过滤* @params [uri]* @return boolean* @author luoyu* @date 2021/12/31 1:35 下午**/public boolean isNeedFilter(String uri) {for (String includeUrl : includeUrls) {if(includeUrl.equals(uri)) {return false;}}return true;}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void destroy() {} }
4. controller类
5. SpringBoot的主入口方法。注意:因为我们使用的是注解注入Filter,
所以需要加入:@ServletComponentScan
@SpringBootApplication @ServletComponentScan public class SpringbootFilterApplication {public static void main(String[] args) {SpringApplication.run(SpringbootFilterApplication.class, args);}}
6. 运行结果
1. 正常没有过滤逻辑
请求:http://localhost:8080/test1
运行结果:
可以看到代码执行流程,首先请求会被FirstFilter截获,打印出first filter1,然后执行filterChain.doFilter(servletRequest, servletResponse),这句话代表请求会转发给过滤器链上的下一个对象,也就是SecondFilter,所以打印出second filter 1 。接下来执行SecondFilter里面的 filterChain.doFilter(servletRequest, servletResponse) ,请求会转发给下一个对象,到达SessionFilter打印filter url:/test1.然后根据是否过滤逻辑,发现不需要过滤直接给到下一个filter。调用filterChain.doFilter(servletRequest, servletResponse),但是没有其他filter了。所以会转发给controller。打印出controller里面对应方法的内容【“method in controller”】,接下来去虚拟机栈栈帧里面获取信息,调用SecondFilter打印出second filter 2. 同理调用FirstFilter打印出first filter 2。
2. filter过滤逻辑
请求:http://localhost:8080/api/filterTest.json
运行结果:
first filter 1 second filter 1 before:org.apache.catalina.connector.RequestFacade@5d98f8e7 http://localhost:8080/api/filterTest.json /api/filterTest.json 过滤。。。 first filter 2
可以看到没有进入controller。因为命中率这里的逻辑:
也就是说:这里断开了,没有了后续。
3. SessionFilter拦截非法请求
因为从整个请求链路来看:经过了firstfilter-》scondfilter -》sessionfilter
首先secondfilter没有拦截,因为url没有包含“Test”字符,所以到达了sessionfilter
但是被sessionfilter拦截了。因为needFilter是true,需要拦截
4. 请求被filter拦截。通过arthas确认是哪一个filter拦截的。
开启arthas监听模式:在Arthas里面,把整个请求经过哪些filter处理,都打印成树。这里找下嵌套最深层
可以看到这里是:SessionFilter里面进行了拦截
arthas:所有结果
[arthas@86617]$ trace javax.servlet.Filter * Press Q or Ctrl+C to abort. Affect(class count: 18 , method count: 100) cost in 266 ms, listenerId: 1 `---ts=2021-12-31 14:08:34;thread_name=http-nio-8080-exec-4;id=30;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@5c1bd44c`---[6.468228ms] org.springframework.web.filter.OncePerRequestFilter:doFilter()+---[0.888623ms] org.springframework.web.filter.OncePerRequestFilter:getAlreadyFilteredAttributeName() #97| `---[0.851397ms] org.springframework.web.filter.OncePerRequestFilter:getAlreadyFilteredAttributeName()| `---[0.800084ms] org.springframework.web.filter.OncePerRequestFilter:getFilterName() #170| `---[0.07793ms] org.springframework.web.filter.GenericFilterBean:getFilterName()| `---[0.024575ms] javax.servlet.FilterConfig:getFilterName() #298+---[0.019792ms] javax.servlet.ServletRequest:getAttribute() #98+---[2.108542ms] org.springframework.web.filter.OncePerRequestFilter:skipDispatch() #100| `---[2.07759ms] org.springframework.web.filter.OncePerRequestFilter:skipDispatch()| +---[1.977538ms] org.springframework.web.filter.OncePerRequestFilter:isAsyncDispatch() #127| | `---[1.94646ms] org.springframework.web.filter.OncePerRequestFilter:isAsyncDispatch()| | +---[0.013899ms] javax.servlet.http.HttpServletRequest:getDispatcherType() #146| | `---[0.072898ms] javax.servlet.DispatcherType:equals() #146| `---[0.02551ms] javax.servlet.http.HttpServletRequest:getAttribute() #130+---[0.105523ms] org.springframework.web.filter.OncePerRequestFilter:shouldNotFilter() #100| `---[0.031155ms] org.springframework.web.filter.OncePerRequestFilter:shouldNotFilter()+---[0.027592ms] javax.servlet.ServletRequest:setAttribute() #115+---[2.759263ms] org.springframework.web.filter.OncePerRequestFilter:doFilterInternal() #117| `---[2.69305ms] org.springframework.web.filter.CharacterEncodingFilter:doFilterInternal()| +---[0.056953ms] org.springframework.web.filter.CharacterEncodingFilter:getEncoding() #192| | `---[0.020965ms] org.springframework.web.filter.CharacterEncodingFilter:getEncoding()| +---[0.058125ms] org.springframework.web.filter.CharacterEncodingFilter:isForceRequestEncoding() #194| | `---[0.016392ms] org.springframework.web.filter.CharacterEncodingFilter:isForceRequestEncoding()| +---[0.038208ms] javax.servlet.http.HttpServletRequest:setCharacterEncoding() #195| +---[0.035288ms] org.springframework.web.filter.CharacterEncodingFilter:isForceResponseEncoding() #197| | `---[0.011489ms] org.springframework.web.filter.CharacterEncodingFilter:isForceResponseEncoding()| `---[2.412639ms] javax.servlet.FilterChain:doFilter() #201| `---[2.367289ms] org.springframework.web.filter.OncePerRequestFilter:doFilter()| +---[0.092118ms] org.springframework.web.filter.OncePerRequestFilter:getAlreadyFilteredAttributeName() #97| | `---[0.067511ms] org.springframework.web.filter.OncePerRequestFilter:getAlreadyFilteredAttributeName()| | `---[0.046879ms] org.springframework.web.filter.OncePerRequestFilter:getFilterName() #170| | `---[0.025428ms] org.springframework.web.filter.GenericFilterBean:getFilterName()| | `---[0.007377ms] javax.servlet.FilterConfig:getFilterName() #298| +---[0.011038ms] javax.servlet.ServletRequest:getAttribute() #98| +---[0.140236ms] org.springframework.web.filter.OncePerRequestFilter:skipDispatch() #100| | `---[0.115496ms] org.springframework.web.filter.OncePerRequestFilter:skipDispatch()| | +---[0.072747ms] org.springframework.web.filter.OncePerRequestFilter:isAsyncDispatch() #127| | | `---[0.041142ms] org.springframework.web.filter.OncePerRequestFilter:isAsyncDispatch()| | | +---[0.008436ms] javax.servlet.http.HttpServletRequest:getDispatcherType() #146| | | `---[0.006054ms] javax.servlet.DispatcherType:equals() #146| | `---[0.010302ms] javax.servlet.http.HttpServletRequest:getAttribute() #130| +---[0.034537ms] org.springframework.web.filter.OncePerRequestFilter:shouldNotFilter() #100| | `---[0.009114ms] org.springframework.web.filter.OncePerRequestFilter:shouldNotFilter()| +---[0.019467ms] javax.servlet.ServletRequest:setAttribute() #115| +---[1.971268ms] org.springframework.web.filter.OncePerRequestFilter:doFilterInternal() #117| | `---[1.937453ms] org.springframework.web.filter.FormContentFilter:doFilterInternal()| | +---[0.196208ms] org.springframework.web.filter.FormContentFilter:parseIfNecessary() #88| | | `---[0.171456ms] org.springframework.web.filter.FormContentFilter:parseIfNecessary()| | | `---[0.148937ms] org.springframework.web.filter.FormContentFilter:shouldParse() #99| | | `---[0.122507ms] org.springframework.web.filter.FormContentFilter:shouldParse()| | | +---[0.020572ms] javax.servlet.http.HttpServletRequest:getContentType() #113| | | +---[0.033034ms] javax.servlet.http.HttpServletRequest:getMethod() #114| | | `---[0.020836ms] org.springframework.util.StringUtils:hasLength() #115| | +---[0.011308ms] org.springframework.util.CollectionUtils:isEmpty() #89| | `---[1.685984ms] javax.servlet.FilterChain:doFilter() #93| | `---[1.664666ms] org.springframework.web.filter.OncePerRequestFilter:doFilter()| | +---[0.081575ms] org.springframework.web.filter.OncePerRequestFilter:getAlreadyFilteredAttributeName() #97| | | `---[0.065688ms] org.springframework.web.filter.OncePerRequestFilter:getAlreadyFilteredAttributeName()| | | `---[0.051453ms] org.springframework.web.filter.OncePerRequestFilter:getFilterName() #170| | | `---[0.030805ms] org.springframework.web.filter.GenericFilterBean:getFilterName()| | | `---[0.007209ms] javax.servlet.FilterConfig:getFilterName() #298| | +---[0.010989ms] javax.servlet.ServletRequest:getAttribute() #98| | +---[0.13897ms] org.springframework.web.filter.OncePerRequestFilter:skipDispatch() #100| | | `---[0.122124ms] org.springframework.web.filter.OncePerRequestFilter:skipDispatch()| | | +---[0.078663ms] org.springframework.web.filter.OncePerRequestFilter:isAsyncDispatch() #127| | | | `---[0.053971ms] org.springframework.web.filter.OncePerRequestFilter:isAsyncDispatch()| | | | +---[0.005793ms] javax.servlet.http.HttpServletRequest:getDispatcherType() #146| | | | `---[0.013142ms] javax.servlet.DispatcherType:equals() #146| | | `---[0.011082ms] javax.servlet.http.HttpServletRequest:getAttribute() #130| | +---[0.021786ms] org.springframework.web.filter.OncePerRequestFilter:shouldNotFilter() #100| | | `---[0.005747ms] org.springframework.web.filter.OncePerRequestFilter:shouldNotFilter()| | +---[0.012466ms] javax.servlet.ServletRequest:setAttribute() #115| | +---[1.293744ms] org.springframework.web.filter.OncePerRequestFilter:doFilterInternal() #117| | | `---[1.262514ms] org.springframework.web.filter.RequestContextFilter:doFilterInternal()| | | +---[0.021243ms] org.springframework.web.context.request.ServletRequestAttributes:<init>() #96| | | +---[0.278449ms] org.springframework.web.filter.RequestContextFilter:initContextHolders() #97| | | | `---[0.256751ms] org.springframework.web.filter.RequestContextFilter:initContextHolders()| | | | +---[0.132398ms] javax.servlet.http.HttpServletRequest:getLocale() #112| | | | +---[0.025818ms] org.springframework.context.i18n.LocaleContextHolder:setLocale() #112| | | | +---[0.017864ms] org.springframework.web.context.request.RequestContextHolder:setRequestAttributes() #113| | | | `---[0.016344ms] org.apache.commons.logging.Log:isTraceEnabled() #114| | | +---[0.705757ms] javax.servlet.FilterChain:doFilter() #100| | | | `---[0.661857ms] com.example.springbootfilter.filterInfo.FirstFilter:doFilter()| | | | `---[0.569476ms] javax.servlet.FilterChain:doFilter() #27| | | | `---[0.532086ms] com.example.springbootfilter.filterInfo.SecondFilter:doFilter()| | | | +---[0.037252ms] javax.servlet.http.HttpServletRequest:getRequestURL() #30| | | | +---[0.012403ms] javax.servlet.http.HttpServletRequest:getRequestURI() #31| | | | `---[0.266668ms] javax.servlet.FilterChain:doFilter() #38| | | | `---[0.228648ms] com.example.springbootfilter.filterInfo.SessionFilter:doFilter()| | | | +---[0.009811ms] javax.servlet.http.HttpServletRequest:getRequestURI() #29| | | | +---[0.089258ms] com.example.springbootfilter.filterInfo.SessionFilter:isNeedFilter() #33| | | | | `---[0.058013ms] com.example.springbootfilter.filterInfo.SessionFilter:isNeedFilter()| | | | `---[0.030816ms] javax.servlet.http.HttpServletResponse:getWriter() #38| | | +---[0.148522ms] org.springframework.web.filter.RequestContextFilter:resetContextHolders() #103| | | | `---[0.083649ms] org.springframework.web.filter.RequestContextFilter:resetContextHolders()| | | | +---[0.023226ms] org.springframework.context.i18n.LocaleContextHolder:resetLocaleContext() #120| | | | `---[0.009855ms] org.springframework.web.context.request.RequestContextHolder:resetRequestAttributes() #121| | | +---[0.00996ms] org.apache.commons.logging.Log:isTraceEnabled() #104| | | `---[0.013286ms] org.springframework.web.context.request.ServletRequestAttributes:requestCompleted() #107| | `---[0.019486ms] javax.servlet.ServletRequest:removeAttribute() #121| `---[0.008947ms] javax.servlet.ServletRequest:removeAttribute() #121`---[0.010701ms] javax.servlet.ServletRequest:removeAttribute() #121
上述结论一致。
SpringBoot filter 责任链相关推荐
- Filter责任链模式
Filter责任链的创建 org.apache.catalina.core.ApplicationFilterFactory#createFilterChain, 此方法是被org.apache.c ...
- 使用SpringBoot实现责任链模式
背景 当我们需要对一个对象进行多次操作时,每个操作支持个性化定制,后续还可能增加更多的操作时就可以使用责任链模式,本篇将使用SpringBoot实现简易责任链 例子 如下代码范例是校验一名粉丝是不是& ...
- java责任链模式审批请假_Java设计模式-责任链模式
Java设计模式-责任链模式 Java版本:jdk1.8 IDE:IDEA 一 前言 本文介绍责任链模式以及Java下的实现. 二 概念 1.什么是责任链模式 责任链模式(Chain of Respo ...
- 责任链模式之Tomcat Filter应用
责任链模式之Tomcat Filter应用 责任链模式是一种对象的行为型模式. 其定义为:很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象处理此请求.发 ...
- SpringCloud SpringBoot uniapp vue b2b2c 微服务 多商家入驻直播带货商城 分销商城 秒杀 高并发电商之责任链模式
责任链模式 推荐分布式微服务电商源码 顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收 ...
- 从Servlet、Dubbo、Mybatis聊聊责任链究竟怎么用
作者:atheva 来源:https://dwz.cn/1TtgW7Ud 责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系, 将这个对象连成一条链,并沿着这条链 ...
- 一起学设计模式 - 责任链模式
责任链模式(ChainOfResponsibilityPattern)属于 行为型模式的一种,将请求沿着一条链传递,直到该链上的某个对象处理它为止. 概述 定义如下:一个请求有多个对象来处理,这些对象 ...
- 折腾Java设计模式之责任链模式
责任链模式 顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计 ...
- 23种设计模式——责任链模式
一.责任链模式 顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的 ...
- 巧用『责任链模式』来优化 参数多重校验,非常优雅!
点击上方"芋道源码",选择"设为星标" 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | ...
最新文章
- html标记汇总,HTML标记语法汇总.doc
- 面试官:MySQL 表设计要注意什么?
- 珂朵莉的约数(牛客练习赛9)
- 【CMD】复制并覆盖目标文件
- TPL Dataflow .Net 数据流组件,了解一下?
- 前端学习(2863):简单秒杀系统学习之优化cookie
- Diccuz!NT的dll版本号控制技巧
- WinMerge 操作界面汉语版(截图),以及简单功能介绍
- 【激光雷达3D】【论文翻译】PointPillars: Fast Encoders for Object Detection from Point Clouds
- iphone多线程事件循环
- lintcode 订单
- Aruba无线AP入坑心得
- win7下 文件名太长无法删除,无法更名问题
- 艾滋hiv最新研究进展(2022年4月)
- 【论文】多核实时操作系统的确定性调度设计
- TIA博途_基于SCL语言制作模拟量输入输出全局库的具体方法
- 服务器虚拟机光驱,vSphere client中的光驱配置方式
- NVIDA CUDA显卡计算能力 GeForce RTX 2060 compute_capability
- Matlab在不同坐标系中绘图(对数、极坐标、双轴图)以及极坐标和直角坐标的相互转换
- JSP SSH机械设备台账管理系统myeclipse开发mysql数据库MVC模式java编程网页设计
热门文章
- mysql导入GP_GP数据库gpload数据导入详细操作
- 以太坊平台评估 私有链和联盟链的机会与挑战
- HPSocket C++控制台版DEMO
- 教程丨如何在AdsPower浏览器内快速配置UCloud 服务器
- win10计算机安全策略设置,win10系统重置本地安全策略所有设置的操作方法
- 很多人觉得FPGA难学,因为他们没总结出数电的尽头是模电!
- 国内主要OTT平台背后的那些CDN服务商
- premiere学习笔记01帧定格,时间码,透明视频,调整图层,转场及批量转场,插件安装,音频调整,关键帧,马赛克,蒙版,嵌套序列
- html 展开 折叠,HTML实现点击展开和收起
- 如何下载南开区卫星地图高清版大图