recently, not in the csdn to write articles, go to * Jane Book *, interested can pay attention to.
In the previous article, we introduced the use and application scenarios of spring MVC handlerinterceptor, and in this article we will study its internal implementation in conjunction with the Spring MVC source code.
This article analyzes the use of the spring Framework source code for the Spring Framework 4.3.4.RELEASE .
First, let's take a look at the Org.springframework.web.servlet.DispatcherServlet Dodispatch method:
protected void Dodispatch (HttpServletRequest request, httpservletresponse response) throws Exception {Httpse
Rvletrequest 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);
Determine handler for the current request.
Mappedhandler = GetHandler (processedrequest); if (Mappedhandler = = NULL | | Mappedhandler.gethandler () = = null) {Nohandlerfound (processedrequest, re
Sponse);
Return
}//Determine handler adapter for the current request. HaNdleradapter ha = Gethandleradapter (Mappedhandler.gethandler ());
Process last-modified Header, if supported by the handler.
String method = Request.getmethod ();
Boolean isget = "GET". Equals (method); if (Isget | |
"HEAD". Equals (method)) {Long lastmodified = ha.getlastmodified (Request, Mappedhandler.gethandler ()); if (logger.isdebugenabled ()) {Logger.debug ("last-modified value for [" + GETR
Equesturi (Request) + "] is:" + lastmodified);
} if (new Servletwebrequest (request, Response). Checknotmodified (lastmodified) && isget) {
Return }}//Call registered Handlerinterceptor's Prehandle () method if (!mappedhandler.applyprehan
Dle (processedrequest, Response)) {return; }//Real execution Controller correspondenceMethod mv = Ha.handle (processedrequest, Response, Mappedhandler.gethandler ());
if (asyncmanager.isconcurrenthandlingstarted ()) {return;
} applydefaultviewname (Processedrequest, MV);
Call the registered Handlerinterceptor Posthandle () method Mappedhandler.applyposthandle (processedrequest, response, MV);
} catch (Exception ex) {dispatchexception = ex; } catch (Throwable err) {//As of 4.3, we ' re processing Errors thrown from handler methods as
Well,//making them available for @ExceptionHandler methods and other scenarios.
Dispatchexception = new Nestedservletexception ("Handler dispatch failed", err);
} processdispatchresult (Processedrequest, Response, Mappedhandler, MV, dispatchexception); } catch (Exception ex) {//Call registered HandlErinterceptor aftercompletion () method Triggeraftercompletion (processedrequest, Response, Mappedhandler, ex); } catch (Throwable err) {//Call the Aftercompletion () method of the registered Handlerinterceptor Triggerafterco Mpletion (processedrequest, Response, Mappedhandler, New Nestedservletexception ("Handler processing FAI
Led ", err)); } finally {if (asyncmanager.isconcurrenthandlingstarted ()) {//Instead of Posthandle and aftercompletion if (mappedhandler! = null) {//calls the Afterconcu of registered Handlerinterceptor Rrenthandlingstarted () method mappedhandler.applyafterconcurrenthandlingstarted (processedrequest, response)
;
}} else {//clean up any of the resources used by a multipart request.
if (multipartrequestparsed) {Cleanupmultipart (processedrequest);
} }}}/** * Handle The result of handler selection and handler invocation, which is * ei
Ther a modelandview or an Exception to is resolved to a modelandview. */private void Processdispatchresult (HttpServletRequest request, httpservletresponse response, Handlerexe
Cutionchain Mappedhandler, Modelandview mv, Exception Exception) throws Exception {Boolean errorview = false; if (Exception! = null) {if (Exception instanceof Modelandviewdefiningexception) {log
Ger.debug ("Modelandviewdefiningexception encountered", exception);
MV = ((modelandviewdefiningexception) exception). Getmodelandview ();
} else {Object handler = (Mappedhandler! = null? Mappedhandler.gethandler (): null);
MV = processhandlerexception (request, response, handler, exception);
Errorview = (mv! = null);
}
}Did the handler return a view to render?
if (mv! = null &&!mv.wascleared ()) {render (MV, request, response);
if (Errorview) {webutils.clearerrorrequestattributes (request); }} else {if (logger.isdebugenabled ()) {Logger.debug ("Null Modelandview Retu Rned to Dispatcherservlet with Name ' "+ getservletname () +" ': Assuming Handleradapter completed
Request Handling "); }} if (Webasyncutils.getasyncmanager (Request). Isconcurrenthandlingstarted ()) {//Concurrent
Handling started during a forward return; if (Mappedhandler! = null) {//invokes the Aftercompletion () method of the registered Handlerinterceptor Mappedhandle
R.triggeraftercompletion (request, response, NULL); }
}
Next, let's take a look at the Applyprehandle method implementation of Handlerexecutionchain:
/** * Performs the Prehandle method of registering all handlerinterceptor on the request */Boolean applyprehandle (HttpServletRequest request
, httpservletresponse response) throws Exception {handlerinterceptor[] interceptors = getinterceptors (); if (! Objectutils.isempty (interceptors)) {for (int i = 0; i < interceptors.length; i++) {Handle
Rinterceptor interceptor = interceptors[i]; if (!interceptor.prehandle (Request, Response, This.handler)) {triggeraftercompletion (Request, respons
e, NULL);
return false;
} this.interceptorindex = i;
}} return true; } public handlerinterceptor[] Getinterceptors () {if (this.interceptors = = null && This.interceptorli St! = null) {this.interceptors = This.interceptorList.toArray (New Handlerinterceptor[this.interceptorlist.siz
E ()]); } return This.interceptors;
}
Handlerexecutionchain's Applyposthandle method implementation:
/**
* Performs the Posthandle method of registering all handlerinterceptor on the request *
/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 in Terceptor = Interceptors[i];
Interceptor.posthandle (Request, Response, This.handler, MV);}}}
Handlerexecutionchain's Triggeraftercompletion method implementation:
/**
* Performs the Aftercompletion method of registering all handlerinterceptor on the request *
/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 int Erceptor = Interceptors[i];
try {
interceptor.aftercompletion (request, Response, This.handler, ex);
}
catch (Throwable ex2) {
logger.error ("Handlerinterceptor.aftercompletion threw exception", EX2);
}
}
}
}
Finally, Handlerexecutionchain's Applyafterconcurrenthandlingstarted method is implemented:
/** * Execute Asynchandlerinterceptor method of all afterconcurrenthandlingstarted registered to the request */ void applyafterconcurrenthandlingstarted (HttpServletRequest request, httpservletresponse response) {Handlerinte
Rceptor[] interceptors = getinterceptors (); if (! Objectutils.isempty (interceptors)) {for (int i = interceptors.length-1; I >= 0; i--) {i F (interceptors[i] instanceof Asynchandlerinterceptor) {try {Asynchandlerint
Erceptor asyncinterceptor = (asynchandlerinterceptor) interceptors[i];
asyncinterceptor.afterconcurrenthandlingstarted (Request, response, This.handler); } catch (Throwable ex) {Logger.error ("interceptor [" + Interceptors[i] + "] f
Ailed in Afterconcurrenthandlingstarted ", ex); }
}
}
}
}
I add comments to the above methods, and the code is better understood, I will not talk nonsense.
Next, the interceptor array inside the Handlerexecutionchain is initialized at what time.
Look at the definition of Handlerexecutionchain class, the source code is as follows:
Package org.springframework.web.servlet;
Import java.util.ArrayList;
Import Java.util.Arrays;
Import java.util.List;
Import Javax.servlet.http.HttpServletRequest;
Import Javax.servlet.http.HttpServletResponse;
Import Org.apache.commons.logging.Log;
Import Org.apache.commons.logging.LogFactory;
Import Org.springframework.util.CollectionUtils;
Import Org.springframework.util.ObjectUtils; public class Handlerexecutionchain {private static final Log logger = Logfactory.getlog (Handlerexecutionchain.class)
;
Private final Object handler;
Private handlerinterceptor[] interceptors;
Private list
Handlerexecutionchain provides the Addinterceptors () method to add Handlerinterceptor, where addinterceptors is called.
We return to Dispatcherservlet's Dodispatch method, as follows:
protected void Dodispatch (HttpServletRequest request, httpservletresponse response) throws Exception {Httpse
Rvletrequest 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);
Gets the current request corresponding to the handler Mappedhandler = GetHandler (processedrequest); if (Mappedhandler = = NULL | | Mappedhandler.gethandler () = = null) {Nohandlerfound (processedrequest, re
Sponse);
Return
}
...
}
catch (Exception ex) {dispatchexception = ex; } catch (Throwable 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 {...} }/** * Gets the current request for the corresponding Handlerexecutionchain */protected Handlerexecutionchain gethandler (httpservletrequest Request) throws Exception {for (handlermapping hm:this.handlerMappings) {if (logger.istraceenable D ()) {Logger.trace ("Testing handler map [" + HM + "] in Dispatcherservlet with n
Ame ' "+ getservletname () +" ' "); } HandlerexeCutionchain handler = Hm.gethandler (request);
if (handler! = NULL) {return handler;
}} return null; }
Then take a look at the GetHandler (request) method of handlermapping, Handlermapping is an interface, gethandler (request) The method is implemented in Abstracthandlermapping, as follows:
@Override Public final Handlerexecutionchain gethandler (HttpServletRequest request) throws Exception {//
Gets the request corresponding to the handler Object handler = gethandlerinternal (request);
if (handler = = null) {handler = Getdefaulthandler ();
} if (handler = = null) {return null;
}//Bean name or resolved handler?
if (handler instanceof string) {string handlerName = (string) handler;
Handler = Getapplicationcontext (). Getbean (HandlerName); }//According to handler construction Handlerexecutionchain handlerexecutionchain executionchain = Gethandlerexecutionchain (Handl
er, request); if (corsutils.iscorsrequest (Request)) {Corsconfiguration GlobalConfig = This.corsConfigSource.getCorsConfigur
ation (Request);
Corsconfiguration handlerconfig = getcorsconfiguration (handler, request); corsconfiguration config = (GlobalConfig! = null? globalconfig.combiNE (handlerconfig): Handlerconfig);
Executionchain = Getcorshandlerexecutionchain (request, Executionchain, config);
} return Executionchain; }/** * Constructs Handlerexecutionchain and initializes handlerinterceptor */protected Handlerexecutionchain Gethandlerex Ecutionchain (Object handler, HttpServletRequest request) {Handlerexecutionchain chain = (Handler instanceof Handl
Erexecutionchain?
(Handlerexecutionchain) Handler:new Handlerexecutionchain (handler));
String Lookuppath = this.urlPathHelper.getLookupPathForRequest (request); for (Handlerinterceptor interceptor:this.adaptedInterceptors) {if (Interceptor instanceof Mappedinterceptor
) {Mappedinterceptor Mappedinterceptor = (mappedinterceptor) interceptor; if (Mappedinterceptor.matches (Lookuppath, This.pathmatcher)) {Chain.addinterceptor (mappedinterceptor.
Getinterceptor ()); }
} else {chain.addinterceptor (Interceptor);
}} return chain; }
The
Source code analysis is here to end.