文章目录
概述
DispatcherServlet继承自HttpServlet类,是spring mvc对servlet的具体实现。而最关键的实现代码就在doDispatch方法中。先看看doDispatch的具体实现
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//1检查是否Multipart请求(文件上传),如果是,调用MultipartResolver.resolveMultipart(HttpServletRequest)解析Multipart资源,返回一个适配类MultipartHttpServletRequest,否则返回参数中的request。
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 2.根据url获取一个具体的HanderMapper对象,让后封装成HandlerExecutionChain对象。
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// 3.根据handler找到对应的handlerAdapter
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;
}
}
//4调用拦截器的 preHandle 方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 5调用具体的接口方法,并返回模型视图对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//6.调用拦截器postHandle方法
applyDefaultViewName(processedRequest, mv);
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);
}
//7调用processDispatchResult方法处理Handler处理之后的结果
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 {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
MultipartResolver
checkMultipart调用multipartResolver.resolveMultipart(request)解析Multipart资源,实际上这个方法返回了一个MultipartHttpServletRequest接口的实现对象,MultipartHttpServletRequest接口继承了HttpServletRequest和MultipartRequest,获取文件的操作都在MultipartRequest中定义。其中MultipartResolver默认有两个实现类,分别是CommonsMultipartResolver和StandardServletMultipartResolver
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
"this typically results from an additional MultipartFilter in web.xml");
}
else if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) instanceof MultipartException) {
logger.debug("Multipart resolution failed for current request before - " +
"skipping re-resolution for undisturbed error rendering");
}
else {
//解析
return this.multipartResolver.resolveMultipart(request);
}
}
// If not returned before: return original request.
return request;
}
获取HandlerExecutionChain
HandlerExecutionChain只能通过HanderMapping接口中的唯一方法来获得,HandlerMapping实例对象的getHandler方法可以获得一个HandlerExecutionChain对象实例,该实例封装了一个handler处理对象和一些interceptors。
Object handler;不做过多介绍,存储的对象是HandlerMethod
HandlerInterceptor[] interceptors :所有的HandlerInterceptor的数组
List<HandlerInterceptor> interceptorList:所有的HandlerInterceptor的链表
HandlerMapping 是由 DispatcherServlet 调用,DispatcherServlet 会从容器中取出所有 HandlerMapping 实例并遍历,让 HandlerMapping 实例根据自己实现类的方式去尝试查找 Handler
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 这些 HandlerMapping 在容器初始化时创建,在 initHandlerMappings 时放入集合中
for (HandlerMapping hm : this.handlerMappings) {
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
HandlerMapping
HanderMapping接口定义如下
我们可以在应用中使用预先构建的或者提供好的HandlerMapping的任何实现类,用来控制请求到处理对象之间的路由的。默认的实现类是:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping和org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.
HanderMapping接口定义如下:
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 MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";
//该方法是HandlerMapping接口中的唯一方法,此方法可以利用用户请求request中的信息来生成HandlerExecutionChain对象
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
HandlerMethod
HandlerMethod其实可以简单理解为保持方法信息的pojo.就springMVC的Controller来说就是某个url对应的某个Controller执行的方法。
定义如下
package org.springframework.web.method;
public class HandlerMethod {
protected final Log logger = LogFactory.getLog(HandlerMethod.class);
// 方法所在的类,如果是String类型,可以去容器中获取
private final Object bean;
// 方法
private final Method method;
// 类管理的容器
private final BeanFactory beanFactory;
// 方法的参数
private final MethodParameter[] parameters;
// 如果方法是bridged方法,则对应原始方法
private final Method bridgedMethod;
// ...
}
Interceptor 拦截器
HandlerInterceptor接口
在preHandler阶段,要遍历执行所有的HandlerInterceptor ,执行preHandle。
拦截器的总接口 HandlerInterceptor 定义如下:
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
}
HandlerIntercetor共有13个实现类.
HandlerAdapter
根据 Handler 来找到支持它的 HandlerAdapter,通过 HandlerAdapter 执行这个 Handler 得到 ModelAndView 对象。