通过xml配置SpringMVC注解DispatcherServlet初始化过程解析

 更新时间:2023年10月12日 10:04:35   作者:福  
这篇文章主要为大家介绍了通过xml配置SpringMVC注解DispatcherServlet初始化过程解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

xml方式初始化DispatcherServle配置

通过xml方式初始化DispatcherServlet时,xml文件中可以配置:

<mvc:annotation-driven />

或:

<mvc:annotation-driven >
        <!--设置响应输出字符集-->
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=utf-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

表示对MVC注解的支持。

该标签的解析工作最终会由AnnotationDrivenBeanDefinitionParser的parse方法完成,parse方法主要完成以下工作

  • 注册RequestMappingHandlerMapping的beanDefinition到WebApplication容器
  • 注册RequestMappingHandlerAdapter的beanDefinition到WebApplication容器,同时从xml文件解析其messageConverters的定义(这也是xml文件中messageConverters生效的原因)
  • 注册ExceptionHandlerExceptionResolver的beanDefinition到WebApplication容器
  • 注册ResponseStatusExceptionResolver的beanDefinition到WebApplication容器
  • 注册DefaultHandlerExceptionResolver的beanDefinition到WebApplication容器

根据beanDefinition创建对应的bean

之后在容器refresh的过程中根据beanDefinition创建对应的bean。

之后,在DispatcherServlet初始化的过程中,通过initStrategies初始化SpringMVC的相关“特殊类型的Bean”:

protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context);
        initHandlerMappings(context);
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }

比如initHandlerMappings方法:

private void initHandlerMappings(ApplicationContext context) {
        this.handlerMappings = null;
        if (this.detectAllHandlerMappings) {
            // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
            //首先通过beanFactoryUtils从Spring容器中,通过类型获取
            Map<String, HandlerMapping> matchingBeans =
                    BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
            //如果从容器中获取到了bean,放入到handlerMappings中
            if (!matchingBeans.isEmpty()) {
                this.handlerMappings = new ArrayList<>(matchingBeans.values());
                // We keep HandlerMappings in sorted order.
                AnnotationAwareOrderComparator.sort(this.handlerMappings);
            }
        }
        else {
            try {
                //通过名字和类型从容器获取
                HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
                this.handlerMappings = Collections.singletonList(hm);
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Ignore, we'll add a default HandlerMapping later.
            }
        }
        // Ensure we have at least one HandlerMapping, by registering
        // a default HandlerMapping if no other mappings are found.
        if (this.handlerMappings == null) {
            //从容器中没有获取到,才调用getDefaultStrategies获取默认的、dispatcherServlet.properties文件中定义的
            this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
            if (logger.isTraceEnabled()) {
                logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
                        "': using default strategies from DispatcherServlet.properties");
            }
        }
    }

如果xml文件中不配置<mvc:annotation-driven />,也没有 <mvc:default-servlet-handler />,则Spring容器中就不会有对应的bean,这种情况下,才通过调用getDefaultStrategies方法,读取DispatcherServlet.properties文件获取该文件定义的默认HandlerMappings,完成创建,当然,创建后也会放入Spring容器:

protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {
        return context.getAutowireCapableBeanFactory().createBean(clazz);
    }

DefaultServletHandlerBeanDefinitionParser

xml文件中如果配置了 <mvc:default-servlet-handler />,SpringMVC启动时解析 <mvc:default-servlet-handler />标签过程中会调用DefaultServletHandlerBeanDefinitionParser,其parse方法会将SimpleUrlHandlerMapping以及BeanNameUrlHandlerMapping注入到WebApplicationContext容器中,目的是通过SimpleUrlHandlerMapping来处理"/**"请求(转交给DefaultServletHttpRequestHandler)。

这个处理有个副作用:由于SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping作为handlerMappings注入到容器中,分析DispatcherServlet的初始化方法initHandlerMappings的源码可知:

DispatcherServlet.properties文件中默认的RequestMappingHandlerMapping不会被注入!

而RequestMappingHandlerMapping是具体负责SpringMVC注解解释的,没有了RequestMappingHandlerMapping,类似@Controller等SpringMVC注解就不会生效。

所以,其实SpringMVC默认情况下天生是可以支持SpringMVC注解的,只不过是 <mvc:default-servlet-handler />往往不可避免的需要配置(因为项目中总有静态资源需要展示),但是加了 <mvc:default-servlet-handler />会导致SpringMVC的注解失效!

因此导致了,正常的SpringMVC项目的以下两项配置往往需要成对出现:

<mvc:annotation-driven />
 <mvc:default-servlet-handler />

以上就是通过xml配置SpringMVC注解DispatcherServlet初始化过程解析的详细内容,更多关于xml配置SpringMVC注解的资料请关注脚本之家其它相关文章!

相关文章

  • springboot如何静态加载@configurationProperties

    springboot如何静态加载@configurationProperties

    这篇文章主要介绍了springboot如何静态加载@configurationProperties,本文一个错误案例和成功案例结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • springboot整合quartz实现定时任务示例

    springboot整合quartz实现定时任务示例

    spring支持多种定时任务的实现。我们来介绍下使用spring的定时器和使用quartz定时器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-04-04
  • springBoot2.6.2自动装配之注解源码解析

    springBoot2.6.2自动装配之注解源码解析

    对于springboot个人认为它就是整合了各种组件,然后提供对应的自动装配和启动器(starter),基于这个流程去实现一个定义的装配组件,下面这篇文章主要给大家介绍了关于springBoot2.6.2自动装配之注解源码解析的相关资料,需要的朋友可以参考下
    2022-01-01
  • 关于SpringBoot配置文件application.properties的路径问题

    关于SpringBoot配置文件application.properties的路径问题

    这篇文章主要介绍了关于SpringBoot配置文件application.properties的路径问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • java.lang.NoClassDefFoundError错误的原因及解决方法

    java.lang.NoClassDefFoundError错误的原因及解决方法

    这篇文章主要给大家介绍了关于java.lang.NoClassDefFoundError错误的原因及解决的相关资料,java.lang.NoClassDefFoundError是Java虚拟机在运行时无法找到特定类的错误,需要的朋友可以参考下
    2023-10-10
  • Java实现软件运行时启动信息窗口的方法

    Java实现软件运行时启动信息窗口的方法

    这篇文章主要介绍了Java实现软件运行时启动信息窗口的方法,比较实用的功能,需要的朋友可以参考下
    2014-08-08
  • 如何使用Spring Boot ApplicationRunner解析命令行中的参数

    如何使用Spring Boot ApplicationRunner解析命令行中的参数

    这篇文章主要介绍了使用Spring Boot ApplicationRunner解析命令行中的参数,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-12-12
  • Java Swing JTextArea文本区域的实现示例

    Java Swing JTextArea文本区域的实现示例

    这篇文章主要介绍了Java Swing JTextArea文本区域的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • Spring之什么是ObjectFactory?什么是ObjectProvider?

    Spring之什么是ObjectFactory?什么是ObjectProvider?

    这篇文章主要介绍了Spring之什么是ObjectFactory?什么是ObjectProvider?具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • SpringBoot之spring.factories的使用方式

    SpringBoot之spring.factories的使用方式

    这篇文章主要介绍了SpringBoot之spring.factories的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01

最新评论