一、流程图
二、主要流程介绍:
DispatcherServlet:作为springmvc最重要的一部分,它
本身也是一个Servlet。它
负责调用HandlerMapping处理我们编写的handler,返回HandlerExecutionChain对象,再利用handler匹配到合适的HandlerAdapter,使用这个HandlerAdapter对象处理handler,最终返回一个ModelAndView对象,DispatcherServlet又请求ViewResolver对视图进行解析,渲染,响应给用户。- handler(用Object来接收的) :就是我们自己写的Contorller。我们要使用springmvc来处理,一般有三种方式:第一种是 实现Controller接口 ,第二种可以 实现HttpRequestHandler接口 ,第三种就是 走@RequestMapping注解方式 。这三种方式会分别使用不同的HandlerMapping来处理,返回的handler类型也不一样(下面会说),所以handler会使用Object来接收
- HandlerExecutionChain :里面封装了 handler 和 HandlerInterceptor的List集合
,
FrameworkServlet又继承了HttpServlet,
并覆写了HttpServlet的service(HttpServletRequest request, HttpServletResponse response)方法,FrameworkServlet的service方法也涉及到调用,调用后还做了很多初始化的工作,但这些不重要,重点是它会调用doService方法,FrameworkServlet的doService方法是个抽象方法,所以直接转到它的实现类DispatcherServlet中去,DispatcherServlet的doService方法又会做很多初始化的工作,向request域保存很多属性这些,但重点是他会调用本类的
doDispatch(request, response)方法,这个才是重点。如何调用到doDispatch方法的简图
三、源码分析
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 {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 1、调用处理器映射器(HandlerMapping),得到HandlerExecutionChain对象
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// 2、根据我们编写的Contorller得到匹配到适合的处理器适配器
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;
}
/*
3、利用处理器适配器,执行我们编写的Contorller方法,
并进一步处理,返会ModelAndView对象 */
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(request, mv);
// 执行每个拦截器的postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
// 对自定义的异常处理器进行捕获
catch (Exception ex) {
dispatchException = ex;
}
// 3、处理结果(页面渲染),这里过了,基本主要流程就走完了
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
// 异常时执行拦截器的afterCompletion方法
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
// 错误时也会执行拦截器的afterCompletion方法
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, 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);
}
}
}
}
分析:
核心1(请求 HandlerMapping获取HandlerExecutionChain对象 ):
mappedHandler =getHandler(processedRequest);protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
解析:这个方法里,会先遍历handlerMapping这个List集合(这个集合里装了所有的HandlerMapping对象(
BeanNameUrlHandlerMapping和
RequestMappingHandlerMapping)),然后依次执行HandlerMapping(HandlerMapping是所有处理器映射器的顶层接口)的getHandler(request)方法,
- BeanNameUrlHandlerMapping: 会处理 xml方式配置的Controller ,这种方式返回的handler包括 处理器拦截器的集合 和 自己配置的Controller对象,且用他的顶层接口来接收 。
- RequestMappingHandlerMapping: 会处理 注解方式配置的Contorller ,这种方式返回的handler包括 处理器拦截器(HandlerInterceptor)的集合 和 HandlerMethod对象 ( HandlerMethod里面又封装了处理方法的Method对象和我们写的Contorller对象 )
核心2(匹配到handler的HandlerAdapter):
HandlerAdapter ha =getHandlerAdapter(mappedHandler.getHandler());protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
解析:这个方法接收的参数就是封装在HandlerExecutionChain里面的handler。首先,它会先遍历HandlerAdapter这个List集合(这个集合里装了所有的HandlerAdapter对象(
HttpRequestHandlerAdapter和
SimpleControllerHandlerAdapter和
RequestMappingHandlerAdapter)),然后
依次执行HandlerAdapter的supports(handler)方法,来判断传入的handler会适配哪一个HandlerAdapter,最终返回这个匹配的HandlerAdapter。- HttpRequestHandlerAdapter: 处理实现了HttpRequestHandler接口的自己写的控制器
- SimpleControllerHandlerAdapter: 处理实现了Conroller接口的自己写的控制器
- RequestMappingHandlerAdapter: 处理使用注解(@RequestMapping)方式的自己写的控制器
核心3(HandlerAdapter处理handler,返回ModelAndView对象):
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());解析:调用HandlerAdapter的handle方法,对handler进行处理。这部分源码很多,而且比较复杂。在这方法里面主要是
先调用了我们编写的处理方法并获取其返回值,然后部分源码如下,它会先遍历returnValueHandler,(这是个存储返回值处理器(
HandlerMethodReturnValueHandler)的List集合,里面存了13个实现类对象,毕竟返回值会有很多种情况)
将返回值与返回值处理器进行匹配,匹配成功后用这个HandlerMethodReturnValueHandler的handleReturnValue方法对返回值进行处理(就是
将返回值装进ModelAndViewContainer这个对象中,
ModelAndViewContainer对象里面装了一个View和一个ModelMap,View用来装视图路径,ModelMap用来装数据(这个数据最终会放到request域中去)),最后再
new一个ModelAndView对象,将ModelAndViewContainer里的View和ModelMap装进去,返回ModelAndView对象private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) {
for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) {
if (logger.isTraceEnabled()) {
logger.trace("Testing if return value handler [" + returnValueHandler + "] supports [" +
returnType.getGenericParameterType() + "]");
}
if (returnValueHandler.supportsReturnType(returnType)) {
return returnValueHandler;
}
}
return null;
}
核心4(请求ViewResolver对ModelAndView解析,然后页面渲染):
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
HttpServletRequest request) throws Exception {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
return null;
}
这一部分只是遍历List<ViewResolver>,利用合适的视图解析器,解析出来View对象。之后会利用这个
View对象的render方法来渲染,渲染做的就是
取出ModelMap里面数据放进request域中,和
对视图名加上前后缀,利用request获取到RequestDispatcher对象,然后forward转发到对应的视图去。(InternalResourceView里的部分渲染源码,看中文解释就行)@Override
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 取出model里的数据保存到request域中
exposeModelAsRequestAttributes(model, request);
// Expose helpers as request attributes, if any.
exposeHelpers(request);
// 获取物理视图地址(就是转发路径)
String dispatcherPath = prepareForRendering(request, response);
// (获取RequestDispatcher以方便后面的转发)
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
if (rd == null) {
throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
"]: Check that the corresponding file exists within your web application archive!");
}
// If already included or response already committed, perform include, else forward.
if (useInclude(request, response)) {
response.setContentType(getContentType());
if (logger.isDebugEnabled()) {
logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
// 请求转发
rd.include(request, response);
}
渲染结束,在调用拦截器的afterCompletion方法。到这里基本节结束了 最后,说一下拦截器的执行顺序(都在doDispatch里调用,然后在HandlerExecutionChain类中执行)
(1)处理器前:// 调用(DispatcherServlet的doDispatch中)
if (!mappedHandler.applyPreHandle(processedRequest, response)) { //调用
return;
}
//执行(HandlerExecutionChain类中)
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (getInterceptors() != null) {
for (int i = 0; i < getInterceptors().length; i++) {
HandlerInterceptor interceptor = getInterceptors()[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
看上面的源码知道他会在处理前调用,执行
顺序也是从0索引开始,返回true就放行,返回false就执行拦截器的afterCompletion方法。最后对interceptorIndex的索引值赋值(这个很重要,它会涉及到有很多拦截器时拦截器后两个方法的分别执行顺序,这个索引也是用来保证拦截器的afterCompletion的调用)
(2)处理后渲染前// 调用(DispatcherServlet的doDispatch中)
mappedHandler.applyPostHandle(processedRequest, response, mv);
//执行(HandlerExecutionChain类中)
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
if (getInterceptors() == null) {
return;
}
for (int i = getInterceptors().length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = getInterceptors()[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
这一部分执行顺序就变了,他会先
从interceptorIndex这个索引开始向前遍历拦截器,然后执行它的postHandle方法 (3) 渲染后// 调用(DispatcherServlet的doDispatch中)
// 3、处理结果(页面渲染),最后会执行拦截器
processDispatchResult(processedRequest, response, mappedHdler, mv, dispatchException);
catch (Exception ex) {
// 异常时执行拦截器的afterCompletion方法
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
// 错误时也会执行拦截器的afterCompletion方法
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
//==================================================================================
//执行(HandlerExecutionChain类中)
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
throws Exception {
if (getInterceptors() == null) {
return;
}
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = getInterceptors()[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
拦截器的afterCompletion的方法是一定会调用的,捕获了异常或者错误会调用,没有捕时在渲染结束也会调用。它的执行顺序和拦截器的postHandle执行顺序一样 结论: - 某个拦截器的preHandle执行了且返回为true,那么它的afterCompletion一定会执行
- preHandle方法按顺序执行,postHandle和afterCompletion反序调用
- 当某一个的拦截器的preHandle方法反回了false,会进入到triggerAfterCompletion(request, response, null); 再根据当前的interceptorIndex索引值,执行前面返回为true的拦截器的afterCompletion方法
以上就是关于springmvc的执行流程的源码分析了,因为本人也刚学springmvc,所以理解可能也会存在错误,如果有说错了的地方,希望大家指出来,一起进步。