第一部分
Spring MVC所有的開(kāi)始都會(huì)集中在Servlet上面许饿,查看Spring MVC的源碼窖贤,你會(huì)發(fā)現(xiàn)Servlet中的所有處理請(qǐng)求的方法(doGet拜效、doPost...)鲫构,最后都會(huì)委托給
org.springframework.web.servlet.DispatcherServlet
中的doDispatch(HttpServletRequest request, HttpServletResponse response)
方法,而這個(gè)方法包含了一個(gè)請(qǐng)求從被分發(fā)奋救,處理岭参,通過(guò)HTTP返回瀏覽器數(shù)據(jù)(response.XXX)的所有邏輯,也就是說(shuō)一個(gè)request的一生都會(huì)在這里度過(guò)尝艘。對(duì)于演侯,核心代碼,下面的源碼中已經(jīng)打上注釋背亥∶爰剩可以先看第二部分,再看下面的源碼狡汉,這里不再贅述娄徊。
spring mvc的攔截器嚴(yán)格上說(shuō)不是責(zé)任鏈模式,但是就是責(zé)任鏈的思想轴猎,但比其更復(fù)雜嵌莉。HandlerInterceptor帶給我們的是一種具有高靈活性的細(xì)粒度的請(qǐng)求處理流程的攔截方案进萄。
/**
* Process the actual dispatching to the handler.
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// ★根據(jù)請(qǐng)求(HttpServletRequest)找到對(duì)應(yīng)的HandlerExecutionChain
//(包含該request對(duì)應(yīng)的Handler和一系列攔截器HandlerInterceptor)
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
//★找到Handler對(duì)應(yīng)的適配器捻脖,方便DispatcherServlet了(正確調(diào)用Handler中的處理方法)
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 [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//★依次調(diào)用該request的所有攔截器的preHandler方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
//★真正開(kāi)始調(diào)用Handler中的處理方法,即請(qǐng)求被分發(fā)到Handler中處理
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//★依次調(diào)用該request的所有攔截器的prePost方法
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);
}
//Handler的handle(...)執(zhí)行后中鼠,返回ModelAndView后可婶,這里主要的工作:
//根據(jù)ModelAndView找到view,渲染援雇,交給response返回
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
}
第二部分
- 1矛渴、首先看
org.springframework.web.servlet.DispatcherServlet
,里面有一個(gè)重要的成員變量handlerMappings。
/** List of HandlerMappings used by this servlet */
private List<HandlerMapping> handlerMappings;
看到熟悉的HandlerMapping
吧惫搏,我們知道這個(gè)接口具温,主要工作是幫助DispatcherServlet
進(jìn)行Web請(qǐng)求的URL到具體處理類的匹配。
/**
* Interface to be implemented by objects that define a mapping between
* requests and handler objects.
**/
public interface HandlerMapping {
/**
* Return a handler and any interceptors for this request. The choice may be made
* on request URL, session state, or any factor the implementing class chooses.
* <p>The returned HandlerExecutionChain contains a handler Object, rather than
* even a tag interface, so that handlers are not constrained in any way.
* For example, a HandlerAdapter could be written to allow another framework's
* handler objects to be used.
* <p>Returns {@code null} if no match was found. This is not an error.
* The DispatcherServlet will query all registered HandlerMapping beans to find
* a match, and only decide there is an error if none can find a handler.
* @param request current HTTP request
* @return a HandlerExecutionChain instance containing handler object and
* any interceptors, or {@code null} if no mapping found
* @throws Exception if there is an internal error
*/
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
- 2筐赔、現(xiàn)在看看
org.springframework.web.servlet.DispatcherServlet
铣猩,根據(jù)請(qǐng)求找到具體的Handler(我們用的最多的Handler就是Controller)的getHandler(...)方法吧! - 我們?cè)谶@個(gè)方法里面可以發(fā)現(xiàn),會(huì)遍歷所有的HandlerMapping茴丰,將為request找Handler委托給HandlerMapping达皿,說(shuō)白了天吓,就是一個(gè)個(gè)試。如果找到就會(huì)返回一個(gè)
HandlerExecutionChain
.
/**
* Return the HandlerExecutionChain for this request.
* <p>Tries all handler mappings in order.
* @param request current HTTP request
* @return the HandlerExecutionChain, or {@code null} if no handler could be found
*/
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
- 3峦椰、我們知道在Spring MVC中龄寞,任何可以用于Web請(qǐng)求處理的處理對(duì)象統(tǒng)稱為Handler(Controller是Handler的一種特殊類型)。也就是可能會(huì)有很多類型的Handler那么
org.springframework.web.servlet.DispatcherServlet
是如何判斷我們使用的是哪一種類型汤功?又如何決定調(diào)用哪一個(gè)方法處理請(qǐng)求呢物邑? - 我們會(huì)在
org.springframework.web.servlet.DispatcherServlet
發(fā)現(xiàn)這樣一個(gè)成員變量。
/** List of HandlerAdapters used by this servlet */
private List<HandlerAdapter> handlerAdapters;
這時(shí)冤竹,我們的
HandlerAdapter
就要登場(chǎng)了拂封!它就是為了解決不同類型的Handler對(duì)DispatcherServlert造成的困擾而生的。每種Handler都應(yīng)該有對(duì)應(yīng)的HandlerAdapter鹦蠕,然后DispatcherHandler只要根據(jù)Handler冒签,找到對(duì)應(yīng)的HandlerAdapter,然后調(diào)用HandlerAdapter中的
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
即可正確調(diào)用Handler中的處理方法钟病。這部分邏輯在DispatcherServlet中的doDispatch(...)方法中萧恕。
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
...
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
public interface HandlerAdapter {
/**
* Given a handler instance, return whether or not this {@code HandlerAdapter}
* can support it. Typical HandlerAdapters will base the decision on the handler
* type. HandlerAdapters will usually only support one handler type each.
* <p>A typical implementation:
* <p>{@code
* return (handler instanceof MyHandler);
* }
* @param handler handler object to check
* @return whether or not this object can use the given handler
*/
boolean supports(Object handler);
/**
* Use the given handler to handle this request.
* The workflow that is required may vary widely.
* @param request current HTTP request
* @param response current HTTP response
* @param handler handler to use. This object must have previously been passed
* to the {@code supports} method of this interface, which must have
* returned {@code true}.
* @throws Exception in case of errors
* @return ModelAndView object with the name of the view and the required
* model data, or {@code null} if the request has been handled directly
*/
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
/**
* Same contract as for HttpServlet's {@code getLastModified} method.
* Can simply return -1 if there's no support in the handler class.
* @param request current HTTP request
* @param handler handler to use
* @return the lastModified value for the given handler
* @see javax.servlet.http.HttpServlet#getLastModified
* @see org.springframework.web.servlet.mvc.LastModified#getLastModified
*/
long getLastModified(HttpServletRequest request, Object handler);
}
最后看看org.springframework.web.servlet.DispatcherServlet
中的getHandlerAdapter就會(huì)一目了然。
/**
* Return the HandlerAdapter for this handler object.
* @param handler the handler object to find an adapter for
* @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
*/
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
//判斷該HandlerAdapter是否支持該Handler
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
- 4.現(xiàn)在
org.springframework.web.servlet.DispatcherServlet
終于可以聰明的為每個(gè)request肠阱,找到對(duì)應(yīng)的Handler了票唆。