关于ZAKER 融媒体解决方案 合作 加入

Spring:web.xml 中的 namespace vs contextConfigLocatio.

CocoaChina 09-18

TL; DR

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

命名空间本质上是告诉 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>

答案很长

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

> 根上下文 ( 父 )

> 个人 servlet 上下文 ( 孩子 )

引用 Spring Framework API ( 编写本文时的版本 3.2.2 ) 为WebApplicationContext ( 强调我的 ) :

Like generic application contexts, web application contexts are

hierarchical. There is a single root context per application, while

each servlet in the application ( including a dispatcher servlet in the

MVC framework ) has its own child context.

也在这里:Context hierarchies

For example, if you are developing a Spring MVC web application you

will typically have a root WebApplicationContext loaded via Spring ’ s

ContextLoaderListener and a child WebApplicationContext loaded via

Spring ’ s DispatcherServlet. This results in a parent-child context

hierarchy where shared components and infrastructure configuration are

declared in the root context and consumed in the child context by

web-specific components.

在这里:17.2 The DispatcherServlet

ApplicationContext instances in Spring can be scoped. In the Web MVC

framework, each DispatcherServlet has its own WebApplicationContext,

which inherits all the beans already defined in the root

WebApplicationContext. These inherited beans can be overridden in the

servlet-specific scope, and you can define new scope-specific beans

local to a given Servlet instance.

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

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

You can create ApplicationContext instances declaratively by using,

for example, a ContextLoader. Of course you can also create

ApplicationContext instances programmatically by using one of the

ApplicationContext implementations.

You can register an ApplicationContext using the ContextLoaderListener

( see the example above )

The listener inspects the contextConfigLocation parameter. If the

parameter does not exist, the listener uses

/WEB-INF/applicationContext.xml as a default. When the parameter does

exist, the listener separates the String by using predefined

delimiters ( comma, semicolon and whitespace ) and uses the values as

locations where application contexts will be searched. Ant-style path

patterns are supported as well. Examples are /WEB-INF/*Context.xml for

all files with names ending with "Context.xml", residing in the

"WEB-INF" directory, and /WEB-INF/**/*Context.xml, for all such files

in any subdirectory of "WEB-INF".

Spring 配置通常分为多个文件 . 它更合乎逻辑 , 更方便 , 特别是在大型项目中 . 在我们的示例中 , 我们在自定义位置显式定义了两个配置 XML 文件:daoContext.xml 和 applicationContext.xml:/ WEB-INF / spring /. 同样 , 如果我们没有定义 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

Upon initialization of a DispatcherServlet, Spring MVC looks for a file named

[ servlet-name ] -servlet.xml in the WEB-INF directory of your

web application and creates the beans defined there, overriding the

definitions of any beans defined with the same name in the global

scope.

Consider the following DispatcherServlet Servlet configuration ( in the

web.xml file ) :

<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 和命名空间

从文档 ( 强调我的 ) :

With the above Servlet configuration in place, you will need to have a file called

/WEB-INF/golfing-servlet.xml in your application; this

file will contain all of your Spring Web MVC-specific components

( beans ) . You can change the exact location of this configuration file

through a Servlet initialization parameter ( see below for details ) .

You can customize individual DispatcherServlet instances by adding

Servlet initialization parameters ( init-param elements ) to the Servlet

declaration in the web.xml file. See the following table for the list

of supported parameters.

contextClass: Class that implements WebApplicationContext, which instantiates the context used by this Servlet. By default, the XmlWebApplicationContext is used.

contextConfigLocation: String that is passed to the context instance ( specified by contextClass ) to indicate where context ( s ) can be found. The string consists potentially of multiple strings ( using a comma as a delimiter ) to support multiple contexts.

In case of multiple context locations with beans that are defined twice, the latest location takes precedence.

namespace: Namespace of the WebApplicationContext. Defaults to [ servlet-name ] -servlet.

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

Passes a "contextConfigLocation" servlet init-param to the context

instance, parsing it into potentially multiple file paths which can be

separated by any number of commas and spaces, like

"test-servlet.xml,

myServlet.xml". If not explicitly specified, the context

implementation is supposed to build a default location from the

namespace of the servlet.

The default namespace is " ‘ servlet-name ’ -servlet", e.g. "test-servlet"

for a servlet-name "test" ( leading to a "/WEB-INF/test-servlet.xml"

default location with XmlWebApplicationContext ) . The namespace can

also be set explicitly via the "namespace" 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 docs ( 强调我的 ) :

By default, the configuration will be taken from

"/WEB-INF/applicationContext.xml" for the root context, and

"/WEB-INF/test-servlet.xml" for a context with the namespace

"test-servlet" ( like for a DispatcherServlet instance with the

servlet-name "test" ) .

The config location defaults can be overridden via the

"contextConfigLocation" context-param of ContextLoader and servlet

init-param of FrameworkServlet. Config locations can either denote

concrete files like "/WEB-INF/context.xml" or Ant-style patterns like

"/WEB-INF/*-context.xml" ( see PathMatcher javadoc for pattern

details ) .

使用 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" ) .*/@Overrideprotected String [ ] getDefaultConfigLocations ( ) { if ( getNamespace ( ) != null ) { return new String [ ] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace ( ) + DEFAULT_CONFIG_LOCATION_SUFFIX}; } else { return new String [ ] {DEFAULT_CONFIG_LOCATION}; }}

如您所见 , 源代码说明了一切 .

指定自定义命名空间的示例

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

额外资源 ( 如上所述还不够 :- ) ) :

> Spring Framework Reference

Documentation

> Difference between applicationContext.xml and spring-servlet.xml in Spring

> What is the difference between ApplicationContext and WebApplicationContext in Spring MVC?

> Spring-MVC: What are a "context" and "namespace"?

以上内容由"CocoaChina"上传发布 查看原文

觉得文章不错,微信扫描分享好友

扫码分享