在SpringMVC源码分析一文中,已经对SpringMVC的初始化及请求响应过程进行了分析,但未对拦截器进行深入研究。
本文将首先通过示例的方式了解拦截器的工作原理,然后再深入分析其源码来了解其内部原理。
本文代码基于Spring Boot+Kotlin。
1 自定义拦截器
GITHUB地址: https://github.com/icarusliu/learn
1.1 Interceptor定义
第一步我们先来定义一个Interceptor;
拦截器一般需要继承自HandlerInterceptor,并需要实现以下三个接口:
接口 | 接口名称 | 说明 |
---|---|---|
preHandle | 前置处理 | 在实际的Handle执行前执行;有Boolean类型的返回值,如果返回为False,则Handle本身及postHandle/afterCompletion以及后续的拦截器全部都不会再继续执行;为True则反之。 |
postHandle | 后置处理 | Handle执行后视图渲染前执行 |
afterCompletion | 完成后处理 | Handle执行且视图渲染完成后执行 |
Spring为方便使用实现了HandlerInterceptorAdapter的抽象类;需要实现的方法都实现为空的方法,在使用时只需实现必要的方法即可。
定义的测试拦截器见以下代码:
class TestInterceptor: HandlerInterceptorAdapter() {
private val logger = LoggerFactory.getLogger(HandlerInterceptorAdapter::class.java)
/**
* This implementation always returns `true`.
*/
@Throws(Exception::class)
override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
if (logger.isDebugEnabled) {
logger.debug("TestInterceptor preHandle begin to execute!")
}
return true
}
/**
* This implementation is empty.
*/
@Throws(Exception::class)
override fun postHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any,
@Nullable modelAndView: ModelAndView?) {
if (logger.isDebugEnabled) {
logger.debug("TestInterceptor postHandle begin to execute!")
}
}
/**
* This implementation is empty.
*/
@Throws(Exception::class)
override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any,
@Nullable ex: Exception?) {
if (logger.isDebugEnabled) {
logger.debug("TestInterceptor afterCompletion begin to execute!")
}
}
/**
* This implementation is empty.
*/
@Throws(Exception::class)
override fun afterConcurrentHandlingStarted(request: HttpServletRequest, response: HttpServletResponse,
handler: Any) {
if (logger.isDebugEnabled) {
logger.debug("TestInterceptor afterConcurrentHandlingStarted begin to execute!")
}
}
}
1.2 拦截器配置
拦截器定义完成后,还需要将拦截器引入,并指定该拦截器所拦截的场景。
在SpringBoot中,一般通过使用EnableWebMvc及Configuration两个注解,并实现WebMvcConfigurer接口来添加拦截器,实现代码如下:
@EnableWebMvc
@Configuration
class WebConfig: WebMvcConfigurer {
override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(TestInterceptor()).addPathPatterns("/**")
}
}
注解一定要通过addPathPatterns来指定该拦截器所拦截的URL,如果不指定将不会拦截任何请求。.
1.3 定义Controller
Controller的定义比较简单,在此不细说,代码如下: