简体   繁体   English

通过Spring XmlWebApplicationContext指定相对资源路径

[英]Specifying relative resource path via Spring XmlWebApplicationContext

The actual question is: Is there a way to get XmlWebApplicationContext to load resources using paths relative to the context location? 实际的问题是:有没有一种方法可以使XmlWebApplicationContext使用相对于上下文位置的路径来加载资源? For clarity's sake, let's say "context location" is the location of the first file specified via setConfigLocation() method. 为了清楚起见,假设“上下文位置”是通过setConfigLocation()方法指定的第一个文件的位置。

Detailed explanation is below: 详细说明如下:
I'm using Spring MVC in web tier and Spring IOC in mid tier. 我在Web层中使用Spring MVC,在中间层中使用Spring IOC。 Appropriate contexts are defined hierarchically as described in Spring Documentation : web stuff is defined in my-servlet.xml and services et al are defined in services.xml that's loaded via ContextLoaderListener . Spring文档中所述,分层定义了适当的上下文:Web东西在my-servlet.xml中定义, services.xml等在通过ContextLoaderListener加载的services.xml中定义。 Mid tier can be deployed either together with web tier (eg the whole thing runs within ServletContainer) or separately (in which case services.xml is replaced by remote-services.xml defining remote stubs). 中间层可以与Web层一起部署(例如,整个事情都在ServletContainer中运行),也可以单独部署(在这种情况下, services.xml被定义远程存根的remote-services.xml取代)。 The whole setup works perfectly except for the following problem: 除以下问题外,整个安装程序运行正常:

I have certain resources (additional XML files, what have you) located in the same folder as services.xml that need to be accessible by said services. 我在与services.xml相同的文件夹中有某些资源(其他XML文件,您拥有什么),所述services.xml需要访问这些资源。 Those resources are specified as dependencies in services.xml using relative paths. 这些资源使用相对路径在services.xml中指定为依赖项。 When mid tier is deployed standalone that works fine, but not when it's deployed within servlet container. 当中间层独立部署时可以正常工作,但在servlet容器内部署时则不能。 In the latter case mid tier context gets instantiated as XmlWebApplicationContext which loads all resources based of servlet context root meaning I have to prefix everything with /WEB-INF/ which I'd really like to avoid. 在后一种情况下,中间层上下文被实例化为XmlWebApplicationContext ,该加载基于servlet上下文根的所有资源,这意味着我必须在所有内容前加上/ WEB-INF /作为前缀,这是我要避免的。 Using PropertyPlaceholderConfigurer presents a similar problem as well. 使用PropertyPlaceholderConfigurer存在类似的问题。

I know I can work around this somewhat by having resources load from classpath, but that's not ideal either - for standalone deployment it means I need to add configuration folder to classpath and for web deployment it means everything has to be copied under WEB-INF/classes. 我知道我可以通过从类路径加载资源来解决此问题,但这也不理想-对于独立部署,这意味着我需要将配置文件夹添加到类路径,对于网络部署,这意味着所有内容都必须在WEB-INF /下复制类。

Any ideas? 有任何想法吗?

I've ended up extending Spring's XmlWebApplicationContext to allow relative resource paths. 我最终扩展了Spring的XmlWebApplicationContext以允许相对的资源路径。 This does what I want, that is allows me to use the same context.xml file no matter whether it's deployed as part of web app or standalone. 这就是我想要的,这使我无论使用Web应用程序还是独立应用程序都可以使用相同的context.xml文件。

For anyone interested source is available below. 对于任何有兴趣的人士,可以在下面找到。 It's published using SOV (Stack Overflow Voting) license :-) which means you're free to do whatever you want with it as long as you upvote this answer :-) 它是使用SOV(堆栈溢出投票)许可证:-)发布的,这意味着只要您支持此答案,您就可以随意使用它进行任何操作。

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()
}

I agree that is rather annoying. 我同意这很烦人。 I get around this by doing what you suggest, which is putting my spring config on the classpath, so even though I still use fully-qualified imports, they work under any environment. 我会按照您的建议解决此问题,这会将我的spring配置放在类路径中,因此即使我仍然使用完全合格的导入,它们也可以在任何环境下工作。

I'm not sure why your classpath config needs to be that complex, though. 我不确定为什么您的类路径配置需要这么复杂。 The files can just under your java source folder alongside the java files, so they get handled the same. 这些文件可以放在java文件旁边的java源文件夹下,因此它们的处理方式相同。

Strange. 奇怪。 Your solution does not work for me. 您的解决方案对我不起作用。 Here is mine: 这是我的:

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()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM