将配置值传递给servlet而不在.war文件中对其进行硬编码?

时间:2014-02-11 16:34:25

标签: java eclipse tomcat servlets

我正在使用Eclipse和Tomcat 6在Java中开发Web应用程序。

我需要将值传递给未经硬编码到.war文件中的servlet
例如,假设我的servlet需要一个文件名,并且每个服务器上的文件名都不同。
如何将它传递给servlet,而不在.war文件中对其进行硬编码?

请帮我解释如何执行此操作:

  • 来自Eclipse内部(例如:将xxxx添加到文件yyy然后运行)
  • 在我将部署应用程序的服务器上

我正在考虑getInitParameter的方向,但我没有找到传递init参数的方法,除了 .war文件中的web.xml ,这不是一个选项,因为它需要是可配置的。因此,如果您可以告诉我如何在外部文件中设置init参数,问题就解决了。

注意:我正在寻找非常确切的建议,例如“在那个位置<编辑那个文件”。我发现了许多相关的问题和答案,但没有一个具体到足以让它发挥作用。

4 个答案:

答案 0 :(得分:3)

有很多方法可以解决这个问题。这实际上取决于您知道您要加载的文件的位置。如果您要为每个tomcat实例/服务器配置它,那么环境变量或JVM参数可能是最简单的。然后,您可以通过代码中的System.getProperty查找此变量。

您可以通过CATALINA_HOME / bin / setenv.sh基于每个tomcat传递JVM参数。

#!/bin/sh
CATALINA_OPTS="$CATALINA_OPTS
    -Dmy.file.path=/path/on/this/host/file.txt"

在您的代码中:

String path = System.getProperty("my.file.path")

Dhanush的建议也是一个很好的建议,从长远来看可能更具可持续性。它的优点是可以将所有每个环境配置保存在一个可以保留在源代码管理中的位置。但是,根据他的方法,您仍然需要一种方法从属性文件中选择适当的密钥(因为此属性文件将在您的战争中捆绑),您可以再次使用环境变量或JVM参数来控制。

如果你想稍微发现一点,你可以考虑使用JNDI

答案 1 :(得分:1)

如果已知配置的位置,则可以将其作为servlet参数传递。在您声明servlet的web.xml中(我将configFile称为您希望获得引用的文件):

<servlet>
    <servlet-name>ConfigParser</servlet-name>
    <servlet-class>foo.baar.ConfigParser</servlet-class>
    <init-param>
        <param-name>configFilePath</param-name>
        <param-value>/path/to/the/config/file</param-value>
    </init-param>
</servlet>

我想你知道web.xml文件的位置,因为你已经在使用servlet了。

然后在您的servlet中,您可以ServletConfig.getInitParameter("configFilePath")获取配置文件的位置。例如在你的servlet中:

public void init(ServletConfig config) throws ServletException {
    super.init(config);
    String path_to_config_file=config.getInitParameter("configFilePath");
}

Container将使用ServletConfig调用此方法,您将获得对配置文件的引用。 这意味着,您根本不需要在eclipse中拥有该文件。使用这种方法,您无需在服务器上执行任何特殊操作,唯一需要注意的是文件被复制并且您在web.xml上声明的路径是正确的。

如果可以动态构造文件的位置,则可以使用ServletContext.getRealPath(“/”)返回webapp的绝对路径。

<强> --- --- UPDATE

回答更新后的问题。我不知道这样做的最佳做法是什么,但有一种解决方法。您在tomcat主目录中创建一个文件(conf_location.txt),该文件包含一行,其中包含要传递给servlet的文件的位置。在您的servlet中,您可以通过此hack访问该文件(假设您的战争在$TOMCAT_HOME/webapps/mywar.war中):

  public void init() throws ServletException{
      String contextPath=getServletContext().getRealPath("/");
      File tomcatHome=new File(contextPath).getParentFile().getParentFile();
      File configFile=new File(tomcatHome,"conf_location.txt");
      try {
          String config_location = new Scanner(configFile).useDelimiter("\\Z").next();
      } catch (Exception e) {}
  }

答案 2 :(得分:1)

  1. 对于一个真实的项目,你不应该直接使用servlet。使用有助于指导您的方向的框架。春天很常见。
  2. 如果您使用Spring,那么在您的应用程序上下文中,您将拥有一个名为Property Placeholder Configurer的bean。例如,请参阅:spring PropertyPlaceholderConfigurer and context:property-placeholder。最佳做法是对该文件位置(file:classpath:)进行硬编码,但将其保存在WAR文件之外。
  3. 应用context.xml中:

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config/properties/database.properties</value>
            </list>
        </property>
        <property name="ignoreResourceNotFound" value="true"/>
    </bean>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>
    
    1. 在需要它的代码中加载配置文件有几个设计问题。它使测试变得困难,它使得一般设计不那么灵活,如果明天你认为属性文件不够而且你想在ZooKeeper或JNDI之类的东西中存储配置,你必须重写很多代码。将代码编写为注入设置的对象,并按照上面的dataSource模式对其进行实例化。

答案 3 :(得分:0)

在servlet代码中,您可以从属性文件中加载它,该文件位于类路径中,如下所示

    Properties props = new Properties();
    try {
        props.load(this.getClass().getClassLoader().getResourceAsStream("config.properties"));
    } catch (IOException e1) {
        log.error(e1.getMessage(), e1);
    }
    String prop1 = props.getProperty("prop1");