目前Java的后端开发基本都会用Spring MVC,在SpringBoot的封装里,拦截器如何添加网上教程千篇一律,即使寻找官方的文档,也只有一种比较死板, 如何灵活添加拦截器呢?下面会介绍5种方式。
Spring MVC添加拦截器
目前Java的后端开发基本都会用Spring MVC,在SpringBoot的封装里,拦截器如何添加网上教程千篇一律,即使寻找官方的文档,也只有一种比较死板的添加方式,如下:
1 |
|
当我要实现在项目启动加载配置时,灵活配置拦截器这种方法就没这么优雅了。所以为了本文提供多种方式注册拦截器。转换器思路一致所以本文仅仅介绍拦截器。
首先我们先来看下spring mvc拦截器原理是怎样的。
理解springMVC 拦截器设置原理
我们知道springMVC真正设置拦截器的时候是在AbstractHandlerMapping中执行的initApplicationContext方式(可查看看透springMVC-142页)所以我们跟一下该方法。方式一中也仅仅是把我们定义的拦截器设置到AbstractHandlerMapping的interceptors中。
1 | public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport |
通过initApplicationContext可以发现springMVC设置到interceptors中的拦截器最终都会存储在adaptedInterceptors
中。springMVC可以从3个地方将拦截器设置到interceptors,并且最终通过initInterceptors方法将interceptors中拦截器设置到adaptedInterceptors中:
- 创建子类的时候通过setInterceptors方法将拦截器设置到interceptors中(方式一springMVC配置就是通过该机制)
- 子类实现的扩展拦截器extendInterceptors,允许子类将一些拦截器设置到interceptors中
- 从spring 容器中获取到所有的MappedInterceptor设置到interceptors中
所以这里就出现了方式2 向spring中注入MappedInterceptor类型的拦截器。
这里补充一点,spring是在哪里使用拦截器的:
1 | public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport |
方式1
利用springMVC提供的WebMvcConfigurer,实现多个WebMvcConfigurer。利用的是创建handlerMapping的时候通过setInterceptors方法将拦截器设置到interceptors中
1 |
|
这种方式原理是:@EnableWebMvc
当使用该注解后会Import DelegatingWebMvcConfiguration
该类会扫描spring容器中所有的WebMvcConfigurer,然后调用所有的WebMvcConfigurer的addInterceptors方法将所有的拦截器注入到InterceptorRegistry中,之后在spring配置的WebMvcConfigurationSupport#requestMappingHandlerMapping中使用InterceptorRegistry并将其配置到相应的HandlerMapping上即可。(注册转换器原理一致)
所以这里注册转换器或者拦截器的方式一出现了,实现多个WebMvcConfigurer(控制WebMvcConfigurer顺序可以使用@Order或者Ordered接口)
方式2
向spring中注入MappedInterceptor类型的拦截器。利用的是AbstractHandlerMapping#detectMappedInterceptors方法
1 |
|
方式3
根据配置添加拦截器时.采用springBoot的@Conditional注解。同方式二,利用了springboot 特性
1 |
|
方式4
利用spring aop功能。采用AOP拦截处理的方式
1 |
|
方式5
利用反射的方式。参考了 Spring MVC从源码分析到实践如何动态添加拦截器
1 |
|
1 |
|
拦截器
1 |
|
方式比较
方式一可以设置拦截器的优先级,方式二则不行即使使用@Order类也不行,原因在于如果是利用spring @Autowired则可以获取到排完序的列表,但是springMVC中使用 BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MappedInterceptor.class, true, false).values()
并没有排序。所以推荐使用方式1。关于spring bean加载顺序可以去看下@Bean处理也许可以根据方法先后顺序进行控制。
参考
1 | 《看透springMVC》 |
- 本文作者: 初心
- 本文链接: http://funzzz.fun/2022/05/09/MVC从源码分析到实践如何动态添加拦截器/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!