职责链模式在开源代码中的应用

职责链模式的作用:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。

案例一

servlet 2.3 版新增了 Filter 和 FilterChain,其中 FilterChain 就是用了职责链模式。

Filter 用于在 Servlet 响应前,进行预处理、信息校验等,Filter 没有调用 doFilter 方法参数中 chain 的 doFilter 方法,调用链即停止 

public interface Filter {
    
    public void init(FilterConfig filterConfig) throws ServletException;

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;

    public void destroy();
}

FilterChain 接口中只有一个方法 doFilter,用于控制下一个 Filter 的方法被调用

public interface FilterChain {
    public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;
}


看下 FilterChain 的简单实现

private static class VirtualFilterChain implements FilterChain {

    private final FilterChain originalChain;

    private final List<? extends Filter> additionalFilters;

    private int currentPosition = 0;

    public VirtualFilterChain(FilterChain chain, List<? extends Filter> additionalFilters) {
        this.originalChain = chain;
        this.additionalFilters = additionalFilters;
    }

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response)
            throws IOException, ServletException {

        if (this.currentPosition == this.additionalFilters.size()) {
            this.originalChain.doFilter(request, response);
        }
        else {
            this.currentPosition++;
            Filter nextFilter = this.additionalFilters.get(this.currentPosition - 1);
            nextFilter.doFilter(request, response, this);
        }
    }
}


案例二

Spring 中的拦截器 HandlerInterceptor

HandlerInterceptor 定义了 3 个方法 preHandle、postHandle、afterCompletion,调用时间见注释

public interface HandlerInterceptor {
	//Called after HandlerMapping determined an appropriate handler object, but before HandlerAdapter invokes the handler
	boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
	
	//Called after HandlerAdapter actually invoked the handler, but before the DispatcherServlet renders the view
	void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
	
	// Callback after completion of request processing, that is, after renderingthe view
	void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;

}

拦截器链 HandlerExecutionChain

public class HandlerExecutionChain {

	//执行链中拦截器的 preHandle 方法,遇到返回 false,执行 triggerAfterCompletion 方法触发
	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;
	}
	
	//DispatcherServlet 中 doDispatch 方法调用,调用链中拦截器的 postHandle 方法
	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, 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);
			}
		}
	}

	//执行链中截止到 applyPreHandle 返回 false 的 拦截器的 afterCompletion 方法
	void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, 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);
				}
			}
		}
	}

}

DispatcherServlet 中对拦截器链的调用

public class DispatcherServlet extends FrameworkServlet {
	
	//分发 servlet 请求
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		.
		.
		.
		//调用拦截器链的 applyPreHandle 方法
		if (!mappedHandler.applyPreHandle(processedRequest, response)) {
			return;
		}

		// Actually invoke the handler.
		mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

		if (asyncManager.isConcurrentHandlingStarted()) {
			return;
		}

		applyDefaultViewName(processedRequest, mv);
		
		//调用拦截器链的 applyPostHandle 方法
		mappedHandler.applyPostHandle(processedRequest, response, mv);
		.
		.
		.
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}
	
	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
		.
		.
		.
		//调用拦截器链的 triggerAfterCompletion 方法
		if (mappedHandler != null) {
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

}

【Java学习资源】整理推荐


【Java面试题与答案】整理推荐

猜你喜欢

转载自blog.csdn.net/meism5/article/details/108136497