SpringBoot 浅谈Filter顺序
写在前面
- ApplicationContext 实现: AnnotationConfigEmbeddedWebApplicationContext
- BeanFactory实现: DefaultListableBeanFactory
Spring Boot Filter类结构图
对应Spring的Filter讲解:
https://blog.csdn.net/geloin/article/details/7441330
Spring Boot 自带初始化的Filter
[INFO] 2019-01-23 15:42:23 org.springframework.boot.web.servlet.FilterRegistrationBean 258 - Mapping filter: 'characterEncodingFilter' to: [/*]
[INFO] 2019-01-23 15:42:23 org.springframework.boot.web.servlet.FilterRegistrationBean 258 - Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
[INFO] 2019-01-23 15:42:23 org.springframework.boot.web.servlet.FilterRegistrationBean 258 - Mapping filter: 'httpPutFormContentFilter' to: [/*]
[INFO] 2019-01-23 15:42:23 org.springframework.boot.web.servlet.FilterRegistrationBean 258 - Mapping filter: 'requestContextFilter' to: [/*]
- CharacterEncodingFilter :编码过滤器
public class OrderedCharacterEncodingFilter extends CharacterEncodingFilter
implements Ordered {
private int order = Ordered.HIGHEST_PRECEDENCE;//-2147483648
// 其余此处省略
}
- HiddenHttpMethodFilter :处理隐藏的PUT,DELETE等请求方法
public class OrderedHiddenHttpMethodFilter extends HiddenHttpMethodFilter
implements Ordered {
public static final int DEFAULT_ORDER = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 10000;
private int order = DEFAULT_ORDER; //-10000
// 其余此处省略
}
- HttpPutFormContentFilter :处理PUT表单请求
public class OrderedHttpPutFormContentFilter
extends HttpPutFormContentFilter implements Ordered {
public static final int DEFAULT_ORDER = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 9900;
private int order = DEFAULT_ORDER; //-9900
// 其余此处省略
}
- RequestContextFilter :设置请求的上下文环境
public class OrderedRequestContextFilter extends RequestContextFilter implements Ordered {
// Order defaults to after Spring Session filter
private int order = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 105;//-105
// 其余此处省略
}
-
在上述Spring Boot 自带Filter的顺序由 order 从小到大排序;
-
综合上述,可以试图将自定义的filter也由这种方式来定义其顺序
- 经过验证,即使使用@Order注解还是实现Ordered接口,都无法实现自定义顺序
@WebFilter(urlPatterns = "/*")
@Order(-9901)
public class FirstFilter extends OncePerRequestFilter implements Ordered {
private static final Logger logger = LoggerFactory.getLogger(FirstFilter.class);
private int order = -110;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
logger.info("FirstFilter:doFilterInternal");
filterChain.doFilter(request, response);
}
@Override
public int getOrder() {
return order;
}
}
- 从Spring Boot初始化源码进行解读上述方式为什么自定义filter无法实现
public class SpringApplication {
public ConfigurableApplicationContext run(String... args) {
... 此处省略若干源码
refreshContext(context);
... 此处省略若干源码
}
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
... 此处省略若干源码
}
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}
}
-
- 由上源码得知调用了AbstractApplicationContext.refresh(),但是由于多态,实际调用则是
AnnotationConfigEmbeddedWebApplicationContext重写的refresh()方法
- 由上源码得知调用了AbstractApplicationContext.refresh(),但是由于多态,实际调用则是
public class AnnotationConfigEmbeddedWebApplicationContext
extends EmbeddedWebApplicationContext {
}
public class EmbeddedWebApplicationContext extends
GenericWebApplicationContext {
@Override
public final void refresh() throws BeansException, IllegalStateException {
... 此处省略若干源码
super.refresh(); // 此处调用父类AbstractApplicationContext.refresh()
... 此处省略若干源码
}
}
public class GenericWebApplicationContext extends GenericApplicationContext
implements ConfigurableWebApplicationContext, ThemeSource {}
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {}
public abstract class AbstractApplicationContext extends
DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
... 此处省略若干源码
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);// WebFilter都在此时进行实例化
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
... 此处省略若干源码
}
}
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
... 此处省略若干源码
}
}
-
- 委任PostProcessorRegistrationDelegate处理BeanFactoryPostProcessors ,从此处可得知,注册Filter的顺序是由类名的顺序决定的。
class PostProcessorRegistrationDelegate {
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
... 此处省略若干源码
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
... 此处省略若干源码
}
/**
* Invoke the given BeanFactoryPostProcessor beans.
*/
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
// 处理@WebFilter的postProcessor 为ServletComponentRegisteringPostProcessor
postProcessor.postProcessBeanFactory(beanFactory);
}
}
}
// File:org.springframework.boot.web.servlet.ServletComponentRegisteringPostProcessor;
class ServletComponentRegisteringPostProcessor
implements BeanFactoryPostProcessor, ApplicationContextAware {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
if (isRunningInEmbeddedContainer()) {
ClassPathScanningCandidateComponentProvider componentProvider = createComponentProvider();
for (String packageToScan : this.packagesToScan) {
scanPackage(componentProvider, packageToScan);
}
}
}
private void scanPackage(
ClassPathScanningCandidateComponentProvider componentProvider,
String packageToScan) {
// packageToScan得到的FilterBeanDefinition顺序由包名决定
for (BeanDefinition candidate : componentProvider
.findCandidateComponents(packageToScan)) {
if (candidate instanceof ScannedGenericBeanDefinition) {
for (ServletComponentHandler handler : HANDLERS) {
// 由WebFilterHandler处理FilterBeanDefinition,并注册Filter
handler.handle(((ScannedGenericBeanDefinition) candidate),
(BeanDefinitionRegistry) this.applicationContext);
}
}
}
}
... 此处省略若干源码
}
-
- 重点在ServletComponentHandler 处理带有注解WebFilter的类;handle方法中处理的attributes是@WebFilter的属性,因为@WebFilter本身是没有Order属性,所以构建的Filter将是默认的Order值,而上面源码可得知,类名可决定注册Filter的顺序(即Filter过滤顺序,因为此处只能注册默认的Order值)
abstract class ServletComponentHandler {
... 此处省略若干源码
void handle(ScannedGenericBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
// 此处可以看出,attributes是通过@WebFilter的属性来获得
Map<String, Object> attributes = beanDefinition.getMetadata()
.getAnnotationAttributes(this.annotationType.getName());
if (attributes != null) {
// 此处调用的为模板方法(WebFilterHandler的实现)
doHandle(attributes, beanDefinition, registry);
}
}
protected abstract void doHandle(Map<String, Object> attributes,
ScannedGenericBeanDefinition beanDefinition, BeanDefinitionRegistry registry);
}
class WebFilterHandler extends ServletComponentHandler {
@Override
public void doHandle(Map<String, Object> attributes,
ScannedGenericBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.rootBeanDefinition(FilterRegistrationBean.class);
builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));
builder.addPropertyValue("dispatcherTypes", extractDispatcherTypes(attributes));
builder.addPropertyValue("filter", beanDefinition);
builder.addPropertyValue("initParameters", extractInitParameters(attributes));
String name = determineName(attributes, beanDefinition);
builder.addPropertyValue("name", name);
builder.addPropertyValue("servletNames", attributes.get("servletNames"));
builder.addPropertyValue("urlPatterns",
extractUrlPatterns("urlPatterns", attributes));
registry.registerBeanDefinition(name, builder.getBeanDefinition());
}
... 此处省略若干源码
}
写在最后
- 开篇给出Spring Boot 自带的4中Filter,主要为了了解其过滤顺序,且与自定义Filter的执行顺序。(由Order值从小到大的顺序),由Filter类名来实现自定义Filter顺序,因Order为默认值,所以自带的4种Filter都会比自定义的Filter先执行。
- 也可以使用FilterRegistrationBean 来设置Order定义过滤器顺序。
转一篇 FilterRegistrationBean 设置过滤器顺序文章: https://blog.csdn.net/qq_34531925/article/details/78194651