这篇文章,DispatcherServlet是个重点,谈springmvc绕不开他,我们使用他作为springmvc接管web项目request的入口(在web.xml)中配置。
所以,接下来,将这位老大哥的身子贴在下面,请大家文明阅览:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var19) {
dispatchException = var19;
}
this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception var20) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20);
} catch (Error var21) {
this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var21);
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
理解springmvc的执行流程,不会让你瞬间理解整个springmvc框架所有高级用法,因为这种水平是经验的积累,但是却能大大加快这个进程,理解springmvc相当于牵到的马鼻子,驯服烈马也就简单了些,闲言少叙,进入正题。
springmvc中有几个重要角色,我在这里列一下:
request:不只springmvc,所有的web请求都是从他开始,您的鼠标轻轻一点,request寄托着您的思念来到了我家的服务器端口前,准备破口而入。
HandlerExecutionChain:处理器拦截器链,springmvc对request的映射
HandlerAdapter:处理器适配器(适配器模式)
接下来简单描述一下springmvc的处理流程:
我们web容器启动,监听http接口(大多数为80),一个request到达,查看web.xml文件,发现配置了url-pattern将请求处理接手,这个接手处理的servlet就是DispatcherServlet,该servlet的核心方法是是doDispatch,在javaweb一个request初始被封装为HttpServletRequest。
我们在使用springmvc过程中,一般会配置映射(显示的或隐式的使用注解驱动)来找到我们的页面控制器,也就是我们常说的Controller,有些需求我们还要配置拦截器(比如登陆权限验证等),springmvc就将我们的request通过handlerMapping映射成为一个执行器链HandlerExecutionChain,也就是我们的request将来就要在这个执行器链中走一遭。
然后为了统一handler接口(也就是我们的Controller),springmvc将我们自己写的Controller包装成了handlerAdapter(适配器模式),这时候你要是不认识自己写的页面处理器(controller),handlerAdapter就会和你说:兄嘚,我穿上马甲你就不认识我了。
接下来真正处理request,先执行拦截器接口中的preHandler方法,再执行ha(handlerAdapter)中的handle方法,执行完handle方法,再执行拦截器接口的posthandle
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;
void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;
}
接下来根据我们ha.handle返回的ModelAndView进行视图解析,返回前端,如果这样说太笼统,这个怎么理解呢,过程如下:
我们现在执行完handle(你可以看成执行完你自己写的Controller中的requestMapping方法),手握ModelAndView,我们手中现在既有Model模型数据,也有View视图数据,但我们现在手里握着的视图数据是抽象的,还没有落实到我们真正的jsp页面、velocity模板页面、freemarker页面或其他模板页面中,我们现在就握着个抽象view有什么用?用处大啦!我们可以根据我们的需要,选择不同的视图解析器将其落实到真正的真正的jsp页面、velocity模板页面、freemarker页面上,至于选哪个?自己配置视图解析器去。
好,我们落实了view,接下来落实Model,数据在手,天下我有,View有了实处,Model自然也找到落脚点,进行数据填充,返回前端。
流程基本结束。
匆忙间写就,如有错误,欢迎指正。