【问题标题】:Application can't find properties file on Tomcat server应用程序在 Tomcat 服务器上找不到属性文件
【发布时间】:2015-08-07 18:42:44
【问题描述】:

我正在尝试让 Tomcat 加载一个外部属性文件,该文件存在于 WAR 文件的类路径之外。

我有一个名为 PropertiesSingleton 的简单类,它应该将属性文件加载到 java.util.Properties 对象中。

package my.test.properties;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class PropertiesSingleton {
    private static String filenameProperty = "testprops";
    private static IProperties properties;      //This is an interface that defines a number of get methods for each property
    private final static Logger log = LoggerFactory
        .getLogger(PropertiesSingleton.class);

    public static void main(String[] args) {
    IProperties props = PropertiesSingleton.load();
    }

    public static synchronized IProperties load() {
    InputStream stream;
    if (properties == null) {
        try {
        String propertyFileName = System.getProperty(filenameProperty);
        String variableFileName = System.getenv(filenameProperty);
        log.debug("Value of "+filenameProperty+" parameter: "+propertyFileName);
        log.debug("Value of "+filenameProperty+" env variable: "+variableFileName);
        PropertiesImpl props = new PropertiesImpl(); //A subclass of java.util.Properties implementing the IProperties interface
        if(propertyFileName != null && !propertyFileName.isEmpty()){
            File file = new File(propertyFileName);
            log.debug("Loading properties from parameter '"+propertyFileName+"'" + (file.exists() ? "" : ", which does not exist") );
            stream = new FileInputStream(file);
        }else if(variableFileName != null && !variableFileName.isEmpty()){
            File file = new File(variableFileName);
            log.debug("Loading properties from environment variable'"+variableFileName+"'"+ (file.exists() ? "" : ", which does not exist"));
            stream = new FileInputStream(file);
        }else{
            log.debug("Loading properties from properties file");
            stream = ClassLoader.getSystemClassLoader().getResourceAsStream("my/test/properties/test.properties");
        }
        if(stream == null){
            log.warn("Could not load the properties file");
            return props;
        }

        props.load(stream);
        properties = props;
        log.info("Loaded properties " + properties);
        } catch (IOException ex) {
        log.error("Could not load properties", ex);
        } catch (Exception ex) {
        log.error("Unexpected Error: Could not load properties", ex);
        throw ex;
        }
    }
    return properties;
    }

    public static synchronized IProperties reload(){
    properties = null;
    return load();
    }

}

当我添加一个 Env 属性并通过我的 IDE 运行 main 方法时,这似乎按预期工作。

2015-05-26 09:17:02,136 DEBUG Value of testprops parameter: null
2015-05-26 09:17:02,139 DEBUG Value of testprops env variable: C:\test\test.properties
2015-05-26 09:17:02,141 DEBUG Loading properties from environment variable'C:\test\test.properties'
2015-05-26 09:17:02,141 INFO Loaded properties {defaultLocale=dk, host=123.123.123.123}

但是,当我有勇气 WAR 打包此代码并在我的本地 Tomcat8 上运行它时,我收到了一条新的令人兴奋的消息。 (tomcat WAR 有时会调用 PropertiesSingleton.load):

2015-05-26 09:17:02,136 DEBUG Value of testprops parameter: null
2015-05-26 09:17:02,139 DEBUG Value of testprops env variable: C:\test\test.properties
2015-05-26 09:17:02,141 DEBUG Loading properties from environment variable'C:\test\test.properties', which does not exist
2015-05-26 09:42:36,114 ERROR Could not load properties
java.io.FileNotFoundException: C:\test\test.properties (The system cannot find the file specified)

Tomcat 中是否有一些安全功能现在允许我访问我的文件系统,或者是其他什么可怕的错误?

我还应该注意,我正在做这个练习,因为我需要一个位于 Tomcat 服务器上 WAR 上下文之外的外部属性文件。有几个原因。例如,多个应用程序将共享来自另一个正在运行的应用程序的配置。 WAR 中的属性文件将非常不切实际。 如果有人知道从 WAR 中读取外部属性文件的另一种方法,那也将被亲切地接受为答案。

【问题讨论】:

  • java.io.FileNotFoundException: C:\test\test.properties(系统找不到指定的文件)明确表示该位置不存在此类文件。请在您的文件系统中手动验证路径。因为如果这是一个访问问题,那么你应该得到类似 java.io.FileNotFoundException: C:\test\test.properties (Access is denied) 的错误
  • stackoverflow.com/questions/13956651/… 以便通过 JNDI 间接完成(= 真正的外部配置),
  • 检查您正在加载的文件“test.properties”是否存在于该路径中,并且它是正确的文件名或文件名中没有空格。
  • 由于 MSWindows 扩展隐藏选项,文件实际上是 test.properties.propertiestest.properties.txt 的可能性很小。嗯?
  • 我确实验证了该文件是可加载的。从我的 IDE 运行类中的 main 方法可以正常工作。在 Tomcat 中运行与战争相同的代码失败。相同的文件,相同的 ENV 参数,相同的计算机。

标签: java tomcat tomcat8


【解决方案1】:

servlet 规范不支持访问底层文件系统,并且不保证可以正常工作,特别是如果访问来自未爆炸的.war-文件(我假设这就是您的情况)。

它使您的应用程序依赖于底层系统 - 操作系统、服务器等。recommended way 是将您的配置打包到 .war 文件中。

如果你必须这样做(我同意外部配置可能是个好主意),这里有一个更独立于操作系统的方法,使用java.net.URLfile: URI scheme

URL url = new URL("file:///test/test.properties");

URLConnection con = url.openConnection();
ResourceUtils.useCachesIfNecessary(con);

InputStream stream = con.getInputStream();

改编自org.springframework.core.io.UrlResource.getInputStream()。如果可以,请使用 Spring 及其 Resource 抽象之类的库/框架。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    • 2012-04-23
    • 2016-04-25
    • 2020-07-18
    相关资源
    最近更新 更多