先上图:
- 百度里的:
- 自己仿着画的
- BigDevil_ 画的
再上文字描述:
转载自:一页知秋否
SpringMVC的具体工作原理
1、客户端用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 HandlerMapping处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、DispatcherServlet调用HandlerAdapter处理器适配器,HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
5、Controller控制器执行完成返回ModelAndView,HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
6、 DispatcherServlet前端控制器将ModelAndView传给ViewReslover视图解析器。
7、 ViewReslover解析后返回具体View。
8、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中),并返回给客户端用户。
最后上源码:
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 {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// -------------- 这是 前端控制器 请求查询 处理器 的过程 start ----------------
// Determine handler for the current request.
// 1、请求HandlerMapping处理器映射器查询Handler处理器
// 返回HandlerExecutionChain处理执行链:1~n个拦截器和处理器handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// -------------- 这是 前端控制器 请求查询 处理器 的过程 end ----------------
// -------------- 这是 前端控制器 请求执行 处理器 的过程 start ----------------
// Determine handler adapter for the current request.
// 2、根据处理器执行链的处理器对象获取处理器适配器
// 先从处理器执行链HandlerExecutionChain中获取处理器对象Handler
// 再从处理器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;
}
}
//--------调用preHandle-----------
// 3、正序遍历HandlerExecutionChain的拦截器数组
// 依次执行拦截器的preHandle方法
// 提示:下面的mappedHandler即为HandlerExecutionChain对象
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// --------调用 目标方法------
// 4、HandlerAdapter处理器适配器调用handle方法获取ModelAndView对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(request, mv);
// --------调用 postHandle------
// 5、逆序遍历HandlerExecutionChain的拦截器数组
// 依次执行拦截器的postHandle方法
// 提示:下面的mappedHandler即为HandlerExecutionChain对象
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
// -------------- 这是 前端控制器 请求执行 处理器 的过程 end ----------------
// -------------- 这是 前端控制器 请求解析 视图 的过程 start ----------------
// (方法的详细内容见下面的processDispatchResult方法)
// 6、请求视图解析器解析ModelAndView对象
// 并调用View对象的render方法真正的实际渲染视图
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
// -------------- 这是 前端控制器 请求解析 视图 的过程 end ----------------
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
/**
* Apply afterConcurrentHandlerStarted callback on mapped AsyncHandlerInterceptors.
*/
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
// 接第6步:请求视图解析器解析视图(详细见下面的processDispatchResult方法)
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
// 6.1 前端控制器请求视图解析器解析ModelAndView对象(render的详细代码见下面)
// 渲染给定的ModelAndView,这是处理请求的最后一个阶段。
// 它可能涉及通过名称解析视图。
render(mv, request, 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");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
if (mappedHandler != null) {
// 6.2 逆序遍历HandlerExecutionChain的拦截器数组
// 依次执行拦截器的afterCompletion方法
// 提示:下面的mappedHandler即为HandlerExecutionChain对象
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
// 接第6.1步:前端控制器请求视图解析器解析ModelAndView对象(详细代码在下面)
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine locale for request and apply it to the response.
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view;
if (mv.isReference()) {
// We need to resolve the view name.
// 6.1.1 通过名称解析视图
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
else {
// No need to lookup: the ModelAndView object contains the actual View object.
// 6.1.2 获取View对象
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name '" + getServletName() + "'");
}
}
// Delegate to the View object for rendering.
if (logger.isDebugEnabled()) {
logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
}
try {
// 6.1.3 调用View对象的render来呈现视图
// 渲染指定模型的视图。
// 第一步是准备请求:在JSP的情况下,这意味着将模型对象设置为请求属性。
// 第二步是视图的实际渲染
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
getServletName() + "'", ex);
}
throw ex;
}
}