概述
Spring MVC 是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,
在 Spring MVC 中,请求发送至前端控制器时,也就是请求会发送到 DispatcherServlet 类中的 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.检查该请求是否为文件上传请求
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
//2.根据当前请求地址URL,寻找到对应处理请求的类(处理器类);并且拿到执行链(包含拦截器)
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
//3.如果未找到对应的处理器,可能会抛出异常或者发送到错误页面 404
//response.sendError(HttpServletResponse.SC_NOT_FOUND);
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
//4.拿到该处理器类其中能处理该请求的适配器(反射工具)(即该类中标注@RequestMapping的方法)
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;
}
}
//执行所有拦截器的preHandle前置方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
//5.适配器对象去执行目标方法:将目标方法执行完后的返回值作为视图名设置保存到ModelAndView中
//目标方法无论怎样写,适配器执行完以后都会将信息封装成ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//如果没有视图名,则会设置一个默认的视图名,即当前的URL
applyDefaultViewName(processedRequest, mv);
//目标方法只要正常处理,就会执行拦截器的postHandle方法
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);
}
//6.根据方法最终执行完成后封装的ModelAndView,转发到目标页面,而且ModelAndView中的数据从请求域中获取
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);
}
}
}
}
并且在执行 Controller 的目标方法时会使用到适配器模式,利用适配器模式对 SpringMVC 做了更好的扩展;
总结
- 所有的请求发送到前端控制器(DispactherServlet),然后调用 doDispacth 方法进行处理;
- 根据 HandlerMapping 中保存的请求映射信息找到能够处理当前请求的处理器执行链(HandlerExecutionChain)(包含拦截器);
- 根据当前处理器找到它的 HandlerAdapter (适配器类);
- 接着会先执行拦截器的 perHandle 方法;
- 然后就会执行目标方法并返回 ModelAndView 对象 mv (mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); );
- 执行拦截器的postHandle;
- 将对象 mv 交给 ViewResolver 视图解析器进行解析并返回 View 对象(在方法 processDispatchResult 中);
- 将 View 对象进行页面的渲染;
- 最终 DispatcherServlet 给用户返回一个响应;