Spring:web.xml中的namespace vs contextConfigLocation init参数

时间:2013-04-04 17:42:28

标签: spring spring-mvc dependency-injection

我正在阅读Spring MVC的文档,我有一个关于init params的问题。如果重要,我正在使用Spring 3.2。 contextConfigLocation和命名空间有什么区别? contextConfigLocation是否仅用于指定上下文类可以找到XML定义的文件夹,而namespace属性用于指定文件名?

<servlet>
        <servlet-name>AppServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF</param-value>
        </init-param>
        <init-param>
            <param-name>namespace</param-name>
            <param-value>application-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

这是对的吗?它应该使用/WEB-INF/application-context.xml吗?你应该指定路径吗?

3 个答案:

答案 0 :(得分:166)

TL; DR

只要您需要指定自定义配置文件,只需设置contextConfigLocation的值即可。这样您就可以指定配置文件名及其位置。

namespace本质上是一种替代方式告诉Spring容器上下文加载器类要使用的配置文件。我从不打扰它,但只要在需要配置自定义配置文件时使用contextConfigLocation

以下是我之前的一个Spring项目的示例(为简洁起见省略了一些配置):

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <display-name>Spring Web Application example</display-name>

    <!-- Configurations for the root application context (parent context) -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/jdbc/spring-jdbc.xml
            /WEB-INF/spring/security/spring-security-context.xml
        </param-value>
    </context-param>

    <!-- Configurations for the DispatcherServlet application context (child context) -->
    <servlet>
        <servlet-name>spring-mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/spring/mvc/spring-mvc-servlet.xml
            </param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring-mvc</servlet-name>
        <url-pattern>/admin/*</url-pattern>
    </servlet-mapping>

</web-app>

长答案

好的,首先让我们清楚一些重要的时刻。我们正在处理两种类型的上下文:

  1. 根上下文(父)
  2. 个人servlet上下文(子)
  3. 引用WebApplicationContext(强调我的)的Spring Framework API(编写本文时的版本3.2.2):

      

    与通用应用程序上下文一样,Web应用程序上下文也是如此   分层。 每个应用程序都有一个根上下文,而   应用程序中的每个servlet(包括一个调度程序servlet)   MVC框架)有自己的子上下文

    此处:Context hierarchies

      

    例如,如果您正在开发Spring MVC Web应用程序   通常会通过Spring加载根WebApplicationContext   ContextLoaderListener 和一个子WebApplicationContext通过加载   Spring的DispatcherServlet 。这导致父子上下文   共享组件和基础结构配置的层次结构   在根上下文中声明并在子上下文中使用   特定于网络的组件。

    在这里:17.2 The DispatcherServlet

      

    Spring中的ApplicationContext实例可以作用域。在Web MVC中   框架,每个DispatcherServlet都有自己的WebApplicationContext,   它继承了已在根中定义的所有bean   WebApplicationContext的即可。这些继承的bean可以在中重写   特定于servlet的范围,您可以定义新的特定于范围的bean   给定Servlet实例的本地。


    现在让我们看一下根应用程序上下文配置。这是一个例子:
    的web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                                http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/spring/daoContext.xml
                /WEB-INF/spring/applicationContext.xml
            </param-value>
        </context-param>
    </web-app>
    


    从官方的Spring文档(强调我的):
    5.14.4 Convenient ApplicationContext instantiation for web applications

      

    您可以使用声明性地创建ApplicationContext实例,   例如,ContextLoader。当然你也可以创建   ApplicationContext实例以编程方式使用其中一个   ApplicationContext实现。

         

    您可以使用ContextLoaderListener 注册ApplicationContext   (见上面的例子)

         

    侦听器检查contextConfigLocation参数。 如果   参数不存在,监听器使用   /WEB-INF/applicationContext.xml作为默认值。参数的时候   如果存在,则侦听器使用预定义分隔String   分隔符(逗号,分号和空格)并将值用作   将搜索应用程序上下文的位置。蚂蚁风格的道路   也支持模式。示例是/WEB-INF/*Context.xml for   名称以&#34结尾的所有文件; Context.xml&#34;,驻留在   &#34; WEB-INF&#34;所有此类文件的目录和/WEB-INF/**/*Context.xml   在&#34; WEB-INF&#34;的任何子目录中。


    Spring配置通常分为多个文件。它更合乎逻辑,更方便,特别是在大型项目中。在我们的示例中,我们在自定义位置/WEB-INF/spring/中明确定义了两个配置XML文件: daoContext.xml applicationContext.xml 。同样,如果我们没有定义 contextConfigLocation ContextLoaderListener 将尝试找到默认配置文件: /WEB-INF/applicationContext.xml

    注意:
    根上下文是可选的。另请参阅此答案:https://stackoverflow.com/a/7451389/814702

    因此,如果默认 /WEB-INF/applicationContext.xml 配置文件不符合您的需求,请使用 ContextLoaderListener 以及<context-param> contextConfigLocation 您可以在其中定义自定义配置文件以定义根应用程序上下文


    接下来让我们看一下个人(子)应用程序上下文。从官方的Spring文档(强调我的):
    17.2 The DispatcherServlet

      

    在初始化DispatcherServlet时,Spring MVC会查找名为
    的文件   您的WEB-INF目录中的[servlet-name] -servlet.xml
      Web应用程序并创建在那里定义的bean,覆盖   全局中使用相同名称定义的任何bean的定义   范围。

         

    考虑以下DispatcherServlet Servlet配置(在   web.xml文件):

    <web-app>
    
        <servlet>
            <servlet-name>golfing</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>golfing</servlet-name>
            <url-pattern>/golfing/*</url-pattern>
        </servlet-mapping>
    
    </web-app>
    


    关于contextConfigLocation和命名空间

    从文档(强调我的):

      

    上面的Servlet配置到位后,您需要有一个名为
    的文件   您的申请中/WEB-INF/golfing-servlet.xml;这个   file将包含所有Spring Web MVC特定的组件   (豆子)。您可以更改此配置文件的确切位置   通过Servlet初始化参数(详见下文)   ...
      您可以通过添加自定义单个DispatcherServlet实例   Servlet初始化参数(init-param元素)到Servlet   web.xml文件中的声明。有关列表,请参阅下表   支持的参数。

         
        
    • contextClass :实现WebApplicationContext的类,它实例化此Servlet使用的上下文。默认情况下,使用XmlWebApplicationContext。

    •   
    • contextConfigLocation :传递给上下文实例(由contextClass指定)的字符串,用于指示可以找到上下文的位置。该字符串可能包含多个字符串(使用逗号作为分隔符)以支持多个上下文。   如果多个上下文位置的bean定义了两次,则最新位置优先。

    •   
    • 命名空间 :WebApplicationContext的命名空间。默认为[servlet-name] -servlet。

    •   


    现在让我们研究相关类的API文档。类DispatcherServlet扩展了抽象类FrameworkServlet。来自 FrameworkServlet API文档(强调我的):

      

    传递&#34; contextConfigLocation&#34; servlet init-param到上下文   实例,将其解析为可能的多个文件路径   由任意数量的逗号和空格分隔,如
      &#34;测试servlet.xml中,   myServlet.xml&#34 ;. 如果未明确指定,则为上下文   实现应该从中构建一个默认位置   servlet的命名空间

         

    默认命名空间是&#34;&#39; servlet-name&#39; -servlet&#34;,例如&#34;测试的servlet&#34;   对于servlet-name&#34; test&#34; (导致&#34; /WEB-INF/test-servlet.xml"   XmlWebApplicationContext的默认位置)。 命名空间可以   也可以通过&#34;命名空间&#34;显式设置。 servlet init-param

    这是 FrameworkServlet 源代码的摘录:
    FrameworkServlet.java

    ....
    /**
    * Suffix for WebApplicationContext namespaces. If a servlet of this class is
    * given the name "test" in a context, the namespace used by the servlet will
    * resolve to "test-servlet".
    */
    public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";
    ....
    


    FrameworkServlet 的默认上下文类是XmlWebApplicationContext。来自 XmlWebApplicationContext API文档(强调我的):

      

    默认情况下,将从中获取配置   &#34; /WEB-INF/applicationContext.xml"对于根上下文,和   &#34; /WEB-INF/test-servlet.xml"对于具有命名空间的上下文   &#34;测试的servlet&#34; (对于带有的DispatcherServlet实例   servlet-name&#34; test&#34;)。

         

    可以通过以下方式覆盖配置位置默认值   &#34; contextConfigLocation的&#34; ContextLoader和servlet的context-param   FrameworkServlet的init-param 。配置位置可以表示   具体文件如&#34; /WEB-INF/context.xml"或蚂蚁式的图案   &#34; / WEB-INF / * - context.xml的&#34; (有关模式,请参阅PathMatcher javadoc   详情)。

    使用contextConfigLocation覆盖默认配置位置与上面的根应用程序上下文示例相同。

    至于覆盖默认命名空间,有一些重要的时刻。当您设置新的命名空间时,不要将其添加到/WEB-INF之前,并且不要将.xml添加到其中。如果我们查看 XmlWebApplicationContext 类的源文件,可以发现原因:
    XmlWebApplicationContext.java

    ...
    
    /** Default config location for the root context */
    public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
    
    /** Default prefix for building a config location for a namespace */
    public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
    
    /** Default suffix for building a config location for a namespace */
    public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
    
    ...
    
    /**
    * The default location for the root context is "/WEB-INF/applicationContext.xml",
    * and "/WEB-INF/test-servlet.xml" for a context with the namespace "test-servlet"
    * (like for a DispatcherServlet instance with the servlet-name "test").
    */
    @Override
    protected String[] getDefaultConfigLocations() {
        if (getNamespace() != null) {
            return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
        }
        else {
            return new String[] {DEFAULT_CONFIG_LOCATION};
        }
    }
    

    正如您所看到的,源代码说明了一切。


    指定自定义命名空间

    的示例

    的web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                                http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    
    
        <!-- Configurations for the DispatcherServlet application context (child context) -->
        <servlet>
            <servlet-name>spring-mvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>namespace</param-name>
                <param-value>spring/mvc/spring-mvc</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>spring-mvc</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    
    </web-app>
    

    结果是,容器将查找/WEB-INF/spring-mvc-servlet.xml,而不是使用默认命名空间来构造配置文件的路径(否则为/WEB-INF/spring/mvc/spring-mvc.xml)。

    注意:
    以上与设置自定义命名空间相关的解释适用于默认的XmlWebApplicationContext上下文类。可以指定另一个类,例如AnnotationConfigWebApplicationContext,因此会有一些特殊的时刻。


    结论

    使用contextConfigLocation参数来定义自定义配置文件(根应用程序上下文和单个上下文)更加容易(恕我直言)。唯一的区别是对于根应用程序上下文,您在<context-param>元素中使用 <web-app> ,但不在特定的servlet中(也不要忘记监听器类) 。对于子上下文,您使用 <init-param> 嵌套在<servlet>元素中,用于每个特定的servlet 。请参阅本文开头的示例配置( web.xml )。

    其他资源(好像上面的内容还不够: - )):

答案 1 :(得分:4)

我认为LuckyLuke的答案有很多有用的信息,但它没有回答这个问题。特别是,“namespace”和“contextConfigLocation”参数如何协同工作?

我能找到具体答案的唯一地方是源代码:

  • 命名空间 paremeter设置用于构建默认上下文配置位置的自定义命名空间
  • contextConfigLocation 参数显式设置上下文配置位置,而不是依赖于从命名空间构建的默认位置

答案 2 :(得分:3)

contextConfigLocation和命名空间有什么区别? contextConfigLocation用于指定spring配置文件的路径,这意味着它们将被初始化。 namespace用于指定Spring MVC的DispatcherServlet的路径和名称。默认值为[Dispatcher_name]-servlet.xml,这是一个示例:

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>namespace</param-name>
        <param-value>config/spring-mvc</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

Spring将通过/WEB-INF/config/spring-mvc.xml的路径搜索要用作mvc配置的文件。
contextConfigLocation是否仅用于指定上下文类可以找到XML定义的文件夹

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/config/app-*.xml</param-value>
</context-param>

上面的代码显示,当应用程序启动Spring时,将加载所有名称以'app-'开头并以WEB-INF / config目录中的'.xml'结尾的文件。

它应该使用/WEB-INF/application-context.xml吗?你应该指定路径吗?
通过上面的例子,我们可以知道在配置Spring时我们需要指定完整路径和通用文件名,当SpringMVC只指定路径时(如果它位于目录中,不包括WEB-INF目录)和名称(不包括扩展名)。
希望能帮到你:)。