HandlerAdapter接口中定义的方法为ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
看这个方法就明白了,就是HanlerMapping负责找到Handler(更具体的是找到Handler中处理的方法),然后交给HandlerAdapter负责执行这个方法,最终返回视图对象ModelAndView 。
Spring中默认定义的HandlerAdapter为HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、AnnotationMethodHandlerAdapter ,重点也就是在这三个类,下面分别来看下关键代码。
- HttpRequestHandlerAdapter
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//返回null,相当于空白处理
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}
具体的处理交给了HttpRequestHandler类,看下这个类的继承关系:
这里看下有代表性的DefaultServletHttpRequestHandler类的实现。
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher rd =this.servletContext.getNamedDispatcher(this.defaultServletName);
//简单的forward
rd.forward(request, response);
}
- SimpleControllerHandlerAdapter
这个类返回的对象是ModelAndView,这是和HttpRequestHandlerAdapter的不同之处。
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler){
return ((Controller) handler).handleRequest(request, response);
}
通过上面代码我们知道实际的处理在Controller类中。其中handleRequest()的默认实现是在抽象的类AbstractController中。
AbstractController实现了一些特殊功能,如继承了WebContentGenerator缓存控制功能,并提供了可选的会话的串行化访问功能。而且提供了handleRequestInternal方法。
//委托给WebContentGenerator进行缓存控制
checkAndPrepare(request, response, this instanceof LastModified);
// Execute handleRequestInternal in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return handleRequestInternal(request, response);
}
}
}
然后看抽象方法handleRequestInternal()在子类中的实现,这里以AbstractUrlViewController为例说明,关键代码如下:、
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
//交给子类去实现
String viewName = getViewNameForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Returning view name '" + viewName + "' for lookup path [" + lookupPath + "]");
}
//这才是关键
return new ModelAndView(viewName, RequestContextUtils.getInputFlashMap(request));
}
getViewNameForRequest在子类UrlFilenameViewController中实现,看代码:
protected String getViewNameForUrlPath(String uri) {
String viewName = this.viewNameCache.get(uri);
if (viewName == null) {
//通过/index.html得到 index
viewName = extractViewNameFromUrlPath(uri);
//将前缀和后缀组合
viewName = postProcessViewName(viewName);
this.viewNameCache.put(uri, viewName);
}
return viewName;
}
- AnnotationMethodHandlerAdapter
这是基于注解配置的handler,只要是注解的肯定用到反射调用。
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler){
ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
Method handlerMethod = methodResolver.resolveHandlerMethod(request);
ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ExtendedModelMap implicitModel = new BindingAwareModelMap();
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
ModelAndView mav =
methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
return mav;
}