3

如何配置 PropertyPlaceholderConfigurer 以使用与战争相关的属性文件(某些目录向上)?

我们已经多次运行战争,每场战争都应该读取其配置,例如从../../etc/db.properties.

更新:

是的,属性文件在战争之外。目录结构为:

/htdocs/shop/live/apache-tomat/webapps/shop.war 应该读 /htdocs/shop/live/etc/db.properties

/htdocs/shop/test/apache-tomat/webapps/shop.war 应该读 /htdocs/shop/test/etc/db.properties

4

4 回答 4

2

最后,我们引入了一个新的资源类型“relative:”:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreResourceNotFound" value="true" />
    <property name="locations">
        <list>
            <value>classpath:db.properties</value>
            <value>relative:../../../etc/db.properties</value>
        </list>
    </property>
</bean>

我们扩展了 XmlWebApplicationContext 以注入自定义资源处理:

public class Context extends XmlWebApplicationContext {
    @Override
    public Resource getResource(String location) {
        if (location.startsWith(RelativeResource.RELATIVE_URL_PREFIX)) {
            String relativePath = location.substring(RelativeResource.RELATIVE_URL_PREFIX.length());
            return new RelativeResource(getServletContext(), relativePath);
        }
        return super.getResource(location);
    }
}

这是相对资源类:

public class RelativeResource extends AbstractResource {
    public static final String RELATIVE_URL_PREFIX = "relative:";

    private final ServletContext servletContext;
    private final String relativePath;

    public RelativeResource(ServletContext servletContext, String relativePath) {
        this.servletContext = servletContext;
        this.relativePath = relativePath;
    }

    @Override
    public String getDescription() {
        return "RelativeResource [" + relativePath + "]";
    }

    @Override
    public boolean isReadable() {
        return true;
    }

    @Override
    public boolean isOpen() {
        return true;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        String rootPath = WebUtils.getRealPath(servletContext, "/");
        if (!rootPath.endsWith(File.separator)) rootPath += File.separator;
        String path = rootPath + relativePath;
        return new FileInputStream(path);
    }

}
于 2013-07-04T16:13:29.020 回答
1

我的代码,基于 mazatwork 解决方案:

public class RelativeResource extends AbstractResource {
    private final String relativePath;

    public RelativeResource(String relativePath) {
        this.relativePath = relativePath;
    }

    @Override
    public String getDescription() {
        return "RelativeResource [" + relativePath + "]";
    }

    @Override
    public boolean isReadable() {
        File resourceFile = new File(getAbsoluteFileLocation());
        return resourceFile.exists();
    }

    @Override
    public boolean isOpen() {
        return true;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return new FileInputStream(getAbsoluteFileLocation());
    }

    private String getAbsoluteFileLocation() {
        return Paths.get("").toAbsolutePath().resolve(relativePath).toString();
    }
}

之后我们可以在xml中写入,例如:

<bean id="configurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:application.properties</value>
            <value type="com.blabla.RelativeResource">overrideProperties.properties</value>
        </list>
    </property>
    <property name="ignoreResourceNotFound" value="true"/>
</bean>

这种方法的优点 - 您不会破解 Spring Context 并且不坚持这种破解的上下文实现,您可以使用 Spring 分发中的任何(例如,不是 XmlWebApplicationContext,而是 ClassPathXmlApplicationContext)。

于 2015-10-22T20:34:22.287 回答
0

In your configuration you can specify the properties from the classpath instead of relative to the configuration file.

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations" value="classpath:com/foo/jdbc.properties"/>
</bean>

For this to work you must make sure that the properties file makes it to the classpath.

于 2013-07-03T08:56:24.533 回答
0

不知何故,我无法按照其他人的方法获得所需的路径,所以这是我的工作版本,主要基于 Dmitry 的回答(xml 中的用法相同),而 isReadable() 和 getInputStream() 看起来更像 mazatwork 的版本:

public class RelativeResource extends AbstractResource {
    private final String relativePath;

    public RelativeResource(String relativePath) {
        this.relativePath = relativePath;
    }

    @Override
    public String getDescription() {
        return "RelativeResource [" + relativePath + "]";
    }

    @Override
    public boolean isReadable() {
        return true;
    }

    @Override
    public boolean isOpen() {
        return true;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        String rootPath = this.getClass().getResource("/").getPath();
        rootPath = URLDecoder.decode(rootPath, "UTF-8");
        if (!rootPath.endsWith(File.separator)) rootPath += File.separator;
        String path = rootPath + relativePath;
        return new FileInputStream(path);
    }
}
于 2017-03-02T00:36:30.233 回答