The principle and example demonstration of spring-mvc interceptor

spring-mvc interceptor

   Overview:

    The spring-mvc interceptor mainly implements the  HandlerInterceptor interface. When the core DispatcherServlet of spring-mvc executes the main processing request method doDispatch, the processor mapper HandlerMapping finds the corresponding Handler and wraps the HandlerInterceptor implementation class according to the request path of the request object requset Assemble into a HandlerInterceptorChain , and then the HandlerInterceptorChain will call the specific methods of each interceptor according to the sequence of execution of the Handler.

   The HandlerInterceptor interceptor mainly processes and intercepts the request in the pre-processing method, and performs the processing after the post-processing method. If the pre-processing of an interceptor is executed, then the final processing method is either the pre-processing interrupt request or the error report. The final processing method must be implemented.

   Let's take a look at the simplified main execution code doDispatch() of DispatcherServlet

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		try {
			ModelAndView mv = null;
			Exception dispatchException = null;
			try {
                // 由HandlerMapping 找到handle并包装拦截器组装成HandlerExecutionChain
				mappedHandler = getHandler(processedRequest);

				// 因为handler可以是任意类型,因此需要由一个HandlerAdapter来包装调用
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
				
                // 前置处理链
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}
                
                // 实际调用方法
        		mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                // 后置处理链
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
            // 处理视图结果---内部包含拦截器的最终处理(即不异常也要执行最终处理)
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
            // 最终处理链
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		finally {
		    // ....
		}

   Below we implement a simple simulation of a spring-mvc interceptor chain and other related classes.

1. Introduction to the main classes of simulation

HandlerInterceptor interceptor

    This interface has three methods, which respectively represent the completed processing before and after the execution of the Handler request.
    
    Request pre-processing: preHandle (Request request, Response response, Handler handler)
    Request post-processing: postHandle (Request request, Response response, Handler handler)
    Request final processing: afterCompletion (Request request, Response response, Handler handler, Exception exc)
        
HandlerExecutionChain interceptor chain:
 
    function overview:
    there is a List<HandlerInterceptor> variable inside the interceptor chain instance, which is used to add the interceptor during initialization, and an int type interceptorIndex variable is used, which indicates how many interceptors have performed the pre-operation The preHandle() method, if the pre-method has an error, the interceptor that has completed the pre-operation needs to do the corresponding afterCompletion final processing operation. The afterCompletion operation is the method that will be executed when the execution is completed or the execution error occurs.
    
Other classes:
    Handler processor, originally used the processor adapter to execute the request. To simplify it, set it as a Handler class that handles the request fixedly.
    Request request class, simplified into a msg pojo class
    Response response class, simplified into a msg pojo class

2. Sample code


public class MvcFilterDemo {
	
	/**模拟request*/
	static class Request {
		public Request(String msg) {
			super();
			this.msg = msg;
		}
		private String msg;
		public String getMsg() {
			return msg;
		}
		public void setMsg(String msg) {
			this.msg = msg;
		}
	}
	
	/**模拟response*/
	static class Response{
		private String msg;
		public String getMsg() {
			return msg;
		}
		public void setMsg(String msg) {
			this.msg = msg;
		}
	}
	
	/**处理接口*/
	static interface Handler {
		public Object invoke (Request request, Response response) ;
	}
	
	/** 拦截器接口*/
	static interface HandlerInterceptor {
		boolean preHandle(Request request, Response response, Handler handler);
		void postHandle(Request request, Response response, Handler handler);
		void afterCompletion(Request request, Response response, Exception exc);
	}
	
	/**
	 * 拦截器链
	 */
	static class HandlerExecutionChain {
		private Handler handler;
		private HandlerInterceptor[] interceptors; // 拦截链调用辅助用途
		private List<HandlerInterceptor> interceptorList = new ArrayList<HandlerInterceptor>(); // 装拦截器
		private int interceptorIndex = -1; // 前置执行的角标
		public HandlerExecutionChain(Handler handler) {
			this.handler = handler;
		}
		public Handler getHandler() {
			return this.handler;
		}
		public void addInterceptor(HandlerInterceptor interceptor) {
			this.interceptorList.add(interceptor);
		}
		public HandlerInterceptor[] getInterceptors() {
			if (this.interceptors == null && this.interceptorList != null) {
				this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
			}
			return this.interceptors == null ? new HandlerInterceptor[0] : this.interceptors;
		}
		
		// 1、前置执行所有 : 每次for循环,后记录已经执行的拦截器角标,并且如果拦截器返回false,此时的最后一个拦截器要执行下最终处理方法。
		boolean applyPreHandle(Request request, Response response) throws Exception {
			HandlerInterceptor[] interceptors = getInterceptors();
				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;
		}
		
		// 2、后置执行所有:按反方向全部拦截器都执行。
		void applyPostHandle(Request request, Response response) throws Exception {
			HandlerInterceptor[] interceptors = getInterceptors();
			for (int i = interceptors.length - 1; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				interceptor.postHandle(request, response, this.handler);
			}
		}
		
		// 3、最终执行:前置操作过不管是否中断请求还是出错,这个都会进行执行。
		void triggerAfterCompletion(Request request, Response response, Exception ex) throws Exception {
			HandlerInterceptor[] interceptors = getInterceptors();
			for (int i = this.interceptorIndex; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				try {
					interceptor.afterCompletion(request, response, ex);
				} catch (Throwable ex2) {
				}
			}
		}
	
	}
	
	
	/**
	 * 请求调度总类
	 */
	static class DispatcherServlet{
		
		private HandlerExecutionChain chain ;

		public void setChain(HandlerExecutionChain chain) {
			this.chain = chain;
		}
		
		public void doService(Request request, Response response) throws Exception {
			Handler handler = chain.getHandler();
			try {
				// 前置拦截 --- 如果false,内部会
				if (!chain.applyPreHandle(request, response)) {
					return;
				}
				Exception dispatchException = null;
				try {
					handler.invoke(request, response);
					// 后置执行
					chain.applyPostHandle(request, response);
				} catch (Exception e) {
					dispatchException = e;
				}
				// 最终执行
				chain.triggerAfterCompletion(request, response, dispatchException);
			} catch (Exception e) {
				chain.triggerAfterCompletion(request, response, e);
			} finally {
				 // ....
			}
		}
	}
	
	测试阶段//
	
	public static class MyHandler implements Handler {
		@Override
		public Object invoke(Request request, Response response) {
			System.out.println("handler处理方法进行实际处理");
			String old = request.getMsg() ;
			request.setMsg(old + "[real excute]");
			return "hello wolrd";
		}
	}
	
	static class HandlerInterceptorOne implements HandlerInterceptor {
		@Override
		public boolean preHandle(Request request, Response response, Handler handler) {
			String old = request.getMsg() ;
			request.setMsg(old + "[one excute]");
			System.out.println("one 前置执行");
			return true;
		}
		@Override
		public void postHandle(Request request, Response response, Handler handler) {
			System.out.println("one 后置执行");
		}
		@Override
		public void afterCompletion(Request request, Response response, Exception exc) {
			System.out.println("one 最终执行");
		}
	}
	
	static class HandlerInterceptorTwo implements HandlerInterceptor {
		@Override
		public boolean preHandle(Request request, Response response, Handler handler) {
			String old = request.getMsg() ;
			request.setMsg(old + "[two excute]");
			System.out.println("two 前置执行");
			return true;
		}
		@Override
		public void postHandle(Request request, Response response, Handler handler) {
			System.out.println("two 后置执行");
		}
		@Override
		public void afterCompletion(Request request, Response response, Exception exc) {
			System.out.println("two 最终执行");
		}
	}
	
	
	/**
	 * 测试: 
	 */
	public static void main(String[] args) throws Exception {
		DispatcherServlet dispatcherServlet = new DispatcherServlet();
		MyHandler myHandler = new MyHandler();
		HandlerInterceptorOne oneInterceptor = new HandlerInterceptorOne();
		HandlerInterceptorTwo twoInterceptor = new HandlerInterceptorTwo();
		HandlerExecutionChain chain = new HandlerExecutionChain(myHandler);
		chain.addInterceptor(oneInterceptor);
		chain.addInterceptor(twoInterceptor);
		
		dispatcherServlet.setChain(chain);
		Request request = new Request("base request");
		Response response = new Response();
		dispatcherServlet.doService(request, response);
		System.out.println("最终结果" + request.getMsg());
//		one 前置执行
//		two 前置执行
//		handler处理方法进行实际处理
//		two 后置执行
//		one 后置执行
//		two 最终执行
//		one 最终执行
//		最终结果base request[one excute][two excute][real excute]
	}
	
}

complete!

 

 

 

Guess you like

Origin blog.csdn.net/shuixiou1/article/details/112970999