文章目录
前言
Spring是目前Java企业级开发应用广泛的框架之一,其具有强大的生态,且得益于其提供的高扩展能力,能够减少开发成本,提高开发效率。如此优秀的框架,当然离不开各种设计模式,本文主要介绍设计模式中的责任链模式Spring框架中的应用。
一、责任链模式介绍
责任链模式属于三种设计模式分类中的** 行为型模式**,责任链模式为请求对象创建一个接收者处理链,通常接收者中会存在下一个接收者的引用,如果当前接收者无法处理当前请求时,则将请求对象传递到下一个接收者进行处理,从而实现责任链,直到可以处理请求对象为止。责任链模式中请求发送者无需知道是哪个接收者处理的请求对象以及请求对象处理的具体过程,能够很好的将请求发送者和接收者进行解耦。责任链模式通常用于各种过滤器链、拦截处理链中,例如JavaWeb中的Filter过滤器等等。下面我们来简单实现以下责任链模式。
public abstract class Logger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;
protected int level;
//责任链中的下一个接收者的引用
protected Logger nextLogger;
public void setNextLogger(Logger nextLogger){
this.nextLogger = nextLogger;
}
//调用责任链处理方法
public void logMsg(int level, String msg){
if(this.level <= level){
print(msg);
}
//让下一个接收者进行处理
if(nextLogger !=null){
nextLogger.logMessage(level, msg);
}
}
abstract protected void print(String msg);
}
public class InfoLogger extends Logger {
public InfoLogger(int level){
this.level = level;
}
@Override
protected void print(String msg) {
System.out.println("Info::Logger: " + msg);
}
}
public class ErrorLogger extends Logger {
public ErrorLogger(int level){
this.level = level;
}
@Override
protected void print(String msg) {
System.out.println("Error::Logger: " + msg);
}
}
public class DebugLogger extends Logger {
public DebugLogger(int level){
this.level = level;
}
@Override
protected void print(String msg) {
System.out.println("Debug::Logger: " + msg);
}
}
二、Spring框架中责任链模式的应用
Spring框架中责任链模式的应用有很多,包括web请求设计,security安全权限设计,aop切面设计等等。
1、Spring MVC中 HandlerExecutionChain
SpringMVC中实际上是基于Servlet的框架,当客户端发送请求到web时,都会进入DispatcherServlet中,然后根据Servlet的生命周期去执行doService方法,在doService方法中有一个关键方法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);
//获取处理对象
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//责任链模式实现一:执行调用链的前置处理
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//处理请求
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
//责任链模式实现二:执行调用链的前置处理
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
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()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
HandlerExecutionChain的责任链模式,将需要执行的HandlerInterceptor拦截器,添加在HandlerExecutionChain责任链的interceptorList集合中,然后依次执行HandlerInterceptor相应的处理方法。以preHandle方法为例,在处理方法中,根据返回的处理boolean判断是否要继续进行下面的HandlerInterceptor对象的处理,最终完成整个调用链的拦截处理。HandlerExecutionChain的实现实际上是责任链模式的一种变性用法,它减少了不同处理对象的引用依赖,采用集合的方式来存放处理链对象,降低了耦合度。
//HandlerExecutionChain的applyPreHandle方法
//责任链模式,将处理对象给接收者,并不关心内部如何处理与调用
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
//调用拦截器的preHandle方法,执行所有拦截器的preHandle处理方法
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
return true;
}
2、Spring Security中FilterChainProxy
SpringSecurity是基于Spring实现的权限认证与校验的框架,它通过将请求内容交给过滤器链进行处理,通过框架提供的默认filter以及我们定义的filter来对请求进行处理,从而实现web权限的校验。FilterChainProxy实际上实现了web中Filter过滤器,也是采用了责任链模式来实现。
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//...
if (!clearContext) {
doFilterInternal(request, response, chain);
return;
}
try {
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
doFilterInternal(request, response, chain);
}
catch (RequestRejectedException ex) {
//...
}
finally {
//...
}
}
private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//...
if (filters == null || filters.size() == 0) {
//...
firewallRequest.reset();
chain.doFilter(firewallRequest, firewallResponse);
return;
}
//...
VirtualFilterChain virtualFilterChain = new VirtualFilterChain(firewallRequest, chain, filters);
//执行虚拟调用链virtualFilterChain的doFilter方法
virtualFilterChain.doFilter(firewallRequest, firewallResponse);
}
//VirtualFilterChain是FilterChainProxy中一个静态内部类
private static final class VirtualFilterChain implements FilterChain {
private final FilterChain originalChain;
private final List<Filter> additionalFilters;
private final FirewalledRequest firewalledRequest;
private final int size;
private int currentPosition = 0;
private VirtualFilterChain(FirewalledRequest firewalledRequest, FilterChain chain,
List<Filter> additionalFilters) {
this.originalChain = chain;
this.additionalFilters = additionalFilters;
this.size = additionalFilters.size();
this.firewalledRequest = firewalledRequest;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if (this.currentPosition == this.size) {
//...
this.firewalledRequest.reset();
this.originalChain.doFilter(request, response);
return;
}
this.currentPosition++;
Filter nextFilter = this.additionalFilters.get(this.currentPosition - 1);
//...
//此处为责任链模式的实现,将请求对象交给一下一个处理方法进行处理
nextFilter.doFilter(request, response, this);
}
}
总结
本文介绍了责任链模式的使用场景和实现,并简述了Spring框架中对责任链模式的应用。实际上,在JavaWeb的Servlet规范中,包括Filter在内的组件,都是责任链模式的应用。将请求数据交给web容器,然后通过web容器执行我们创建的过滤器处理链,在这个过程中web容器并不用清楚是如何处理对象的,大大降低了请求者和接收者的耦合程度。Spring框架在保持可扩展能力的前提下,通过责任链模式来实现Web MVC的请求拦截以及Security权限过滤处理,为Web应用提供更好的支持。