设计模式:职责链模式

1、什么是职责链模式

在职责链模式中,多个处理器依次处理同一个请求。一个请求先经过A处理器处理,然后再把请求传递给B处理器,B处理器处理完后再传递给C处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式

在GoF给出的定义中,如果处理器链上的某个处理器能够处理这个请求,那就不会继续往下传递请求。实际上,职责链模式还有一种变体,那就是请求会被所有的处理器都处理一遍,不存在中途终止的情况

在这里插入图片描述

2、代码实现

1)、使用链表来存储处理器

public abstract class Handler {
    
    
    protected Handler nextHandler = null;

    public void setNextHandler(Handler nextHandler) {
    
    
        this.nextHandler = nextHandler;
    }

    public final void handle() {
    
    
        boolean handled = doHandle();
        if (nextHandler != null && !handled) {
    
    
            nextHandler.handle();
        }
    }

    protected abstract boolean doHandle();
}
public class HandlerA extends Handler {
    
    
    @Override
    protected boolean doHandle() {
    
    
        boolean handled = false;
        System.out.println("HandlerA doHandle()");
        return handled;
    }
}
public class HandlerB extends Handler {
    
    
    @Override
    protected boolean doHandle() {
    
    
        boolean handled = false;
        System.out.println("HandlerB doHandle()");
        return handled;
    }
}
public class HandlerChain {
    
    
    private Handler head = null;
    private Handler tail = null;

    public void addHandler(Handler handler) {
    
    
        handler.setNextHandler(null);
        if (head == null) {
    
    
            head = handler;
            tail = handler;
            return;
        }
        tail.setNextHandler(handler);
        tail = handler;
    }

    public void handle() {
    
    
        if (head != null) {
    
    
            head.handle();
        }
    }
}
public class Application {
    
    
    public static void main(String[] args) {
    
    
        HandlerChain chain = new HandlerChain();
        chain.addHandler(new HandlerA());
        chain.addHandler(new HandlerB());
        chain.handle();
    }
}

Handler是所有处理器类的抽象父类,doHandle()是抽象方法,handle()决定了每经过一个处理器,如果它能处理该请求,就不继续往下传递;如果不能处理,则交由后面的处理器来处理(也就是调用nextHandler.handle())。HandlerChain是处理器链,从数据结构的角度来看,它就是一个记录了链头、链尾的链表。其中,记录链尾是为了方便添加处理器

2)、使用数组来存储处理器

public interface IHandler {
    
    
    boolean handle();
}
public class HandlerA implements IHandler {
    
    
    @Override
    public boolean handle() {
    
    
        boolean handled = false;
        System.out.println("HandlerA handle()");
        return handled;
    }
}
public class HandlerB implements IHandler {
    
    
    @Override
    public boolean handle() {
    
    
        boolean handled = false;
        System.out.println("HandlerB handle()");
        return handled;
    }
}
public class HandlerChain {
    
    
    private List<IHandler> handlers = new ArrayList<>();

    public void addHandler(IHandler handler) {
    
    
        this.handlers.add(handler);
    }

    public void handle() {
    
    
        for (IHandler handler : handlers) {
    
    
            boolean handled = handler.handle();
            if (handled) {
    
    
                break;
            }
        }
    }
}
public class Application {
    
    
    public static void main(String[] args) {
    
    
        HandlerChain chain = new HandlerChain();
        chain.addHandler(new HandlerA());
        chain.addHandler(new HandlerB());
        chain.handle();
    }
}

3、Spring Interceptor源码剖析

自定义Interceptor一般会实现HandlerInterceptor接口中的方法:

public interface HandlerInterceptor {
    
    

	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
    
    

		return true;
	}

	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
    
    
	}

	default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable Exception ex) throws Exception {
    
    
	}

}
  • preHandle():在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理
  • postHandle():在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView
  • afterCompletion():在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面)

在这里插入图片描述

Spring Interceptor是基于职责链模式实现,一个请求的处理流程如上图所示,HandlerExecutionChain类是职责链模式中的处理器链,核心代码如下:

public class HandlerExecutionChain {
    
    	

	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;
	}

	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable 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);
			}
		}
	}

	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--) {
    
    
				HandlerInterceptor interceptor = interceptors[i];
				try {
    
    
					interceptor.afterCompletion(request, response, this.handler, ex);
				}
				catch (Throwable ex2) {
    
    
					logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
				}
			}
		}
	}
}  

猜你喜欢

转载自blog.csdn.net/qq_40378034/article/details/112732766