Spring:命名空间vs contextConfigLocation web.xml中的init参数

我正在阅读Spring MVC的文档,我有一个关于init params的问题。 如果有问题,我正在使用Spring 3.2。 contextConfigLocation和名称空间有什么区别? contextConfigLocation仅用于指定上下文类可以findXML定义的文件夹,而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吗? 而且你应该指定path?

TL; DR

只要需要指定自定义configuration文件,只需设置contextConfigLocation的值即可。 这样你将指定configuration文件名和它们的位置。

namespace本质上是告诉Spring容器上下文加载器类使用什么configuration文件的一种替代方法 。 我从来不打扰它,但只要使用contextConfigLocation每当我需要configuration自定义configuration文件。

下面是我以前的一个Spring项目中的一个例子(为简洁起见,省略了一些configuration):

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> 

长答案

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

  1. 根上下文 (父)
  2. 单独的servlet上下文 (子)

引用来自Spring框架API(在编写这个时刻的版本3.2.2)的WebApplicationContext (强调我的):

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

同样在这里: 上下文层次结构 :

例如,如果您正在开发Spring MVC Web应用程序,则通常会通过Spring的ContextLoaderListener加载根WebApplicationContext,通过Spring的DispatcherServlet加载子WebApplicationContext 。 这会产生父子上下文层次结构,其中共享组件和基础结构configuration在根上下文中声明,并由特定于Web的组件在子上下文中使用。

在这里: 17.2 DispatcherServlet :

Spring中的ApplicationContext实例可以被限定范围。 在Web MVC框架中, 每个DispatcherServlet都有自己的WebApplicationContext,它inheritance了已经在根WebApplicationContext中定义的所有bean 。 这些inheritance的bean可以在特定于servlet的范围中重写,并且可以为给定的Servlet实例定义新的特定于范围的bean。

现在我们来看看根应用程序的上下文configuration。 这里是一个例子:
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 Web应用程序的便捷ApplicationContext实例化 :

您可以通过使用例如ContextLoader以声明方式创buildApplicationContext实例 。 当然,您也可以通过使用ApplicationContext实现之一以编程方式创buildApplicationContext实例。

您可以使用ContextLoaderListener注册ApplicationContext (请参阅上面的示例)

监听器检查contextConfigLocation参数。 如果该参数不存在,那么侦听器将使用/WEB-INF/applicationContext.xml作为默认值 。 当参数确实存在时,侦听器使用预定义的分隔符(逗号,分号和空格)分隔string,并将这些值用作应用程序上下文将被search的位置。 Ant样式的path模式也被支持。 示例是/WEB-INF/*Context.xml,其中名称以“Context.xml”结尾,驻留在“WEB-INF”目录中的所有文件以及/WEB-INF/**/*Context.xml这些文件在“WEB-INF”的任何子目录中。

很多时候,Springconfiguration被分割成多个文件。 这更合乎逻辑,更方便,特别是在大型项目中。 在我们的例子中,我们明确定义了两个configurationXML文件: daoContext.xmlapplicationContext.xml在自定义位置: /WEB-INF/spring/ 。 再次,如果我们没有定义contextConfigLocationContextLoaderListener将尝试find默认的configuration文件: /WEB-INF/applicationContext.xml

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

因此,如果默认的/WEB-INF/applicationContext.xmlconfiguration文件不适合您的需要,请使用ContextLoaderListener<context-param> contextConfigLocation ,您可以在其中定义自定义configuration文件来定义根应用程序上下文

接下来让我们看看个人(孩子)应用程序的上下文 。 从官方的Spring文档(重点是我的):
17.2 DispatcherServlet

在初始化DispatcherServlet之后,Spring MVC将查找一个名为的文件
[servlet-name] -servlet.xml,并创build在那里定义的bean,覆盖在全局范围内定义的具有相同名称的bean的定义。

考虑以下DispatcherServlet Servletconfiguration(在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和名称空间

从文档(重点是我的):

通过上面的Servletconfiguration,您将需要一个名为的文件
/WEB-INF/golfing-servlet.xml ; 这个文件将包含所有的Spring Web MVC特定的组件(bean)。 您可以通过Servlet初始化参数来更改此configuration文件的确切位置(请参阅下面的详细信息)。

您可以通过将Servlet初始化参数(init-param元素)添加到web.xml文件中的Servlet声明来自定义单独的DispatcherServlet实例 。 请参阅下表以获取支持的参数列表。

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

  • contextConfigLocation :传递给上下文实例(由contextClass指定)的string,用于指示可以在何处find上下文。 该string可能包含多个string(使用逗号作为分隔符)以支持多个上下文。 在定义了两次bean的多个上下文位置的情况下,最新的位置优先。

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

现在我们来研究相关类的API文档。 DispatcherServlet类扩展了抽象类FrameworkServlet 。 从FrameworkServlet API文档(重点是我的):

将“contextConfigLocation”servlet init-param传递给上下文实例,将其parsing为可能被多个逗号和空格分隔的多个文件path,如
“test-servlet.xml,myServlet.xml”。 如果没有明确指定,则上下文实现应该从servlet的名称空间构build一个默认位置

默认名称空间是“servlet-name-servlet”,例如servlet-name“test”的“test-servlet”(通向XmlWebApplicationContext的“/WEB-INF/test-servlet.xml”默认位置)。 命名空间也可以通过“命名空间”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文档(重点是我的):

默认情况下,configuration将取自“/WEB-INF/applicationContext.xml”作为根上下文,“/WEB-INF/test-servlet.xml”作为命名空间为“test-servlet”的上下文(例如对于servlet名称为“test”的DispatcherServlet实例)。

configuration位置默认值可以通过ContextServlet的ContextLoader和servlet init-param的“contextConfigLocation”上下文参数覆盖 。 configuration位置既可以表示具体文件,如“/WEB-INF/context.xml”,也可以表示为“/WEB-INF/*-context.xml”(请参阅​​PathMatcher javadoc获取模式细节)。

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

至于重写的默认名称空间有一些重要的时刻。 当你设置一个新的命名空间时, 不要使用/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> 

结果是,不是使用默认名称空间来构buildconfiguration文件的path,否则它将是/WEB-INF/spring-mvc-servlet.xml ,容器将查找/WEB-INF/spring/mvc/spring-mvc.xml

注意:
上述与设置自定义名称空间有关的解释是默认的XmlWebApplicationContext上下文类。 可以指定一个替代类,比如AnnotationConfigWebApplicationContext ,所以会有一些特殊的时刻。


结论

这是(恕我直言)更容易使用contextConfigLocation参数来定义自定义configuration文件,为根应用程序上下文和个人上下文。 唯一的区别是,对于根应用程序上下文,您可以在<web-app>元素中使用<context-param> ,但不能在特定的servlet中使用(也不要忘记监听器类)。 而对于子上下文,您可以使用嵌套在每个特定servlet<servlet>元素中的<init-param> 。 看到我的示例configuration( web.xml )在这篇文章的开头。

其他来源(就像上面的不够:-)):

  • Spring框架参考文档
  • Spring MVC上下文加载

也看到这些答案:

  • Spring中applicationContext.xml和spring-servlet.xml的区别
  • ApplicationContext和WebApplicationContext在Spring MVC中有什么区别?
  • Spring-MVC:什么是“上下文”和“命名空间”?

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

唯一的地方,我可以find具体的答案是源代码:

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

contextConfigLocation和名称空间有什么区别? contextConfigLocation用于指定springconfiguration文件的path,这意味着它们将被初始化。 命名空间用于指定Spring MVC的DispatcherServlet的path和名称。 默认是[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的path来search要使用的文件,因为它是mvc config。
contextConfigLocation仅用于指定上下文类可以findXML定义的文件夹

 <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吗? 而且你应该指定path?
通过上面的例子我们可以知道,在configurationSpring时,我们需要指定完整path和通用文件名,而当SpringMVC只需要指定path(如果它位于一个目录中,不包括WEB-INF目录)和名称(不包括扩展名)。
希望能帮助你:)