SpringMVC全过程略写图
-
用户发送请求,经过前端控制器Dispacherservlet(Controller的核心)将url交给处理器映射器HandlerMapping处理
-
处理器映射器HandlerMapping处理url,返回HandlerExecutionChain(可能包含拦截器,一定包含自定义的Controller(handler))
-
前端控制器将Controller交给处理器适配器HandlerAdapter处理,处理完成后,返回MV对象(ModelAndView)
-
前端控制器将MV交给视图解析器处理ViewResolver,处理的过程:将MV拆分成Model和view两个对象,并且将model渲染到view视图上,并且将view返回给前端控制器。
-
最后,前端控制器将视图响应给用户
用户发送请求到DispatchServlet,请求查询Handle到处理器映射器(HandleMapping),此时返回一个处理器拦截器链到dispatchServlet之后再请求执行Handler到处理器适配器去选择相应处理器(就是Controller),处理器返回一个ModelAndView之后再转达到dispatchServlet,dispatchServlet在向视图解析器(ViewResolver)请求解析视图,之后视图解析器返回一个View对象给dispatchServlet,前端控制器在渲染视图,之后在响应给用户。
SpringMVC全过程详解
首先我们大家都知道SpringMvc是通过DispatcherServlet
这个类和web.xml配置中的拦截来接管Tomcat中的请求的。所有想看所有关于控制器(打了Controller注解)的细节基本都是在DispatcherServlet这个类中,下面我们就来看看DispatcherServlet
中的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 {
//可以看出springMVC最先初始化的是文件上传组件
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//为request请求找到对应的处理器
(源码在下一个三级标题)
mappedHandler = getHandler(processedRequest);
//非空判断
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
//
很明显这是为了拿到处理器适配器了
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//
获取Method,并且在下面代码就开始和Method比较了
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
真正执行处理器适配的方法,返回ModelAndView对象了
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//是否需要解析view name ,渲染时需要。
applyDefaultViewName(processedRequest, mv);
//执行处理器的postHandler方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
//下一步的方法就是拿着ModelAndView去render(渲染)了,至此程序跑完,页面也出来了(这一步也有视图解析器工作流程)
//将map和model参数保存在request中是在internResourceView的exposeModelRequestAttribute
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
mappedHandler = getHandler(processedRequest)源码:
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//此时会拿到所有的处理器映射器进行匹配
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
//通过处理器映射器去找到对应的处理器(三级标题为getHandler)
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
处理器映射器(handlerMappings):
getHandler(我们写的Controller其实就是Handler)
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//通过这个方法来找到处理器,也就是Controller
Object handler = getHandlerInternal(request);
//很神奇spring做了两次null处理
if (handler == null) {
handler