处理请求是MVC中的C(Control)部分,他是MVC的核心内容。在初始化上下文是将所有的HandlerMapping都加载到handlerMappings中且根据Order排序。每个HandlerMapping 都持有URL到Controller的映射关系。
在MVC初始化完成之后,对Http请求的处理是在doService()方法中完成的。DispatcherServlet是HttptServlet的子类,对Http请求的处理是在doService()方法中完成的。
在初始化完成时,在上下文中配置的所有HandlerMapping都已经被加载了,(HandlerMap初始化) 并被排序后放在一个List中。HandlerMapping存储着Http请求和对应的处理器的映射数据。
/**
*实现Http请求和handler对象映射关系的接口 *这个接口可以被应用开发者实现,虽然这不是必须的,因为在框架中包含了BeanNameUrlHanlderMapping和SimpleUrlHandlerMapping。同*时如果没有注册任何HandlerMapping上述连个HandlerMapping是默认的HandlerMapping
* *HandlerMapping实现类支持拦截器的映射,但不是必要的。一个Handler始终包含在HandlerExutionChain实例中,也可以选择伴随一些拦*截器。DispatcherServlet首先按照顺序调用每个拦截器的preHandler方法,如果所有拦截器的的preHandler方法都返回true,最后将调**用handler自身。
**/
public interface HandlerMapping {
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";
/**
返回一个请求的处理器和所有的拦截器。该选择可以基于请求的URL,会话状态或实现类的任何因素。
返回的HandlerExecutionChain包含一个处理器对象,而不是一个标签接口,处理器没有任何形式的限制
如果没有匹配的处理器则返回null,这不是一个错误。
DispatcherServlet将会查询所有注册的HanlderMapping去查找匹配的Handler,如果没有找到任何处理器只能判定有误
*/
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
对请求的实际处理是在doDispatche()方法中完成的,其中主要步骤有:
- 准备ModelAndView,
- 调用getHandler来获取处理该请求的Handler,
- 然后通过handler响应请求返回一个ModelAndView 对象,
- 最后将这个ModelAndView交给视图对象去呈现。
doService 接收到HttpServletRequest请求,在进行请求参数初始化后就直接将请求委派给doDispatch(),线面是doService源码:
/**
* Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
* for the actual dispatching.
*/
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
logger.debug("DispatcherServlet with name '" + getServletName() + "' processing " + request.getMethod() +
" request for [" + requestUri + "]");
}
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map<String, Object> attributesSnapshot = null;
// 如果给定的请求中包含请求
if (WebUtils.isIncludeRequest(request)) {
logger.debug("Taking snapshot of request attributes before include");
attributesSnapshot = new HashMap<String, Object>();
//获取所有属性名称
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make framework objects available to handlers and view objects.
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
doDispatch(request, response);
}
finally {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
doDispatch()是HttpServletRequest请求真正被处理的类,
在该类中首先是从HandlerMappings中按照顺序检查是否有匹配的处理方法。如果在HandlerMappings中所有的handlerMap都没有匹配的处理方法则返回一个404.下面是doDispatch源码的分析:
/**
* 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 {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1;
try {
ModelAndView mv;
boolean errorView = false;
try {
// 判断请求是否是多媒体请求
processedRequest = checkMultipart(request);
// 获取当前请求的处理器HandlerExecutionChain
mappedHandler = getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
//如果没有处理器,则返回一个404
noHandlerFound(processedRequest, response);
return;
}
// 获取当前请求的Handler适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
//获取当前请求的请求方法
String method = request.getMethod();
// 判断当前请求方法是否是GET请求
boolean isGet = "GET".equals(method);
// 如果是GET请求或者是HEAD
if (isGet || "HEAD".equals(method)) {
//获取最后修改时间
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 获取拦截器
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
//如果拦截器不为空
if (interceptors != null) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
//如果处理请求被拦截,则结束请求,否则继续
if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
return;
}
interceptorIndex = i;
}
}
// 调用处理器获取一个视图
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//如果视图不为空,且有view,则设置默认视图名称
if (mv != null && !mv.hasView()) {
mv.setViewName(getDefaultViewName(request));
}
// Apply postHandle methods of registered interceptors.
if (interceptors != null) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
}
}
}
catch (ModelAndViewDefiningException ex) {
logger.debug("ModelAndViewDefiningException encountered", ex);
mv = ex.getModelAndView();
}
catch (Exception ex) {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(processedRequest, response, handler, ex);
errorView = (mv != null);
}
// 渲染视图
if (mv != null && !mv.wasCleared()) {
render(mv, processedRequest, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
// Trigger after-completion for successful outcome.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
}
catch (Exception ex) {
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
catch (Error err) {
ServletException ex = new NestedServletException("Handler processing failed", err);
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
finally {
// Clean up any resources used by a multipart request.
if (processedRequest != request) {
cleanupMultipart(processedRequest);
}
}
}
getHandler 就是遍历handlerMappings的过程,如果其中有一个handlerMappings 中有匹配的处理方法则返回该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</code> 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;
}
/**
* 查找一个给定请求的处理器,如果没有找到特定的处理器则返回一个默认处理器
* @param request current HTTP request
* @return the corresponding handler instance, or the default handler
* @see #getHandlerInternal
*/
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
// 如果没有找到处理器则使用默认值
if (handler == null) {
handler = getDefaultHandler();
}
// 如果也没有默认处理器则返回null
if (handler == null) {
return null;
}
// 找到处理器Bean的名称
if (handler instanceof String) {
String handlerName = (String) handler;
// 从上下文中获取处理器
handler = getApplicationContext().getBean(handlerName);
}
return getHandlerExecutionChain(handler, request);
}
HandlerExeutionChain 包含了Hnadler对象和一些列的拦截器
/**
* Handler execution chain, consisting of handler object and any handler interceptors.
* Returned by HandlerMapping's {@link HandlerMapping#getHandler} method.
*
* @author Juergen Hoeller
* @since 20.06.2003
* @see HandlerInterceptor
*/
public class HandlerExecutionChain {
private final Object handler;
private HandlerInterceptor[] interceptors;
private List<HandlerInterceptor> interceptorList;
在HandlerMapping中找到了当前请求的处理Handle以后,HandlerAdapter将会调用这个处理器处理请求
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//获取处理器类
Class<?> clazz = ClassUtils.getUserClass(handler);
//从缓存中获取这个处理器的值,
Boolean annotatedWithSessionAttributes = this.sessionAnnotatedClassesCache.get(clazz);
//如果缓存中没有值,则判断这个处理器即controller上是否有@SessionAttribute注解,并将其放入到缓存中
if (annotatedWithSessionAttributes == null) {
annotatedWithSessionAttributes = (AnnotationUtils.findAnnotation(clazz, SessionAttributes.class) != null);
this.sessionAnnotatedClassesCache.put(clazz, annotatedWithSessionAttributes);
}
if (annotatedWithSessionAttributes) {
checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
}
else {
checkAndPrepare(request, response, true);
}
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return invokeHandlerMethod(request, response, handler);
}
}
}
return invokeHandlerMethod(request, response, handler);
}
//处理器调用处
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
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;
}