实际问题是:有没有办法让XmlWebApplicationContext使用相对于上下文位置的路径加载资源?为清楚起见,我们假设“上下文位置”是通过setConfigLocation()
方法指定的第一个文件的位置。
详细说明如下:
我在Web层使用Spring MVC,在中间层使用Spring IOC。适当的上下文按层次结构定义,如Spring Documentation中所述:在my-servlet.xml
中定义了web内容,在services.xml
中定义了通过ContextLoaderListener
加载的服务等。中间层可以与Web层一起部署(例如,整个操作在ServletContainer中运行)或单独部署(在这种情况下services.xml
被remote-services.xml
替换为定义远程存根)。除以下问题外,整个设置工作正常:
我有一些资源(其他XML文件,你有什么)与services.xml
所需的文件夹相同,需要所述服务才能访问。使用相对路径将这些资源指定为services.xml
中的依赖项。独立部署中间层时可以正常工作,但在部署在servlet容器中时则不行。在后一种情况下,中间层上下文被实例化为XmlWebApplicationContext
,它根据servlet上下文根加载所有资源,这意味着我必须用 / WEB-INF / 作为前缀,我真的很喜欢避免。使用PropertyPlaceholderConfigurer
也会出现类似的问题。
我知道我可以通过从类路径加载资源来解决这个问题,但这也不理想 - 对于独立部署,这意味着我需要将配置文件夹添加到类路径中,对于Web部署,这意味着必须在WEB下复制所有内容-INF /类。
有什么想法吗?
答案 0 :(得分:3)
我最终扩展了Spring的XmlWebApplicationContext
以允许相对资源路径。这就是我想要的,这使我可以使用相同的context.xml文件,无论它是作为Web应用程序的一部分还是独立部署。
对于任何感兴趣的人来源如下。它是使用SOV(Stack Overflow Voting)许可证发布的:-)这意味着只要你赞成这个答案,你就可以自由地用它做任何事情: - )
import java.io.IOException;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;
/**
* Extends Spring's default web application context to allow relative
* resource paths. Resources without explicitly specified URL protocol
* and / or leading slash are loaded relative to the first location
* from getConfigLocations().
*/
public class SpringApplicationContext extends XmlWebApplicationContext {
@Override
protected Resource getResourceByPath(String path) {
path = StringUtils.cleanPath(path);
if (path.startsWith("/") || (path.indexOf(':')>0)) {
return super.getResourceByPath(path);
}
try {
return super.getResourceByPath(getConfigLocations()[0])
.createRelative(path);
} catch (IOException E) {
// failed to create relative resource - default to standard implementation
return super.getResourceByPath(path);
}
} // getResourceByPath()
}
答案 1 :(得分:1)
我同意这很烦人。我通过做你的建议来解决这个问题,这就是把我的spring配置放在类路径上,所以即使我仍然使用完全限定的导入,它们也可以在任何环境下工作。
我不确定为什么你的classpath配置需要那么复杂。这些文件可以放在java源文件夹和java文件旁边,因此它们的处理方式相同。
答案 2 :(得分:1)
奇怪。您的解决方案对我不起作用。这是我的:
package dmp.springframework.web.context;
import java.io.IOException;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;
public class RelativeResourceXmlWebApplicationContext extends XmlWebApplicationContext {
@Override
protected Resource getResourceByPath(String path) {
path = StringUtils.cleanPath(path);
if (path.startsWith("/") || (path.contains(":"))) {
return super.getResourceByPath(path);
}
try {
String newFilename = super.getResourceByPath(getConfigLocations()[0]).getFile().getParentFile().getAbsolutePath();
newFilename = newFilename + "/" + path;
return new FileSystemResource(newFilename);
} catch (IOException E) {
// failed to create relative resource - default to standard implementation
return super.getResourceByPath(path);
}
} // getResourceByPath()
}