spring-mvcインターセプター
概要:
spring-mvcインターセプターは主にHandlerInterceptorインターフェースを実装します。spring-mvc のコアDispatcherServletがメイン処理リクエストメソッドdoDispatchを実行すると、プロセッサーマッパーHandlerMappingは対応するハンドラーを見つけ、リクエストオブジェクトのリクエストパスに従ってHandlerInterceptor実装クラスをラップします。 requset HandlerInterceptorChainにアセンブルすると、HandlerInterceptorChainは、ハンドラーの実行シーケンスに従って、各インターセプターの特定のメソッドを呼び出します。
HandlerInterceptorインターセプターは、主に前処理メソッドの後にリクエストを処理してインターセプトし、後処理メソッドの後に処理を実行します。特定のインターセプターの前処理が実行された場合、最終的な処理メソッドは前処理のいずれかです。割り込み要求またはエラーレポート。最終的な処理方法を実装する必要があります。
DispatcherServletの簡略化されたメイン実行コードdoDispatch()を見てみましょう
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 {
// ....
}
以下では、spring-mvcインターセプターチェーンとその他の関連クラスの簡単なシミュレーションを実装します。
1.シミュレーションの主なクラスの紹介
HandlerInterceptorインターセプター
このインターフェースには3つのメソッドがあり、それぞれ、Handler要求の実行の前後に完了した処理を表します。
リクエストの前処理:preHandle(リクエストリクエスト、レスポンスレスポンス、ハンドラーハンドラー)
リクエストの後処理:postHandle(リクエストリクエスト、レスポンスレスポンス、ハンドラーハンドラー)
リクエストの最終処理:afterCompletion(リクエストリクエスト、レスポンスレスポンス、ハンドラーハンドラー、例外exc)
HandlerExecutionChainインターセプターチェーン:
関数の概要:
インターセプターチェーンインスタンス内にList <HandlerInterceptor>変数があり、初期化中にインターセプターを追加するために使用され、intタイプのinterceptorIndex変数が使用されます。操作preHandle()メソッド、preメソッドにエラーがある場合、前操作を完了したインターセプターは、対応するafterCompletion最終処理操作を実行する必要があります。afterCompletion操作は、実行が完了したときに実行されるメソッドです。または実行エラーが発生します。
その他のクラス:
ハンドラプロセッサ、元々はプロセッサアダプタを使用してリクエストを実行しました。簡略化するには、リクエストを固定的に処理するハンドラクラスとして設定します。
リクエストリクエストクラス、msg pojo
クラスに簡略化応答応答クラス、msgに簡略化pojoクラス
2.サンプルコード
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]
}
}
コンプリート!