SpringMVC拦截器使用流程和源码分析
2021-01-15 12:13
标签:over nested dap sem efault 请求 exe port The 重点是实现 preHandle、postHandle、afterCompletion三个方法 正常流程: 拦截器的preHandle--->目标方法---->拦截器的postHandle---->页面----->拦截器的afterCompletion 其他流程: 只要preHandle不放行,就没有下面的流程。 只要放行了,afterCompletion都会执行 SpringMVC的核心方法doDispatch() 源码如下 ---------------之前的随笔也分析过 ------------------ 先来到 processDispatchResult方法 页面渲染完成之后,执行 triggerAfterCompletion 方法 SpringMVC拦截器使用流程和源码分析 标签:over nested dap sem efault 请求 exe port The 原文地址:https://www.cnblogs.com/lxy-java/p/12936334.html1、SpringMVC拦截器的使用流程
1)、在spring-servlet.xml中配置拦截器信息。
mvc:interceptors>
mvc:interceptor>
mvc:mapping path="/test01"/>
bean class="com.lxy.controller.FilterController">
bean>
mvc:interceptor>
mvc:interceptors>
2)、写自己的拦截器并实现 HandlerInterceptor接口
public class MyFilter implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
2、SpringMVC拦截器运行流程
3、SpringMVC拦截器源码分析
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 在目标方法执行之前,会先执行preHandle方法 如何返回false就直接返回了 下面统统不执行
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 执行目标方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 在执行完目标方法之后,会执行拦截器的postHandler方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we‘re processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 渲染页面,并在该方法中执行afterCompletion方法
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
// 即使上面执行的方法抛出了异常,afterCompletion的方法依然会被执行
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
} 1)、preHandle方法是如何执行的(applyPreHandle方法)
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 得到所有的拦截器
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 循环正序遍历所有的拦截器
for (int i = 0; i ) {
HandlerInterceptor interceptor = interceptors[i];
// 执行拦截器方法,并返回true/false 来当前方法,preHandler是否放行了
if (!interceptor.preHandle(request, response, this.handler)) {
// 执行到这,说明preHandler返回的是false,就是不放行,那么就执行完下面方法(afterCompletion方法的执行方法),直接返回,不纪录拦截器索引
// 由于没有纪录当前拦截器索引,所以即使执行了下面方法,当前拦截器的afterCompletion也不会被执行
triggerAfterCompletion(request, response, null);
return false;
}
// 纪录拦截器索引最远达到的位置,为之后执行afterCompletion方法做准备
// 说明:如果索引为1的拦截器的preHandle方法返回的是false,即使索引为2的拦截器的preHandle方法返回的是true,索引为2的拦截器的postHandle等后面所有方法统统不执行
this.interceptorIndex = i;
}
}
return true; 2)、postHandle方法是如何执行的(applyPostHandle)
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 逆序遍历所有的拦截器,并执行postHandler方法
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
} 3)、afterCompletion方法是如何执行的
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
boolean errorView = false;
// 先进行页面渲染
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No view rendering, null ModelAndView returned.");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
// 页面渲染完成后,执行afterCompletion方法
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 遍历所有之前preHandle方法放行的拦截器,interceptorIndex就是之前在执行preHandle方法时候,如果返回的是true就纪录一下
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);
}
}
}
}
上一篇:Python-GUI程序设计-2
下一篇:数据结构-C语言实现-链栈
文章标题:SpringMVC拦截器使用流程和源码分析
文章链接:http://soscw.com/index.php/essay/42249.html