JAVA && Spring && SpringBoot2.x — 学习目录
SpringBoot2.x(Spring)
含有内置的Filter
。即OncePerRequestFilter
顾名思义:仅执行一次的Filter
。图1是OncePerRequestFilter
的子类:
在Spring中,Filter默认继承OncePerRequestFilter类。来过滤请求。
1. OncePerRequestFilter存在的意义
OncePerRequestFilter
是在一次外部请求中只过滤一次。对于服务器内部之间的forward
等请求,不会再次执行过滤方法。
在SpringBoot2.x环境下,服务器内部转发(forward)
一个请求,代码如图2所示:
- 自定义实现
Filter
接口的类,在过滤请求时打印日志。结果如图三所示:
根据上图所示,实际上请求在服务器内部转发时,并未进行过滤。可以看到上,实现Filter
接口,也会在一次请求中只过滤一次。
源码:org.springframework.web.filter.OncePerRequestFilter#doFilter
中,通过更改request中的Filter状态,防止内部请求时多次调用Filter,核心代码如图4所示。
采用的是模板方法模式,子类实现org.springframework.web.filter.OncePerRequestFilter#doFilterInternal
方法。对请求进行过滤。
2. OncePerRequestFilter方法
OncePerRequestFilter
是采用的模板方法模式,子类需要实现父类定义的钩子方法(算法逻辑父类已经实现),便可以进行过滤。
2.1 初始化方法
org.springframework.web.filter.GenericFilterBean#init
中实现init方法,子类若是想执行init方法。需要实现org.springframework.web.filter.GenericFilterBean#initFilterBean
默认的钩子方法,源码如图5所示。
但initFilterBean()
方法,在两个地方使用到,一个是init
方法中,一个是afterPropertiesSet
方法(即Filter若放到Spring容器,初始化时执行该方法)。实际上会执行两次初始化方法,如图6所示:
SpringBoot2.x将Filter加入到容器的几种方法
2.2 过滤方法
以SpringBoot2.x自动装载的编码过滤器为例,如图7所示:
源码:org.springframework.web.filter.CharacterEncodingFilter
源码:org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
总结:在Spring环境中,推荐实现OncePerRequestFilter类,而非实现原生的Filter接口。