1、拦截器基本使用
1.1 编写拦截器类
实现HandlerInterceptor接口即可
@Slf4j
public class MyHandlerInterceptor implements HandlerInterceptor {
/**
* 目标方法执行前执行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle执行了.................");
return true;
}
/**
* 目标方法执行后执行
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle.................");
}
/**
* 所有逻辑处理完成后执行 异常也会执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion.................");
}
}
1.2 配置使拦截器生效
通过WebMvcConfigurer中addInterceptors方法进行注册配置拦截器
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyHandlerInterceptor())
.addPathPatterns("/**") //拦截所有请求,包含静态资源请求
.excludePathPatterns("/login"); // login请求排除在外
}
}
1.3 测试类
@RestController
@Slf4j
public class TestHandlerInterceptorController {
@GetMapping("/hello")
public String hello() {
log.info("hello执行了.................");
return "hello word";
}
}
访问地址:http://127.0.0.1:8080/hello,后台依次打印
2、拦截器原理
2.1 根据当前请求,可以处理请求的handler以及handler的所有拦截器
根据地址请求,与容器中所有的拦截器进行匹配返回处理请求的拦截器
//DispatcherServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//...............
mappedHandler = getHandler(processedRequest);
//..............
}
//AbstractHandlerMapping
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//..............
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
//.............
}
/**
* 将容器中所有拦截器与访问地址进行匹配
*/
//AbstractHandlerMapping
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
2.2、执行preHandle方法
顺序执行所有的preHandle方法,如果拦截器返回false,将已经执行的的拦截器的afterCompletion进行执行,只要一个拦截器不过,目标方法就不会执行
//DispatcherServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//...............
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//执行目标方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//..............
}
//HandlerExecutionChain
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
//HandlerExecutionChain
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
//将已经执行的的拦截器的afterCompletion进行执行
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
2.3 执行目标方法
所有拦截器通过执行目标方法
//DispatcherServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//...............
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//执行目标方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//..............
}
2.4、执行applyPostHandle
目标方法执行完成。倒叙执行applyPostHandle
//DispatcherServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//...............
mappedHandler.applyPostHandle(processedRequest, response, mv);
//..............
}
//HandlerExecutionChain
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
2.5 执行afterCompletion
processDispatchResult渲染方法最后,会倒序执行afterCompletion
//DispatcherServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//...............
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
//..............
}
//DispatcherServlet
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,@Nullable Exception exception) throws Exception {
//...............
if (mappedHandler != null) {
// Exception (if any) is already handled..
mappedHandler.triggerAfterCompletion(request, response, null);
}
//...............
}
//HandlerExecutionChain
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
2.6 异常执行
执行过程中,出现任何异常,都会将已经执行的的拦截器的afterCompletion进行执行
//DispatcherServlet
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,@Nullable Exception exception) throws Exception {
try{
//...............
}catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
}
//DispatcherServlet
private void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, Exception ex) throws Exception {
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, ex);
}
throw ex;
}
//HandlerExecutionChain
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}