zoukankan      html  css  js  c++  java
  • 分析Filter,HandlerInterceptor,ControllerAdvice,Aop的执行时机

    测试代码 https://gitee.com/A_yes/pagehelper

    Filter

    因为filter不是springmvc里的,是servlet里的,所以filter在其他3个最外层

    springboot中Filter的写法

    //加了@Component注解,就不需要自己在配置类里去注册过滤器了
    @Component
    @WebServlet(urlPatterns = "/**")
    public class MyFilter implements Filter {
    
        private static final Logger logger = LoggerFactory.getLogger(MyFilter.class);
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            logger.warn(filterConfig.toString());
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            logger.warn("Myfilter before");
            try {
                filterChain.doFilter(servletRequest,servletResponse);
            }catch (Throwable e){
                logger.error("Myfilter catch:{}",e.getMessage());
            }
            logger.warn("Myfilter after");
        }
    
        @Override
        public void destroy() {
    
        }
    }
    

    另外三个

    剩下的三个就跟springmvc分不了关系了,我们一起来看看DispatcherServlet的关键方法doDispatch

    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);
    				
    				//mappedHandle是一个HandlerExecutionChain对象,这个对象包含了要处理请求的handler和注册是拦截器们
    				// Determine handler for the current request.
    				mappedHandler = getHandler(processedRequest);
    				if (mappedHandler == null) {
    					noHandlerFound(processedRequest, response);
    					return;
    				}
    				
    				//通过HandlerExecutionChain对象中的handler找到一个合适的handler适配器  
    				// 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;
    					}
    				}
    
    				//applyPreHandle方法就是循环调用们注册的拦截器的preHandle方法,
    				//如果拦截器返回true,就接着执行下一个,
    				//如果有返回false的,就结束执行,
    				//并触发 triggerAfterCompletion 执行拦截器中的afterCompletion方法,请求也不会进入我们的handler
    				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    					return;
    				}
    				
    				//这里开始调用我们的handler方法,一般为controller的方法
    				//当调用的方法为我们aop的切点,那就会触发我们的aop执行
    				//如果这里抛出异常,并且aop中没有进行捕获处理,那么就会进入我们的ControllerAdvice的异常处理方法
    				// Actually invoke the handler.
    				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
    				if (asyncManager.isConcurrentHandlingStarted()) {
    					return;
    				}
    
    				applyDefaultViewName(processedRequest, mv);
    
    				//执行我们注册的拦截器的postHandle方法,
    				//可见如果我们的handler不能正常返回,是不会调用postHandle方法的
    				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);
    			}
    			//在以上代码有异常未处理的时候会进入processHandlerException方法, 
    			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    		}
    		catch (Exception ex) {
    			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);
    				}
    			}
    		}
    	}
    
    //processHandlerException方法
    protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
    			@Nullable Object handler, Exception ex) throws Exception {
    
    		// Success and error responses may use different content types
    		request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
    
    		// Check registered HandlerExceptionResolvers...
    		ModelAndView exMv = null;
    		if (this.handlerExceptionResolvers != null) {
    			for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
    				//会在这里调用我们的ControllerAdvice的异常处理方法
    				exMv = resolver.resolveException(request, response, handler, ex);
    				if (exMv != null) {
    					break;
    				}
    			}
    		}
    		if (exMv != null) {
    			if (exMv.isEmpty()) {
    				request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
    				return null;
    			}
    			// We might still need view name translation for a plain error model...
    			if (!exMv.hasView()) {
    				String defaultViewName = getDefaultViewName(request);
    				if (defaultViewName != null) {
    					exMv.setViewName(defaultViewName);
    				}
    			}
    			if (logger.isTraceEnabled()) {
    				logger.trace("Using resolved error view: " + exMv, ex);
    			}
    			if (logger.isDebugEnabled()) {
    				logger.debug("Using resolved error view: " + exMv);
    			}
    			WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
    			return exMv;
    		}
    
    		throw ex;
    	}
    

    拦截器的执行顺序

    	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		HandlerInterceptor[] interceptors = getInterceptors();
    		if (!ObjectUtils.isEmpty(interceptors)) {
    			//从第一个往后依次执行preHandle方法
    			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;
    	} 
    	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
    			throws Exception {
    
    		HandlerInterceptor[] interceptors = getInterceptors();
    		if (!ObjectUtils.isEmpty(interceptors)) {
    			//从最后一个依次向前执行postHandle
    			for (int i = interceptors.length - 1; i >= 0; i--) {
    				HandlerInterceptor interceptor = interceptors[i];
    				interceptor.postHandle(request, response, this.handler, mv);
    			}
    		}
    	} 
    	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--) {
    				//从已执行preHandle方法的最后一个拦截器向前执行afterCompletion
    				HandlerInterceptor interceptor = interceptors[i];
    				try {
    					interceptor.afterCompletion(request, response, this.handler, ex);
    				}
    				catch (Throwable ex2) {
    					logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
    				}
    			}
    		}
    	}
    

    总结

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    矩阵的阶
    python中'0b111'中的b 是什么意思
    Python字节码介绍
    多版本python共存,安装三方库到指定python版本
    关于python 中的__future__模块
    解决Python模块报错:ModuleNotFoundError: No module name 'StringIO'
    python常用魔法函数
    MySQL binlog
    MySQL start and stop
    Mysql 源码安装
  • 原文地址:https://www.cnblogs.com/A-yes/p/12026947.html
Copyright © 2011-2022 走看看