1.責任連鎖モデルとは何ですか
Chain of Responsibilityモデルでは、複数のプロセッサが同じリクエストを順番に処理します。要求はAプロセッサによって処理され、次にBプロセッサに渡されます。Bプロセッサが処理された後、Cプロセッサに渡され、チェーンが形成されます。チェーン内の各プロセッサは独自の処理責任を負うため、Chain ofResponsibilityモデルと呼ばれます。
GoFによって与えられた定義では、プロセッサチェーン内のプロセッサがこの要求を処理できる場合、要求を引き継ぐことはありません。実際、Chain of Responsibilityモデルにはバリエーションがあります。つまり、リクエストはすべてのプロセッサによって処理され、途中で終了することはありません。
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();
}
}
ハンドラーは、すべてのプロセッサークラスの抽象親クラスでdoHandle()
あり、抽象メソッドです。handle()
プロセッサーが通過するたびに、要求を処理できる場合は受け渡しを継続しないことを決定します。処理できない場合は、処理します。後続のプロセッサによって処理されます(つまり、call 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. SpringInterceptorソースコードの分析
カスタムインターセプターは通常、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()
:ビジネスプロセッサがリクエストを処理して実行した後、ビューが生成される前に実行されます。後処理(サービスが呼び出され、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);
}
}
}
}
}