Spring的bean 配置文件路径问题

在配置beans 的时候,可以使用 ContextLoaderListener 或者 ContextLoaderServlet搭配名为contextConfigLocation 的Context-Param,也可以在DispatchServlet的 init-param中定义。

但是其中要注意的是,无论如何,当web容器初始化DispatchServlet的时候,都会去找这个它对于的配置文件。这个配置文件的默认位置 和名字为/WEB-INF/servletname-servlet.xml。所以,即使已经使用了ContextLoaderListener或 ContextLoaderServlet,配置文件 /WEB-INF/servletname-servlet.xml仍然是必须的。

有时候我们需要自定义所有的配置文件,比如,我希望把所有的spring相关的配置文件都放在目录/WEB-INF/spring/底下,我还希望用文件名 appContent-servlet来取代 envoy-servlet.xml。举个例子:

我的配置文件web.xml的相关部分如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/appContent-servlet.xml
/WEB-INF/config/appContent-service.xml
</param-value>
</context-param>

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<servlet>
<servlet-name>envoy</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

注意,其中的/WEB-INF/config/appContent-servlet.xml其实就是原来默认名为/WEB-INF/envoy-servlet.xml的配置文件。

我们希望这个配置可以工作。但是很可惜,它无法正常启动。

为 什么呢?原因就在于当web容器启动名为envoy的servlet的时候,它会尝试去加载bean定义配置文件。即使我们已经使用了 ContextLoaderListener来加载bean定义,它仍然会发现没有人为这个servlet定义其默认的配置文件,所以它会去尝试使用默认 的路径和名字去加载文件。这个路径就是/WEB-INF/envoy-servlet.xml。可是我们已经把这个文件改名并放在路径/WEB- INF/config/appContent-servlet.xml下了,web容器就会找不到文件,并报错。

那么,我们该怎么办才能正确的配置所有的加载文件呢?我们可以用servlet配置的子节点init-param,而不要ContextLoaderListener或者ContextLoaderServlet。我们还是举个例子:

新的配置文件web.xml的相关部分如下:
<servlet>
<servlet-name>envoy</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/appContent-service.xml,
/WEB-INF/config/appContent-servlet.xml
</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

显然,新的配置更加简洁,而且这一次当web容器名为envoy的servlet的时候,系统可以发现这个servlet需要的名为contextConfigLocation的参数在这里,就会用客户定义的路径去取代默认的路径。

我的疑惑是,既然我们已经使用了context-param来定义contentConfigLocation这个变量,那么当web容器加载名为envoy的servlet的时候,就应该用这个路径来取代默认的路径才对,为什么事实却不是这样呢?

我估计原因是spring并不是配置的这个路径来指明DispatchServlet的配置文件的路径,而是用这个路径来为 ContentLoaderListener或者ContentLoaderServlet指明其配置文件的路径。所以DispatchServlet仍 然需要在启动的时候去加载该servlet的配置文件,就导致了上面的结果。

由于时间不够,没有去确认是否其真实原因,等以后有空再去确认吧。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐