如何在 Tomcat 中获取 属性 文件

How to get property file in Tomcat

我使用 Neatbeans 创建了一个 Java Class 图书馆项目。这个class(名称:TestDB.java)是做一些数据库工作。我写了一个 "config.properties" 文件来配置一些属性。 config.properties 位于项目文件夹中。在我的 class TestDB.java:

Properties properties = new Properties(System.getProperties());
String configFile = "config.properties";
properties.load(new FileInputStream(configFile));
String param1 = properties.getProperty("Postgre.Driver1");

我可以用测试用例得到属性,没关系。

当我构建这个项目并创建一个 jar 文件时。我想要另一个 Web 应用程序使用这个 jar 文件来做一些数据库工作。我已经将 jar 包含在我的 webapp 中并构建了一个 webproj.war。当我将此 webproj.war 放置到 Tomcat 和 运行 webapp 时。我无法获取 属性,因为我不知道 Tomcat webapp 中的哪个文件夹可以放置 config.properties。谁能帮我解决这个问题?

Sorry for the long answer, but I'm trying to cover the background as I think your question is a little bit confused.

This answer tries to clarify your understanding of web-apps and reusability a little more generally.

First, it's important to understand that applications typically have to 运行 in multiple environments - dev, sit, uat, production, etc. If you include environment specifics in your binary (jar or war) that means you can only use that binary in a single environment.

The original J2EE assumption was that these environment specifics would be managed by the container (Tomcat in this case). This is what the answer referenced in the first comment of your question is doing. Basically the container provides resources registered in JNDI, which your application can look up.

Now, I think it's fair to say, the J2EE folks where wide of the mark with some of the features, the JNDI resource mechanism being one instance of this, which isn't commonly used these days (at least not in the applications I'm used to).

Now, to try and answer your question.

The first important thing to recognise is that the reason for putting code into a seperate jar is to make it reusable. Since Spring burst onto the scene, one of the fundimental ways to achieve reusability is with dependency injection. Spring aside, dependency injection is nothing more complicated that passing the resources a particular object needs at the time you create that object.

For example, your TestDB class might be instantiated as follows:

TestDB testDB = new TestDB(dataSource);

This still doesn't solve the problem of instantiating the DataSource, however it does place this responsiblity with the code using TestDB rather than TestDB itself.

The simple way to instantiate the DataSource would be include a properties file in the war's classpath (in WEB-INF/classes), which would allow you to do the following (note the DataSource instantiation will be database specific):

Properties properties = new Properties();
properties.load(getClass().getClassLoader().getResourceAsStream("config.properties"))

DataSource dataSource = new PGSimpleDataSource();
dataSource.setServerName(properties.get("database.server.name")); 
...

So this gets you to the point where you're loading a properties file from within your war. However as I stated, this makes the war environment specific.

The best way I know to solve this is to use an exploded war with a symlink to the environment configuration. To do this, you use a context file which you would place in [Tomcat root]/conf/Catalina/localhost.

For example, the given context file:

<?xml version="1.0" encoding="UTF-8"?>

<Context path="/my-app" docBase="/local/apps/my-app/war" distributable="false" allowLinking="true">

  <WatchedResource>WEB-INF/web.xml</WatchedResource>

</Context>

You would have a directory structure like this:

local
  + apps
    + my-app
      + war
        + WEB-INF
          + classes
            + env -> /local/apps/my-app/env
      + env

Where /local/apps/my-app/war/WEB-INF/classes/env is a symlink to /local/apps/my-app/env.

Your properties would now be loaded like this:

Properties properties = new Properties();
properties.load(getClass().getClassLoader().getResourceAsStream("env/config.properties"))

This gives you two releaseable components - the application and the configuration that are simply unpacked to install them.