SpringMVC分发器DispatcherServlet初始化

    技术2024-12-18  8

    内容参考自https://my.oschina.net/lichhao/blog/102315

    DispatcherServlet处理请求的流程图

    DispatcherServlet继承关系图

    1、HttpServlet及其父类

    隶属于org.apache.tomcat开发的jar包,定义了init()、service(ServletRequest,ServletResponse)等核心方法

    2、HttpServletBean

    HttpServlet的SpringMVC的实现。通过实现init()方法,解析配置文件(web.xml),从而对BeanWrapper(DispatcherServlet)进行属性的设置

    public final void init() throws ServletException { //1、解析配置文件,读取属性 PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties); if (!pvs.isEmpty()) { try { //2、为Bean设置配置文件中的属性 BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment())); this.initBeanWrapper(bw); bw.setPropertyValues(pvs, true); } catch (BeansException var4) { if (this.logger.isErrorEnabled()) { this.logger.error("Failed to set bean properties on servlet '" + this.getServletName() + "'", var4); } throw var4; } } //3、初始化Bean,交给子类FrameworkServlet实现 this.initServletBean(); }

     

    3、FrameworkServlet

    实现了HttpServletBean的initServlet()方法。调用initWebApplicationContext()负责初始化webIOC。

    protected final void initServletBean() throws ServletException { this.getServletContext().log("Initializing Spring " + this.getClass().getSimpleName() + " '" + this.getServletName() + "'"); if (this.logger.isInfoEnabled()) { this.logger.info("Initializing Servlet '" + this.getServletName() + "'"); } long startTime = System.currentTimeMillis(); try { //初始化IOC,包括DispatcherServlet this.webApplicationContext = this.initWebApplicationContext(); //没有子类实现 this.initFrameworkServlet(); } catch (RuntimeException | ServletException var4) { this.logger.error("Context initialization failed", var4); throw var4; } if (this.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"; this.logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails + "': request parameters and headers will be " + value); } if (this.logger.isInfoEnabled()) { this.logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms"); } } protected WebApplicationContext initWebApplicationContext() { WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext()); WebApplicationContext wac = null; //如果找到已存在的web容器,直接使用此容器并重新初始化 if (this.webApplicationContext != null) { wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac; if (!cwac.isActive()) { if (cwac.getParent() == null) { cwac.setParent(rootContext); } //设置一些新的配置,最终调用了refresh()方法,进行了IOC初始化 this.configureAndRefreshWebApplicationContext(cwac); } } } if (wac == null) { wac = this.findWebApplicationContext(); } //容器==null时,创建新的容器并最终调用refresh()方法,进行了IOC初始化 if (wac == null) { wac = this.createWebApplicationContext(rootContext); } //IOC初始化之后,调用onRefresh(wac)方法,进行MVC的初始化 //这一步在子类DispatcherServlet中进行了实现 if (!this.refreshEventReceived) { Object var6 = this.onRefreshMonitor; synchronized(this.onRefreshMonitor) { this.onRefresh(wac); } } //将ioc设置到Servlet上下文中,以便能通过servletContext调用SpringContext if (this.publishContext) { String attrName = this.getServletContextAttributeName(); this.getServletContext().setAttribute(attrName, wac); } return wac; }

    4、 DispatcherServlet

    protected void onRefresh(ApplicationContext context) { this.initStrategies(context); } //SpringMVC 初始化过程。初始化视图解析器、异常处理器、处理器映射器、处理器适配器等 protected void initStrategies(ApplicationContext context) { this.initMultipartResolver(context); this.initLocaleResolver(context); this.initThemeResolver(context); this.initHandlerMappings(context); this.initHandlerAdapters(context); this.initHandlerExceptionResolvers(context); this.initRequestToViewNameTranslator(context); this.initViewResolvers(context); this.initFlashMapManager(context); }

    4.1、 initHandlerMappings(context)初始化处理器映射器

    策略的初始化大同小异,以处理器映射器的初始化为例。

    private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; //如果从SpringIOC中能获取到handlerMapping,也就是手动指定了handlerMapping if (this.detectAllHandlerMappings) { Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList(matchingBeans.values()); AnnotationAwareOrderComparator.sort(this.handlerMappings); } } else { try { HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class); this.handlerMappings = Collections.singletonList(hm); } catch (NoSuchBeanDefinitionException var3) { ; } } //如果handlerMapping==null,使用默认策略。调用getDefaultStrategies if (this.handlerMappings == null) { this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class); if (this.logger.isTraceEnabled()) { this.logger.trace("No HandlerMappings declared for servlet '" + this.getServletName() + "': using default strategies from DispatcherServlet.properties"); } } } //几乎所有的初始化策略都调用此方法,除了initMultipartResolver() //具体步骤就是 先进行类加载,再调用createDefaultStrategy()方法创建bean,最后加入到集合中 protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) { String key = strategyInterface.getName(); // defaultStrategies 在静态代码块中实例化的, // 取自DispatcherServlet.properties配置文件 String value = defaultStrategies.getProperty(key); if (value == null) { return new LinkedList(); } else { String[] classNames = StringUtils.commaDelimitedListToStringArray(value); List<T> strategies = new ArrayList(classNames.length); String[] var7 = classNames; int var8 = classNames.length; for(int var9 = 0; var9 < var8; ++var9) { String className = var7[var9]; try { Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader()); //通过IOC先生成BeanDefinition,再生成BeanWrapper,最后生成一个bean Object strategy = this.createDefaultStrategy(context, clazz); strategies.add(strategy); } catch (ClassNotFoundException var13) { throw new BeanInitializationException("Could not find DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]", var13); } catch (LinkageError var14) { throw new BeanInitializationException("Unresolvable class definition for DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]", var14); } } return strategies; } }

     DispatcherServlet.properties文件内容:key=value形式。

    # Default implementation classes for DispatcherServlet's strategy interfaces. # Used as fallback when no matching beans are found in the DispatcherServlet context. # Not meant to be customized by application developers. org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\ org.springframework.web.servlet.function.support.RouterFunctionMapping org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\ org.springframework.web.servlet.function.support.HandlerFunctionAdapter org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

    5、总结 

    回顾整个SpringMVC的初始化流程,我们看到,通过HttpServletBean、FrameworkServlet、DispatcherServlet三个不同的类层次,SpringMVC的设计者将三种不同的职责分别抽象,运用模版方法设计模式分别固定在三个类层次中。其中HttpServletBean完成的是<init-param>配置元素的依赖注入,FrameworkServlet完成的是容器上下文的建立,DispatcherServlet完成的是SpringMVC具体编程元素的初始化策略。

    Processed: 0.031, SQL: 9