SpringMVC的DispatcherServlet的默认策略

news/2024/7/7 12:48:45 标签: java, 测试

SpringMVC的DispatcherServlet的默认策略

在使用SpringMVC的时候,我们知道需要HandlerMapping定义请求路径与处理器之间的映射,需要HandlerAdapter来调用处理器方法并返回一个ModelAndView对象,需要ViewResolver来解析视图。这些是SpringMVC中最基本的接口。通常我们都需要在SpringMVC的配置文件中定义好需要使用的HandlerMapping、HandlerAdapter和ViewResolver,基于注解的SpringMVC配置也是类似的。所以一般我们的SpringMVC配置文件会是如下这样:

<mvc:annotation-driven/>
    <!-- 快速注册视图解析器 -->
<mvc:view-resolvers>
    <mvc:jsp prefix="/WEB-INF/views/" suffix=".jsp"/>
</mvc:view-resolvers>

mvc命名空间是Spring提供的一个简化SpringMVC配置的命名空间,<mvc:annotation-driven/>会自动在Spring的bean容器中注册HandlerMapping接口实现RequestMappingHandlerMapping类型的bean和HandlerAdapter接口实现类RequestMappingHandlerAdapter类型的bean。<mvc:view-resolvers/>是用来快速定义ViewResolver实现的,其中<mvc:jsp/>会自动定义一个InternalResourceViewResolver类型的ViewResolver。

针对这些比较基本接口,即使我们不定义它们的实现,SpringMVC内部也给了默认的定义,它管这些叫策略。SpringMVC把这些默认策略都定义在一个叫DispatcherServlet.properties的文件中,它与DispatcherServlet在同一个包中。以下是笔者在使用的4.1.0版本中的DispatcherServlet.properties文件中的定义。

java">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.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
	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

 

从上面的定义中我们可以看出来,在使用SpringMVC时,即使你不定义HandlerMapping,SpringMVC默认也会给你定义一个BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping。HandlerAdapter和ViewResolver也是一样的。还有一些其它的默认策略也请参考DispatcherServlet.properties中。如果默认策略不能满足你的要求,那么我们可以在bean容器中定义我们自己对应的实现,这个时候就会应用我们自己的实现了。我们拿初始化HandlerMapping为例,来看一下DispatcherServlet的源码。

java">/**
 * Initialize the HandlerMappings used by this class.
 * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
 * we default to BeanNameUrlHandlerMapping.
 */
private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;

    if (this.detectAllHandlerMappings) {
        // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
        Map<String, HandlerMapping> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
            // We keep HandlerMappings in sorted order.
            OrderComparator.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) {
        this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
        if (logger.isDebugEnabled()) {
            logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
        }
    }
}

 

从源码中我们可以看到,SpringMVC先会从绑定的ApplicationContext中获取对应的HandlerMapping定义,如果没有取到就会调用getDefaultStrategies(context, HandlerMapping.class)从默认策略中获取。它的代码如下所示。

java">protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
    String key = strategyInterface.getName();
    String value = defaultStrategies.getProperty(key);
    if (value != null) {
        String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
        List<T> strategies = new ArrayList<T>(classNames.length);
        for (String className : classNames) {
            try {
                Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
                Object strategy = createDefaultStrategy(context, clazz);
                strategies.add((T) strategy);
            }
            catch (ClassNotFoundException ex) {
                throw new BeanInitializationException(
                        "Could not find DispatcherServlet's default strategy class [" + className +
                                "] for interface [" + key + "]", ex);
            }
            catch (LinkageError err) {
                throw new BeanInitializationException(
                        "Error loading DispatcherServlet's default strategy class [" + className +
                                "] for interface [" + key + "]: problem with class file or dependent class", err);
            }
        }
        return strategies;
    }
    else {
        return new LinkedList<T>();
    }
}

 

其中的defaultStrategies就是对应的DispatcherServlet.properties文件中的内容。

java">private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";

private static final Properties defaultStrategies;

static {
    // Load default strategy implementations from properties file.
    // This is currently strictly internal and not meant to be customized
    // by application developers.
    try {
        ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
        defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
    }
    catch (IOException ex) {
        throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());
    }
}

 

(注:本文是基于SpringMVC4.1.0所写)


http://www.niftyadmin.cn/n/1122874.html

相关文章

Xcode 添加PCH文件

Xcode 添加PCH文件 1.) 打开你的Xcode工程. 在Supporting Files目录下,选择 File > New > File > iOS > Other > PCH File 然后点击下一步&#xff1b; 2.) 给你的PCH文件起名字TestDemo-Prefix.pch. 例如你的项目工程名为TestDemo然而你的PCH 文件的名字应该为…

安装gcc,g++

安装gcc、g sudo apt-get install make gcc g 查看g版本 g --version转载于:https://www.cnblogs.com/liangliangdetianxia/p/4364846.html

配置管理计划_0402项目管理计划

什么是项目管理计划&#xff1f;在没有学过PMBOK之前&#xff0c;通常&#xff0c;老板找到项目工程师说&#xff0c;这个项目&#xff0c;你做一个计划出来。这时候讲的计划&#xff0c;指的是项目的进度计划。而我们这里讲的项目管理计划&#xff0c;是包含了所有知识领域的一…

01-Vue插值操作

Mustache语法(也就是双括号) <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body><div id"app"> <!-- mustache语法中&#xff0c;不…

也要开始写博   客啦

在朋友的鼓动下也开始弄这种东西HOHO开这个博客呢也没期待会有很多人来看吧只是想从现在开始能够找个地方记录下自己以后生活的点点滴滴~~&#xff01;要是有人来逛偶的小窝窝偶当然是更开心的啦哇卡卡(*^__^*) 8想用本本写日记还是因为觉得太麻烦了>_<也不知道写些什么才…

多线程技术(一)线程概述

进程&#xff1a;是应用程序的一个运行例程&#xff0c;是应用程序的一次动态执行过程。线程&#xff1a;是进程中的一个执行单元&#xff1b;是操作系统分配CPU时间的基本单元。Windows是一个支持多线程的系统。一个进程可以包含若干个线程。 多线程的概念多线程&#xff1a;在…

Android五种基本布局

1.LinearLayout 线性布局&#xff0c;是一种常用的布局&#xff0c;所包含的控件在线性方向上排列&#xff0c;包括水平和竖直两个方向。通过android:orientation属性来指定排列方向是竖直vertical或者水平horizontal。如果LinerLayout的排列方向是horizontal&#xff0c;内部的…

Linux:在文件最后一列添加递增数(awk,cat函数)

假设有文件file1.txt&#xff1a; aa eeeee bb eeeee cc eeeee dd eeeee 先修改为&#xff1a; aa eeeee 1 bb eeeee 2 cc eeeee3 dd eeeee 4 则只需要写上命令&#xff1a; cat file1.txt | awk {print $1,$2 " " NR} 转载于:https://www.cnblogs.com/chenwenyan/p…