- 前言
- DispatcherServlet 注册阶段
- ServletWebServerApplicationContext.createWebServer
- RegistrationBean.onStartUp
- ServletRegistrationBean
- DispatcherServlet初始化阶段,初始化的源头
- DispatcherServlet
- frameworkServlet
- HttpServletBean
- GenericServlet
- StandardWrapper
- StandardWrapperValve
- ApplicationFilterChain
- OncePerRequestFilter
- DispatcherServlet 初始化组件阶段
- DispatcherServlet
- initHandlerMappings
- RequestMappingHandlerMapping
- BeanNameUrlHandlerMapping
- initHandlerAdapters
- RequestMappingHandlerAdapter
- initHandlerExceptionResolvers
- initRequestToViewNameTranslator
- initViewResolvers
- initFlashMapManager
- frameworkServlet
- DispatcherServlet处理请求阶段
- frameworkServlet
- DispatcherServlet
- AbstractHandlerMapping.getHandler
- RequestMappingInfoHandlerMapping.getHandlerInternal
- AbstractHandlerMethodMapping
- HandlerAdapter.handle
- RequestMappingHandlerAdapter
- HandlerMethod
- InvocableHandlerMethod
- ServletInvocableHandlerMethod
- handleReturnValue
- RequestResponseBodyMethodProcessor
- AbstractMessageConverterMethodProcessor
前面我们分析到SpringBoot在启动的过程中,执行到AbstractApplicationContext的refresh方法时,执行到了onRefresh() 过程的时候,开始创建WebServer,在此过程中,加载类tomcat服务器和一些特殊类型的Bean:Servlet、Filter等,在其中我们发现了一个我们熟悉的Servlet,DispatcherServlet,并在此找到了它的启动入口,接下来我们详细分析一下DispatcherServlet的加载过程。前言中介绍到的加载过程,可以查看博客SpringBoot启动过程的“onRefresh() 在特定的上下文子类中初始化其他特殊bean 主题对象和创建webServer”章节。
DispatcherServlet 注册阶段 ServletWebServerApplicationContext.createWebServer在调用selfInitialize自我初始化函数的时候,遍历调用加载的Bean的onStartup方法,并且传入ServletContext上下文;
public class ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebServerApplicationContext { private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null) { StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create"); //从BeanFactory获取factory 实例对象 ServletWebServerFactory factory = getWebServerFactory(); createWebServer.tag("factory", factory.getClass().toString()); this.webServer = factory.getWebServer(getSelfInitializer()); createWebServer.end(); getBeanFactory().registerSingleton("webServerGracefulShutdown", new WebServerGracefulShutdownLifecycle(this.webServer)); getBeanFactory().registerSingleton("webServerStartStop", new WebServerStartStopLifecycle(this, this.webServer)); } else if (servletContext != null) { try { getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context", ex); } } initPropertySources(); } //自我初始化函数 private void selfInitialize(ServletContext servletContext) throws ServletException { //此处的servletContext是在创建tomcat服务器的时候,创建的,在回调时传入该变量 prepareWebApplicationContext(servletContext); //注册一个应用范围域的作用域,在工厂和servletContext中注册该作用域 registerApplicationScope(servletContext); //将servletContext注册为bean对象 WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext); //获取servlet上下文初始化Bean,并调用对应Bean的startup方法,触发servletContext启动事件 for (ServletContextInitializer beans : getServletContextInitializerBeans()) { beans.onStartup(servletContext); } } //注册一个应用范围域的作用域,在工厂和servletContext中注册该作用域 private void registerApplicationScope(ServletContext servletContext) { ServletContextScope appScope = new ServletContextScope(servletContext); getBeanFactory().registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope); // Register as ServletContext attribute, for ContextCleanupListener to detect it. servletContext.setAttribute(ServletContextScope.class.getName(), appScope); } //构建了一个ServletContextInitializerBeans实例对象 protected CollectionRegistrationBean.onStartUpgetServletContextInitializerBeans() { return new ServletContextInitializerBeans(getBeanFactory()); } }
调用ServletRegistrationBean的getDescription获取描述符,然后调用注册方法
public abstract class RegistrationBean implements ServletContextInitializer, Ordered { private int order = Ordered.LOWEST_PRECEDENCE; @Override public final void onStartup(ServletContext servletContext) throws ServletException { //description = servlet dispatcherServlet String description = getDescription(); if (!isEnabled()) { logger.info(StringUtils.capitalize(description) + " was not registered (disabled)"); return; } register(description, servletContext); } }ServletRegistrationBean
调用 getDescription获取描述符
public class ServletRegistrationBeanDispatcherServlet初始化阶段,初始化的源头extends DynamicRegistrationBean { @Override protected String getDescription() { Assert.notNull(this.servlet, "Servlet must not be null"); return "servlet " + getServletName(); } }
DispatcherServlet的初始化阶段是在请求request的时候触发的,此处可以根据调用栈倒推一下,servlet使用的策略对象是在initStrategies方法中生成的。而initStrategies方法的调用是onRefresh方法,此处的onRefresh的调用又是根据发布事件触发的
DispatcherServletpublic class DispatcherServlet extends frameworkServlet { @Override protected void onRefresh(ApplicationContext context) { initStrategies(context); } protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); } }
frameworkServlet此处用到了策略模式
此处我们跟踪到onRefresh方法是由onApplicationEvent方法触发的,而onApplicationEvent方法是由ContextRefreshListener 上下文刷新监听器监听到的。而ContextRefreshListener 的生成是在frameworkServlet 的configureAndRefreshWebApplicationContext方法中,而configureAndRefreshWebApplicationContext又是在createWebApplicationContext方法中调用的;而createWebApplicationContext又是在
initWebApplicationContext方法中调用的;而initWebApplicationContext方法又是在initServletBean方法中调用的;而initServletBean又是在HttpServletBean的initServletBean方法的实现方法,initServletBean方法是在HttpServletBean的init方法中调用的
public abstract class frameworkServlet extends HttpServletBean implements ApplicationContextAware { //初始化Servlet Bean protected final void initServletBean() throws ServletException { getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'"); if (logger.isInfoEnabled()) { logger.info("Initializing Servlet '" + getServletName() + "'"); } long startTime = System.currentTimeMillis(); try { this.webApplicationContext = initWebApplicationContext(); initframeworkServlet(); } catch (ServletException | RuntimeException ex) { logger.error("Context initialization failed", ex); throw ex; } if (logger.isDebugEnabled()) { String value = this.enableLoggingRequestDetails ? "shown which may lead to unsafe logging of potentially sensitive data" : "masked to prevent unsafe logging of potentially sensitive data"; logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails + "': request parameters and headers will be " + value); } if (logger.isInfoEnabled()) { logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms"); } } //初始化web应用上下文 初始化并发布这个servlet的WebApplicationContext。 protected WebApplicationContext initWebApplicationContext() { WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; if (this.webApplicationContext != null) { // A context instance was injected at construction time -> use it wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> set // the root application context (if any; may be null) as the parent cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac); } } } if (wac == null) { // No context instance was injected at construction time -> see if one // has been registered in the servlet context. If one exists, it is assumed // that the parent context (if any) has already been set and that the // user has performed any initialization such as setting the context id wac = findWebApplicationContext(); } if (wac == null) { // No context instance is defined for this servlet -> create a local one wac = createWebApplicationContext(rootContext); } if (!this.refreshEventReceived) { // Either the context is not a ConfigurableApplicationContext with refresh // support or the context injected at construction time had already been // refreshed -> trigger initial onRefresh manually here. synchronized (this.onRefreshMonitor) { onRefresh(wac); } } if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; } //创建web应用上下文 protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) { Class> contextClass = getContextClass(); if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { throw new ApplicationContextException( "Fatal initialization error in servlet with name '" + getServletName() + "': custom WebApplicationContext class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext"); } ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); wac.setEnvironment(getEnvironment()); wac.setParent(parent); String configLocation = getContextConfigLocation(); if (configLocation != null) { wac.setConfigLocation(configLocation); } configureAndRefreshWebApplicationContext(wac); return wac; } //配置和刷新web应用上下文 protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) { if (ObjectUtils.identityToString(wac).equals(wac.getId())) { // The application context id is still set to its original default value // -> assign a more useful id based on available information if (this.contextId != null) { wac.setId(this.contextId); } else { // Generate default id... wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName()); } } wac.setServletContext(getServletContext()); wac.setServletConfig(getServletConfig()); wac.setNamespace(getNamespace()); wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener())); // The wac environment's #initPropertySources will be called in any case when the context // is refreshed; do it eagerly here to ensure servlet property sources are in place for // use in any post-processing or initialization that occurs below prior to #refresh ConfigurableEnvironment env = wac.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig()); } postProcessWebApplicationContext(wac); applyInitializers(wac); wac.refresh(); } private class ContextRefreshListener implements ApplicationListenerHttpServletBean{ @Override public void onApplicationEvent(ContextRefreshedEvent event) { frameworkServlet.this.onApplicationEvent(event); } } // 从这个servlet的WebApplicationContext接收刷新事件的回调。 public void onApplicationEvent(ContextRefreshedEvent event) { this.refreshEventReceived = true; synchronized (this.onRefreshMonitor) { onRefresh(event.getApplicationContext()); } } }
而HttpServletBean 的init方法的调用是由GenericServlet 的init方法触发的
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware { // 将配置参数映射到这个servlet的bean属性上,并调用子类初始化。 public final void init() throws ServletException { // 从初始化参数中设置bean属性。 PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); if (!pvs.isEmpty()) { try { BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); initBeanWrapper(bw); bw.setPropertyValues(pvs, true); } catch (BeansException ex) { if (logger.isErrorEnabled()) { logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); } throw ex; } } // 让子类做任何他们喜欢的初始化。 initServletBean(); } }GenericServlet
GenericServlet即子类DispatcherServlet的init(ServletConfig config) 方法是由StandardWrapper 的initServlet方法调用的。
public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable { public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); } // 一个方便的方法,它可以被重写,这样就不需要调用super.init(config)。 public void init() throws ServletException { // NOOP by default } }StandardWrapper
initServlet(Servlet servlet)方法调用了servlet.init(facade)方法,此处的servlet即DispatcherServlet;而initServlet(Servlet servlet)方法又是在StandardWrapper 的allocate方法调用的;而allocate方法是在StandardWrapperValve的invoke方法中调用的
// Wrapper接口的标准实现,它表示一个单独的servlet定义。不允许子容器存在,父容器必须是上下文。 public class StandardWrapper extends Containerbase implements ServletConfig, Wrapper, NotificationEmitter { public Servlet allocate() throws ServletException { boolean newInstance = false; // If not SingleThreadedModel, return the same instance every time if (!singleThreadModel) { // Load and initialize our instance if necessary if (instance == null || !instanceInitialized) { synchronized (this) { if (instance == null) { try { // 此处加载已经注册的servlet,即DispatcherServlet instance = loadServlet(); newInstance = true; if (!instanceInitialized) { initServlet(instance); } } } if (singleThreadModel) { if (newInstance) { // Have to do this outside of the sync above to prevent a // possible deadlock synchronized (instancePool) { instancePool.push(instance); nInstances++; } } } else { if (log.isTraceEnabled()) { log.trace(" Returning non-STM instance"); } // For new instances, count will have been incremented at the // time of creation if (!newInstance) { countAllocated.incrementAndGet(); } return instance; } } synchronized (instancePool) { while (countAllocated.get() >= nInstances) { // Allocate a new instance if possible, or else wait if (nInstances < maxInstances) { try { instancePool.push(loadServlet()); nInstances++; } catch (ServletException e) { throw e; } catch (Throwable e) { ExceptionUtils.handleThrowable(e); throw new ServletException(sm.getString("standardWrapper.allocate"), e); } } else { try { instancePool.wait(); } catch (InterruptedException e) { // Ignore } } } if (log.isTraceEnabled()) { log.trace(" Returning allocated STM instance"); } countAllocated.incrementAndGet(); return instancePool.pop(); } } private synchronized void initServlet(Servlet servlet) throws ServletException { if (instanceInitialized && !singleThreadModel) { return; } // Call the initialization method of this servlet try { if( Globals.IS_SECURITY_ENABLED) { boolean success = false; try { Object[] args = new Object[] { facade }; SecurityUtil.doAsPrivilege("init", servlet, classType, args); success = true; } finally { if (!success) { // destroy() will not be called, thus clear the reference now SecurityUtil.remove(servlet); } } } else { servlet.init(facade); } instanceInitialized = true; } catch (Throwable f) { throw new ServletException (sm.getString("standardWrapper.initException", getName()), f); } }StandardWrapperValve
分析到这里我们可以大概知道DispatcherServlet其实是由request的请求,导致调用Servlet的init方法,对DispatcherServlet进行初始化 *** 作的,再往下分析便是tomcat的细节了,我们在别处进行讨论。
我们在此看一下invoke方法中,都有哪些动作:调用完wrapper.allocate方法,对Servlet即DispatcherServlet初始化完毕后,调用了ApplicationFilterFactory.createFilterChain方法,创建了filterChain 过滤器链:
OrderedCharacterEncodingFilter OrderedFormContentFilter OrderedRequestContextFilter WsFilter
加载完filter之后,执行filterChain.doFilter方法对filter和serlvet进行调用
final class StandardWrapperValve extends Valvebase { public final void invoke(Request request, Response response) throws IOException, ServletException { long t1=System.currentTimeMillis(); requestCount.incrementAndGet(); StandardWrapper wrapper = (StandardWrapper) getContainer(); Servlet servlet = null; Context context = (Context) wrapper.getParent(); // Check for the application being marked unavailable if (!context.getState().isAvailable()) { response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardContext.isUnavailable")); unavailable = true; } 。。。。。。 // Allocate a servlet instance to process this request 分配一个servlet实例来处理这个请求 try { if (!unavailable) { servlet = wrapper.allocate(); } } catch (UnavailableException e) { long available = wrapper.getAvailable(); if ((available > 0L) && (available < Long.MAX_VALUE)) { } else if (available == Long.MAX_VALUE) { } } catch (ServletException e) { } catch (Throwable e) { } MessageBytes requestPathMB = request.getRequestPathMB(); DispatcherType dispatcherType = DispatcherType.REQUEST; if (request.getDispatcherType()==DispatcherType.ASYNC) { dispatcherType = DispatcherType.ASYNC; } request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType); request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB); // Create the filter chain for this request ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet); // Call the filter chain for this request 调用此请求的过滤器链 // NOTE: This also calls the servlet's service() method 这也调用servlet的service()方法 Container container = this.container; try { if ((servlet != null) && (filterChain != null)) { // Swallow output if needed 如果需要,吞咽输出 if (context.getSwallowOutput()) { try { SystemLogHandler.startCapture(); if (request.isAsyncDispatching()) { request.getAsyncContextInternal().doInternalDispatch(); } else { filterChain.doFilter(request.getRequest(), response.getResponse()); } } finally { String log = SystemLogHandler.stopCapture(); if (log != null && log.length() > 0) { context.getLogger().info(log); } } } else { } } } catch (ClientAbortException | CloseNowException e) { exception(request, response, e); } catch (IOException e) { exception(request, response, e); } catch (UnavailableException e) { container.getLogger().error(sm.getString( "standardWrapper.serviceException", wrapper.getName(), context.getName()), e); // throwable = e; // exception(request, response, e); wrapper.unavailable(e); long available = wrapper.getAvailable(); if ((available > 0L) && (available < Long.MAX_VALUE)) { response.setDateHeader("Retry-After", available); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName())); } else if (available == Long.MAX_VALUE) { response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName())); } } catch (ServletException e) { } finally { // Release the filter chain (if any) for this request if (filterChain != null) { filterChain.release(); } // Deallocate the allocated servlet instance 释放分配的servlet实例 try { if (servlet != null) { wrapper.deallocate(servlet); } } catch (Throwable e) { } } } }ApplicationFilterChain
调用doFilter方法,内部调用internalDoFilter方法即内部DoFilter方法,内部DoFilter方法调用对应Filter的doFilter方法,此处先调用了doFilter的父类OncePerRequestFilter方法,当filte执行完毕之后,执行servlet的service方法,即HttpServlet的service方法。service方法内部根据request请求方式调用servlet对应的方法,此处的get方法请求frameworkServlet的doGet方法,该方法内部调用processRequest方法,此处我们继续看DispatcherServlet处理请求阶段
public final class ApplicationFilterChain implements FilterChain { private static final ThreadLocaloncePerRequestFilterlastServicedRequest; private static final ThreadLocal lastServicedResponse; private int pos = 0; private int n = 0; private Servlet servlet = null; static { if (ApplicationDispatcher.WRAP_SAME_OBJECT) { lastServicedRequest = new ThreadLocal<>(); lastServicedResponse = new ThreadLocal<>(); } else { lastServicedRequest = null; lastServicedResponse = null; } } private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0]; public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; try { java.security.AccessController.doPrivileged( (java.security.PrivilegedExceptionAction ) () -> { internalDoFilter(req,res); return null; } ); } catch( PrivilegedActionException pe) { } } else { internalDoFilter(request,response); } } private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // Call the next filter if there is one if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; try { // 从config中获取当前要调用的filter Filter filter = filterConfig.getFilter(); if (request.isAsyncSupported() && "false".equalsIgnoreCase( filterConfig.getFilterDef().getAsyncSupported())) { request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res, this}; SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal); } else { // 调用对应filter的doFilter方法 filter.doFilter(request, response, this); } } catch (IOException | ServletException | RuntimeException e) { throw e; } catch (Throwable e) { } return; } // We fell off the end of the chain -- call the servlet instance try { if (ApplicationDispatcher.WRAP_SAME_OBJECT) { lastServicedRequest.set(request); lastServicedResponse.set(response); } if (request.isAsyncSupported() && !servletSupportsAsync) { request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } // Use potentially wrapped request from this point if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse) && Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res}; SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args, principal); } else { servlet.service(request, response); } } catch (IOException | ServletException | RuntimeException e) { throw e; } finally { if (ApplicationDispatcher.WRAP_SAME_OBJECT) { lastServicedRequest.set(null); lastServicedResponse.set(null); } } } }
public abstract class OncePerRequestFilter extends GenericFilterBean { public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED"; public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) { throw new ServletException("oncePerRequestFilter just supports HTTP requests"); } HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName(); boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null; if (skipDispatch(httpRequest) || shouldNotFilter(httpRequest)) { // Proceed without invoking this filter... filterChain.doFilter(request, response); } else if (hasAlreadyFilteredAttribute) { if (DispatcherType.ERROR.equals(request.getDispatcherType())) { doFilterNestedErrorDispatch(httpRequest, httpResponse, filterChain); return; } // Proceed without invoking this filter... filterChain.doFilter(request, response); } else { // Do invoke this filter... request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE); try { doFilterInternal(httpRequest, httpResponse, filterChain); } finally { // Remove the "already filtered" request attribute for this request. request.removeAttribute(alreadyFilteredAttributeName); } } } }DispatcherServlet 初始化组件阶段 DispatcherServlet
随着调用的请求过程,初始化过程中
public class DispatcherServlet extends frameworkServlet { @Override protected void onRefresh(ApplicationContext context) { initStrategies(context); } // 初始化这个servlet使用的策略对象。 protected void initStrategies(ApplicationContext context) { // 处理文件上传的策略组件对象 initMultipartResolver(context); // 初始化该类使用的区域设置解析器。 initLocaleResolver(context); // 初始化该类使用的主题解析器 initThemeResolver(context); // 初始化这个类使用的处理器映射。 initHandlerMappings(context); // 初始化该类使用的处理程序适配器 initHandlerAdapters(context); // 初始化该类使用的处理程序异常解析器。 initHandlerExceptionResolvers(context); // 初始化这个servlet实例使用的请求查看名称转换器 initRequestToViewNameTranslator(context); // 初始化这个类使用的视图解析器。 initViewResolvers(context); // 初始化这个servlet实例使用的Flash Map Manager。 initFlashMapManager(context); } } // 为DispatcherServlet的成员变量 multipartResolver 赋值,从上下文获取 private void initMultipartResolver(ApplicationContext context) { try { this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class); } } private void initLocaleResolver(ApplicationContext context) { try { this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class); } private void initThemeResolver(ApplicationContext context) { try { this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class); } }initHandlerMappings
此处获取到的matchingBeans 有:
"requestMappingHandlerMapping" -> {RequestMappingHandlerMapping@6627} "welcomePageHandlerMapping" -> {WelcomePageHandlerMapping@8127} "beanNameHandlerMapping" -> {BeanNameUrlHandlerMapping@8129} "routerFunctionMapping" -> {RouterFunctionMapping@6611} "resourceHandlerMapping" -> {SimpleUrlHandlerMapping@8131}
public class DispatcherServlet extends frameworkServlet { private ListRequestMappingHandlerMappinghandlerMappings; private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // 找到ApplicationContext中的所有HandlerMappings,包括祖先上下文。 Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<>(matchingBeans.values()); // We keep HandlerMappings in sorted order. AnnotationAwareOrderComparator.sort(this.handlerMappings); } } else { } // Ensure we have at least one HandlerMapping, by registering // a default HandlerMapping if no other mappings are found. if (this.handlerMappings == null) { this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); } for (HandlerMapping mapping : this.handlerMappings) { if (mapping.usesPathPatterns()) { this.parseRequestPath = true; break; } } } }
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements MatchableHandlerMapping, EmbeddedValueResolverAware { }BeanNameUrlHandlerMapping
public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping { // 检查以“/”开头的给定bean的名称和别名的url。 @Override protected String[] determineUrlsForHandler(String beanName) { ListinitHandlerAdaptersurls = new ArrayList<>(); if (beanName.startsWith("/")) { urls.add(beanName); } String[] aliases = obtainApplicationContext().getAliases(beanName); for (String alias : aliases) { if (alias.startsWith("/")) { urls.add(alias); } } return StringUtils.toStringArray(urls); } }
"requestMappingHandlerAdapter" -> {RequestMappingHandlerAdapter@6634} "handlerFunctionAdapter" -> {HandlerFunctionAdapter@6625} "httpRequestHandlerAdapter" -> {HttpRequestHandlerAdapter@8296} "simpleControllerHandlerAdapter" -> {SimpleControllerHandlerAdapter@8298}
public class DispatcherServlet extends frameworkServlet { private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapters = null; if (this.detectAllHandlerAdapters) { // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts. MapRequestMappingHandlerAdaptermatchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerAdapters = new ArrayList<>(matchingBeans.values()); // We keep HandlerAdapters in sorted order. AnnotationAwareOrderComparator.sort(this.handlerAdapters); } } else { try { HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); this.handlerAdapters = Collections.singletonList(ha); } } // 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); } } }
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean { }initHandlerExceptionResolvers
"errorAttributes" -> {DefaultErrorAttributes@8351} "handlerExceptionResolver" -> {HandlerExceptionResolverComposite@8353}
public class DispatcherServlet extends frameworkServlet { private RequestToViewNameTranslator viewNameTranslator; private void initHandlerExceptionResolvers(ApplicationContext context) { this.handlerExceptionResolvers = null; if (this.detectAllHandlerExceptionResolvers) { // Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts. MapinitRequestToViewNameTranslatormatchingBeans = BeanFactoryUtils .beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values()); // We keep HandlerExceptionResolvers in sorted order. AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers); } } else { try { HandlerExceptionResolver her = context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class); this.handlerExceptionResolvers = Collections.singletonList(her); } } // Ensure we have at least some HandlerExceptionResolvers, by registering // default HandlerExceptionResolvers if no other resolvers are found. if (this.handlerExceptionResolvers == null) { this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class); } } }
public class DispatcherServlet extends frameworkServlet { private RequestToViewNameTranslator viewNameTranslator; private void initRequestToViewNameTranslator(ApplicationContext context) { try { this.viewNameTranslator = context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class); } catch (NoSuchBeanDefinitionException ex) { } } }initViewResolvers
加载到的视图解析器有
"beanNameViewResolver" -> {BeanNameViewResolver@6507} "mvcViewResolver" -> {ViewResolverComposite@8438} "defaultViewResolver" -> {InternalResourceViewResolver@6609} "viewResolver" -> {ContentNegotiatingViewResolver@6511}
public class DispatcherServlet extends frameworkServlet { private void initViewResolvers(ApplicationContext context) { this.viewResolvers = null; if (this.detectAllViewResolvers) { // Find all ViewResolvers in the ApplicationContext, including ancestor contexts. MapinitFlashMapManagermatchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false); if (!matchingBeans.isEmpty()) { this.viewResolvers = new ArrayList<>(matchingBeans.values()); // We keep ViewResolvers in sorted order. AnnotationAwareOrderComparator.sort(this.viewResolvers); } } else { try { ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class); this.viewResolvers = Collections.singletonList(vr); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default ViewResolver later. } } // Ensure we have at least one ViewResolver, by registering // a default ViewResolver if no other resolvers are found. if (this.viewResolvers == null) { this.viewResolvers = getDefaultStrategies(context, ViewResolver.class); } } }
public class DispatcherServlet extends frameworkServlet { private FlashMapManager flashMapManager; private void initFlashMapManager(ApplicationContext context) { try { this.flashMapManager = context.getBean(FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class); } catch (NoSuchBeanDefinitionException ex) { } }frameworkServlet
执行完onRefresh方法,返回到frameworkServlet的initServletBean方法,继续执行
DispatcherServlet处理请求阶段 frameworkServletpublic abstract class frameworkServlet extends HttpServletBean implements ApplicationContextAware { // 处理此请求,不管结果如何发布事件,实际的事件处理是由抽象的{@link #doService}模板方法执行的。 protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); LocaleContext localeContext = buildLocaleContext(request); RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.registerCallableInterceptor(frameworkServlet.class.getName(), new RequestBindingInterceptor()); initContextHolders(request, localeContext, requestAttributes); try { doService(request, response); } catch (ServletException | IOException ex) { failureCause = ex; throw ex; } catch (Throwable ex) { failureCause = ex; throw new NestedServletException("Request processing failed", ex); } finally { resetContextHolders(request, previousLocaleContext, previousAttributes); if (requestAttributes != null) { requestAttributes.requestCompleted(); } logResult(request, response, failureCause, asyncManager); publishRequestHandledEvent(request, response, startTime, failureCause); } } protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws Exception; }DispatcherServlet
在调用doDispatch的过程中,在执行ha.handle方法执行之前,首先调用了mappedHandler.applyPreHandle方法,执行了拦截器的前置处理方法;
在执行完ha.handle方法之后,调用了mappedHandler.applyPostHandle方法对结果进行后置处理
public class DispatcherServlet extends frameworkServlet { protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { logRequest(request); // 保留请求属性的快照,以防出现包含,以便能够在包含之后恢复原始属性。 MapAbstractHandlerMapping.getHandlerattributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap<>(); Enumeration> attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = (String) attrNames.nextElement(); if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } } // 使框架对象对处理程序和视图对象可用。 request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); if (this.flashMapManager != null) { FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); } RequestPath previousRequestPath = null; if (this.parseRequestPath) { previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE); ServletRequestPathUtils.parseAndCache(request); } try { doDispatch(request, response); } finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Restore the original attribute snapshot, in case of an include. if (attributesSnapshot != null) { restoreAttributesAfterInclude(request, attributesSnapshot); } } if (this.parseRequestPath) { ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request); } } protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { // this.handlerAdapters: // 0 = {RequestMappingHandlerAdapter@6739} // 1 = {HandlerFunctionAdapter@6740} // 2 = {HttpRequestHandlerAdapter@6741} // 3 = {SimpleControllerHandlerAdapter@6742} for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); } } 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); // 确定当前请求的处理程序。 mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // 确定当前请求的处理程序适配器 // 此处ha = RequestMappingHandlerAdapter实例对象 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = HttpMethod.GET.matches(method); if (isGet || HttpMethod.HEAD.matches(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } // 首先执行拦截器链的preHandle方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. 实际调用处理程序 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { } catch (Throwable err) { } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } 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); } } } } protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { // 从 for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; } }
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware { public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //得到处理方法,并封装了bean对象 Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } // Ensure presence of cached lookupPath for interceptors and others if (!ServletRequestPathUtils.hasCachedPath(request)) { initLookupPath(request); } // 返回执行器链,包括处理器本身和拦截器链 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) { CorsConfiguration config = getCorsConfiguration(handler, request); if (getCorsConfigurationSource() != null) { CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request); config = (globalConfig != null ? globalConfig.combine(config) : config); } if (config != null) { config.validateAllowCredentials(); } executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } // 返回执行器链,包括处理器本身和拦截器链 return executionChain; } // 初始化用于请求映射的路径。此处进入 else逻辑 protected String initLookupPath(HttpServletRequest request) { if (usesPathPatterns()) { request.removeAttribute(UrlPathHelper.PATH_ATTRIBUTE); RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(request); String lookupPath = requestPath.pathWithinApplication().value(); return UrlPathHelper.defaultInstance.removeSemicolonContent(lookupPath); } else { return getUrlPathHelper().resolveAndCacheLookupPath(request); } } // 获取处理执行器链 protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); for (HandlerInterceptor interceptor : this.adaptedInterceptors) { if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; if (mappedInterceptor.matches(request)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; } }RequestMappingInfoHandlerMapping.getHandlerInternal
public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMappingAbstractHandlerMethodMapping{ protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); try { return super.getHandlerInternal(request); } finally { ProducesRequestCondition.clearMediaTypesAttribute(request); } } }
public abstract class AbstractHandlerMethodMappingextends AbstractHandlerMapping implements InitializingBean { protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = initLookupPath(request); this.mappingRegistry.acquireReadLock(); try { // 从映射注册中心获取处理方法 HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); // 根据bean名称,为handlerMethod 填充bean属性 return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } } protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List matches = new ArrayList<>(); // T = RequestMappingInfo List directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath); if (directPathMatches != null) { addMatchingMappings(directPathMatches, matches, request); } if (matches.isEmpty()) { addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request); } if (!matches.isEmpty()) { Match bestMatch = matches.get(0); if (matches.size() > 1) { Comparator comparator = new MatchComparator(getMappingComparator(request)); matches.sort(comparator); bestMatch = matches.get(0); if (logger.isTraceEnabled()) { logger.trace(matches.size() + " matching mappings: " + matches); } if (CorsUtils.isPreFlightRequest(request)) { for (Match match : matches) { if (match.hasCorsConfig()) { return PREFLIGHT_AMBIGUOUS_MATCH; } } } else { Match secondBestMatch = matches.get(1); if (comparator.compare(bestMatch, secondBestMatch) == 0) { Method m1 = bestMatch.getHandlerMethod().getMethod(); Method m2 = secondBestMatch.getHandlerMethod().getMethod(); String uri = request.getRequestURI(); throw new IllegalStateException( "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}"); } } } request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod()); handleMatch(bestMatch.mapping, lookupPath, request); return bestMatch.getHandlerMethod(); } else { return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request); } } // 添加映射 private void addMatchingMappings(Collection mappings, List matches, HttpServletRequest request) { for (T mapping : mappings) { T match = getMatchingMapping(mapping, request); if (match != null) { matches.add(new Match(match, this.mappingRegistry.getRegistrations().get(mapping))); } } } class MappingRegistry { // 返回匹配给定URL路径。不是线程安全的。 public List getMappingsByDirectPath(String urlPath) { return this.pathLookup.get(urlPath); } } }
public class UrlPathHelper { // 返回web应用程序中给定请求的路径。 public String getPathWithinApplication(HttpServletRequest request) { String contextPath = getContextPath(request); String requestUri = getRequestUri(request); String path = getRemainingPath(requestUri, contextPath, true); if (path != null) { // Normal case: URI contains context path. return (StringUtils.hasText(path) ? path : "/"); } else { return requestUri; } } }HandlerAdapter.handle
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered { public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); } }RequestMappingHandlerAdapter
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean { protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); // 如果需要,在同步块中执行invokeHandlerMethod。此处进入else逻辑 if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No HttpSession available -> no mutex necessary mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No synchronization on session demanded at all... mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; } // 调用处理器 protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { // 构建web请求,包含request 和 response ServletWebRequest webRequest = new ServletWebRequest(request, response); try { // 根据方法和转换服务生成一个ServletRequestDataBinderFactory对象 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); // 根据给出的@ModelAttribute方法,创建一个实例对象 ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); if (this.argumentResolvers != null) { // 设置一个参数解析器 invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } if (this.returnValueHandlers != null) { invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } // 设置数据绑定工厂 invocableMethod.setDataBinderFactory(binderFactory); // 设置参数名称发现器 invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); // 定义一个实体视图容器 ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) { Object result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0]; asyncManager.clearConcurrentResult(); LogFormatUtils.traceDebug(logger, traceOn -> { String formatted = LogFormatUtils.formatValue(result, !traceOn); return "Resume with async result [" + formatted + "]"; }); invocableMethod = invocableMethod.wrapConcurrentResult(result); } // 调用方法 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } } // 根据给定的HandlerMethod定义创建一个Servlet可调用HandlerMethod。 protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) { return new ServletInvocableHandlerMethod(handlerMethod); } }HandlerMethod
public class HandlerMethod { protected HandlerMethod(HandlerMethod handlerMethod) { Assert.notNull(handlerMethod, "HandlerMethod is required"); this.bean = handlerMethod.bean; this.beanFactory = handlerMethod.beanFactory; this.messageSource = handlerMethod.messageSource; this.beanType = handlerMethod.beanType; this.method = handlerMethod.method; this.bridgedMethod = handlerMethod.bridgedMethod; this.parameters = handlerMethod.parameters; this.responseStatus = handlerMethod.responseStatus; this.responseStatusReason = handlerMethod.responseStatusReason; this.description = handlerMethod.description; this.resolvedFromHandlerMethod = handlerMethod.resolvedFromHandlerMethod; } }InvocableHandlerMethod
invokeForRequest方法首先调用getMethodArgumentValues方法获取方法参数值,获取到参数之后,调用doInvoke方法,进行处理
public class InvocableHandlerMethod extends HandlerMethod { private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite(); private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); public InvocableHandlerMethod(HandlerMethod handlerMethod) { super(handlerMethod); } public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); } return doInvoke(args); } protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } Object[] args = new Object[parameters.length]; // 对参数进行解析 for (int i = 0; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } try { args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception ex) { // Leave stack trace for later, exception may actually be resolved and handled... if (logger.isDebugEnabled()) { String exMsg = ex.getMessage(); if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) { logger.debug(formatArgumentError(parameter, exMsg)); } } throw ex; } } return args; } protected Object doInvoke(Object... args) throws Exception { Method method = getBridgedMethod(); try { if (KotlinDetector.isSuspendingFunction(method)) { return CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args); } return method.invoke(getBean(), args); } catch (IllegalArgumentException ex) { } catch (InvocationTargetException ex) { } } public void setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) { this.resolvers = argumentResolvers; } }ServletInvocableHandlerMethod
调用invokeAndHandle方法,方法内部首先调用了父类的 invokeForRequest方法,方法返回返回值,随后调用returnValueHandlers的handleReturnValue方法将结果输出。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod { private HandlerMethodReturnValueHandlerComposite returnValueHandlers; public ServletInvocableHandlerMethod(HandlerMethod handlerMethod) { super(handlerMethod); } // 注册HandlerMethod返回值处理程序实例来处理返回值。 public void setHandlerMethodReturnValueHandlers(HandlerMethodReturnValueHandlerComposite returnValueHandlers) { this.returnValueHandlers = returnValueHandlers; } public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); setResponseStatus(webRequest); if (returnValue == null) { if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) { disableContentCachingIfNecessary(webRequest); mavContainer.setRequestHandled(true); return; } } else if (StringUtils.hasText(getResponseStatusReason())) { mavContainer.setRequestHandled(true); return; } mavContainer.setRequestHandled(false); Assert.state(this.returnValueHandlers != null, "No return value handlers"); try { this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(formatErrorForReturnValue(returnValue), ex); } throw ex; } } }handleReturnValue
returnValueHandlers:
0 = {ModelAndViewMethodReturnValueHandler@9410} 1 = {ModelMethodProcessor@9411} 2 = {ViewMethodReturnValueHandler@9412} 3 = {ResponseBodyEmitterReturnValueHandler@9413} 4 = {StreamingResponseBodyReturnValueHandler@9414} 5 = {HttpEntityMethodProcessor@9415} 6 = {HttpHeadersReturnValueHandler@9416} 7 = {CallableMethodReturnValueHandler@9417} 8 = {DeferredResultMethodReturnValueHandler@9418} 9 = {AsyncTaskMethodReturnValueHandler@9419} 10 = {ServletModelAttributeMethodProcessor@9420} 11 = {RequestResponseBodyMethodProcessor@8319} 12 = {ViewNameMethodReturnValueHandler@9421} 13 = {MapMethodProcessor@9422} 14 = {ServletModelAttributeMethodProcessor@9423}
调用selectHandler方法返回的结果处理器为:RequestResponseBodyMethodProcessor
public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler { public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType); if (handler == null) { throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName()); } handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); } // 此处的returnValueHandlers有15个 private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) { boolean isAsyncValue = isAsyncReturnValue(value, returnType); for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) { continue; } if (handler.supportsReturnType(returnType)) { return handler; } } return null; } }RequestResponseBodyMethodProcessor
handleReturnValue方法内部调用了writeWithMessageConverters方法,将结果输出
public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor { public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { mavContainer.setRequestHandled(true); ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); // Try even with null return value. ResponseBodyAdvice could get involved. writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); } }AbstractMessageConverterMethodProcessor
在writeWithMessageConverters方法中,调用了getAdvice().beforeBodyWrite方法,对输出的结果进行处理,即调用RequestBodyAdvice, ResponseBodyAdvice类的拦截方法
public abstract class AbstractMessageConverterMethodProcessor extends AbstractMessageConverterMethodArgumentResolver implements HandlerMethodReturnValueHandler { protectedvoid writeWithMessageConverters(@Nullable T value, MethodParameter returnType, ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { Object body; Class> valueType; Type targetType; if (value instanceof CharSequence) { body = value.toString(); valueType = String.class; targetType = String.class; } else { body = value; valueType = getReturnValueType(body, returnType); targetType = GenericTypeResolver.resolveType(getGenericType(returnType), returnType.getContainingClass()); } if (isResourceType(value, returnType)) { outputMessage.getHeaders().set(HttpHeaders.ACCEPT_RANGES, "bytes"); if (value != null && inputMessage.getHeaders().getFirst(HttpHeaders.RANGE) != null && outputMessage.getServletResponse().getStatus() == 200) { Resource resource = (Resource) value; try { List httpRanges = inputMessage.getHeaders().getRange(); outputMessage.getServletResponse().setStatus(HttpStatus.PARTIAL_CONTENT.value()); body = HttpRange.toResourceRegions(httpRanges, resource); valueType = body.getClass(); targetType = RESOURCE_REGION_LIST_TYPE; } catch (IllegalArgumentException ex) { outputMessage.getHeaders().set(HttpHeaders.CONTENT_RANGE, "bytes */" + resource.contentLength()); outputMessage.getServletResponse().setStatus(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value()); } } } MediaType selectedMediaType = null; MediaType contentType = outputMessage.getHeaders().getContentType(); boolean isContentTypePreset = contentType != null && contentType.isConcrete(); if (isContentTypePreset) { selectedMediaType = contentType; } else { HttpServletRequest request = inputMessage.getServletRequest(); List acceptableTypes; try { acceptableTypes = getAcceptableMediaTypes(request); } catch (HttpMediaTypeNotAcceptableException ex) { int series = outputMessage.getServletResponse().getStatus() / 100; if (body == null || series == 4 || series == 5) { return; } throw ex; } List producibleTypes = getProducibleMediaTypes(request, valueType, targetType); if (body != null && producibleTypes.isEmpty()) { throw new HttpMessageNotWritableException( "No converter found for return value of type: " + valueType); } List mediaTypesToUse = new ArrayList<>(); for (MediaType requestedType : acceptableTypes) { for (MediaType producibleType : producibleTypes) { if (requestedType.isCompatibleWith(producibleType)) { mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType)); } } } if (mediaTypesToUse.isEmpty()) { if (body != null) { throw new HttpMediaTypeNotAcceptableException(producibleTypes); } if (logger.isDebugEnabled()) { logger.debug("No match for " + acceptableTypes + ", supported: " + producibleTypes); } return; } MediaType.sortBySpecificityAndQuality(mediaTypesToUse); for (MediaType mediaType : mediaTypesToUse) { if (mediaType.isConcrete()) { selectedMediaType = mediaType; break; } else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) { selectedMediaType = MediaType.APPLICATION_OCTET_STREAM; break; } } if (logger.isDebugEnabled()) { } } if (selectedMediaType != null) { selectedMediaType = selectedMediaType.removeQualityValue(); for (HttpMessageConverter> converter : this.messageConverters) { GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter>) converter : null); if (genericConverter != null ? ((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) : converter.canWrite(valueType, selectedMediaType)) { body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType, (Class extends HttpMessageConverter>>) converter.getClass(), inputMessage, outputMessage); if (body != null) { Object theBody = body; LogFormatUtils.traceDebug(logger, traceOn -> "Writing [" + LogFormatUtils.formatValue(theBody, !traceOn) + "]"); addContentDispositionHeader(inputMessage, outputMessage); if (genericConverter != null) { genericConverter.write(body, targetType, selectedMediaType, outputMessage); } else { ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage); } } else { if (logger.isDebugEnabled()) { logger.debug("Nothing to write: null body"); } } return; } } } if (body != null) { Set producibleMediaTypes = (Set ) inputMessage.getServletRequest() .getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); if (isContentTypePreset || !CollectionUtils.isEmpty(producibleMediaTypes)) { throw new HttpMessageNotWritableException( "No converter for [" + valueType + "] with preset Content-Type '" + contentType + "'"); } throw new HttpMediaTypeNotAcceptableException(getSupportedMediaTypes(body.getClass())); } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)