SpringMVC 流程分析
SpringMVC 流程
服务器启动阶段(DispatcherServlet初始化阶段)
-
启动后
ContextLoaderListener首先会在初始化方法contextInitialized(ServletContextEvent event)中调用initWebApplicationContext(event.getServletContext())来在创建一个WebApplicationContext。并将其作为ServletContext的一个属性设置到Servlet环境中。这个上下文对象为跟上下文对象。
ContextLoader#initWebApplicationContext(ServletContext servletContext)servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
-
DispatcherServlet初始化过程中中也会创建一个WebApplicationContext对象,并将ContextLoaderListener创建的上下文对象作为父上下文。同样也会将其作为ServletContext的一个属性。
FrameworkServlet#initWebApplicationContext()String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac);
创建完上下文对象后还会调用
onRefresh进行一系列初始化工作。
DispatcherServlet#initStrategies(ApplicationContext context)initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context);
这几个init方法的实现思路基本相同,首先从Bean容器中过的特定类型的类的实例。如果没有找到,则使用默认配置。即
DispatcherServlet.properties中的配置。
DispatcherServlet#initHandlerAdapters(ApplicationContext context)private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapters = null; if (this.detectAllHandlerAdapters) { // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts. Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values()); // We keep HandlerAdapters in sorted order. // 排序后对后来的getHandlerAdapter的结果会有所影响 OrderComparator.sort(this.handlerAdapters); } } else { try { HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); this.handlerAdapters = Collections.singletonList(ha); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default HandlerAdapter later. } } // Ensure we have at least some HandlerAdapters, by registering // default HandlerAdapters if no other adapters are found. if (this.handlerAdapters == null) { this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default"); } } }
经过一系列的init方法后DispatcherServlet正式初始化完成。
请求-响应阶段
-
发起请求
DispatcherServlet是一个标准的Servlet。当我们发送一个GET请求后,会有DispatcherServlet的doGet(HttpServletRequest request, HttpServletResponse response)来处理。
FrameworkServlet#doGet(HttpServletRequest request, HttpServletResponse response)processRequest(request, response);
在
processRequest这一阶段主要调用doService,然后是doDispatch。 -
处理请求
在doDispatch主要有一下几步操作。
1) 首先调用getHandler首先获得一个HandlerMapping对象,然后调用其getHandler方法返回一个HandlerExecutionChain对象。具体查看HandlerMapping实现类,例如RequestMappingHandlerMapping
DispatcherServlet#getHandler(HttpServletRequest request)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; }以
RequestMethodHandlerMapping为例,此对象中主要包含一个HandlerMethod实例及处理此请求的拦截器。
2) 调用getHandlerAdapter来得到第一个supports(handler)为true的HandlerAdapter。
DispatcherServlet#getHandlerAdapter(Object handler)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"); }3) 然后调用
HandlerExecutionChain#applyPreHandle(...)开始应用拦截器,一个一个调用其preHandle方法。
HandlerExecutionChain#applyPreHandle(HttpServletRequest request, HttpServletResponse response)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; }4) 接着调用
HandlerAdapter.handle(...)得到一个ModelAndView对象,里面封装了数据对象及具体的View对象。具体实现需要查看HandlerAdapter实现类。例如:RequestMappingHandlerAdapter。
5) 然后调用HandlerExecutionChain#applyPostHandle(...)再次应用拦截器,调用其postHandle方法。
HandlerExecutionChain#applyPreHandleapplyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv)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); } }6) 最后一步
processDispatchResult处理结果,相应给客户端。在processDispatchResult首先调用了render方法
DispatcherServlet#processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception)render(mv, request, response);
最后是
HandlerExecutionChain#triggerAfterCompletion(...),调用拦截器的afterCompletion方法。拦截器处理流程至此结束。
分析一下reader方法。首先调用resolveViewName,在里面先遍历所有的ViewResolver实例,调用其resolveViewName方法,返回第一不为空的View实例。
DispatcherServlet#resolveViewName(String viewName, Map model, Locale locale, HttpServletRequest request)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; }ViewResolver#resolveViewName具体可参看InternalResourceViewResolver实现。
最后调用View的render方法。render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)方法的具体实现可参考View实现类JstlView。
在JstlView中主要是调用renderMergedOutputModel,首先Model对象数据放置到request中,然后得到一个RequestDispatcher,最后调用其forward方法响应给客户端。
至此一个请求-响应过程结束。