在何处放置以及如何读取基于servlet的应用程序中的configuration资源文件?

在我的Web应用程序中,我必须将电子邮件发送到一组预定义的用户,例如finance@xyz.com ,所以我希望将其添加到.properties文件并在需要时访问它。 这是一个正确的程序,如果是的话,我应该在哪里放置这个文件? 我正在使用Netbeans IDE,它有两个单独的文件夹用于源文件和JSP文件。

这是你的select。 Java Web应用程序归档(WAR)中基本上有三种方法:


把它放在classpath中

所以你可以通过ClassLoader#getResourceAsStream()一个类path相对path:

 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); InputStream input = classLoader.getResourceAsStream("foo.properties"); // ... Properties properties = new Properties(); properties.load(input); 

这里foo.properties应该被放置在webapp的默认类path(例如webapp的/WEB-INF/lib/WEB-INF/classes ,服务器的/lib或者JDK / JRE的/lib 。 如果propertiesfile是特定于webapp的,最好将它放在/WEB-INF/classes 。 如果您在IDE中开发标准WAR项目,请将其放在src文件夹(项目的源文件夹)中。 如果您正在使用Maven项目,请将其放在/main/resources文件夹中。

也可以将其放在默认类path之外的某个位置,并将其path添加到应用服务器的类path。 例如在Tomcat中,您可以将其configuration为Tomcat/conf/catalina.properties shared.loader属性。

如果你把foo.properties放在一个像com.example这样的Java包结构中,那么你需要像下面那样加载它:

 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); InputStream input = classLoader.getResourceAsStream("com/example/foo.properties"); // ... 

请注意,上下文类加载器的这个path不应以/开头。 只有当你使用像SomeClass.class.getClassLoader()这样的“相对”类加载器时,你确实需要用/来启动它。

 ClassLoader classLoader = getClass().getClassLoader(); InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties"); // ... 

但是,属性文件的可见性取决于所涉及的类加载器。 只有加载该类的类加载器才能看到它。 所以,如果类是由例如服务器通用类加载器而不是webapp类加载器加载的,并且属性文件在webapp本身内部,则它是不可见的。 上下文类加载器是最安全的select,因此您可以将属性文件“无处不在”放置在类path中,并且/或者您打算能够从Web应用程序中覆盖服务器提供的属性文件。


2.把它放在webcontent

所以你可以通过ServletContext#getResourceAsStream()用一个webcontent相对path加载它:

 InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties"); // ... 

请注意,我已经演示了将文件放在/WEB-INF文件夹中,否则它将被任何网页浏览器公开访问。 另请注意, ServletContext位于任何可由inheritance的GenericServlet#getServletContext()访问的HttpServlet类中,以及由FilterConfig#getServletContext() Filter 。 如果你不在servlet类中,通常只需通过@Inject注入即可。


把它放在本地磁盘文件系统中

所以你可以用一个绝对的本地磁盘文件系统path来加载它通常的java.io方式:

 InputStream input = new FileInputStream("/absolute/path/to/foo.properties"); // ... 

请注意使用绝对path的重要性。 相对本地磁盘文件系统path在Java EE Web应用程序中是绝对不行的。 请参阅下面的第一个“另请参见”链接。


选哪个?

只需根据自己对可维护性的看法来衡量优势/劣势。

如果属性文件是“静态的”,并且在运行时不需要更改,那么可以将它们保留在WAR中。

如果您希望能够从Web应用程序外部编辑属性文件,而不需要每次重build和重新部署WAR,则将其放在项目之外的类path中(必要时将该目录添加到类path中)。

如果您希望能够使用Properties#store()方法以编程方式从Web应用程序内编辑属性文件,请将其置于Web应用程序之外。 由于Properties#store()需要Writer ,因此无法使用磁盘文件系统path。 该path可以作为VM参数或系统属性传递给Web应用程序。 作为预防措施, 切勿使用getRealPath() 。 部署文件夹中的所有更改都将在重新部署中丢失,原因很简单,原因是这些更改没有反映回原始WAR文件中。

也可以看看:

  • getResourceAsStream()与FileInputStream
  • 添加一个目录到tomcat classpath
  • 以编程方式访问JSF应用程序中的属性文件

警告词:如果将configuration文件放在WEB-INF / classes文件夹中,并且您的IDE(例如Eclipse)执行了清理/重build,则它将会删除您的conf文件,除非它们位于Java源目录中。 BalusC很好的回答暗指在选项1,但我想增加重点。

我学会了如果在Eclipse中“复制”Web项目的困难,它会从任何源文件夹中进行清理/重build。 在我的例子中,我从POJO的java库中添加了一个“链接源代码目录”,它将编译到WEB-INF / classes文件夹中。 在该项目(而不是Web应用程序项目)中进行清理/重build导致了相同的问题。

我想把我的confs放在POJO的src文件夹中,但是confs都是用在WEB-INF / lib文件夹中的第三方libs(比如Quartz或者URLRewrite),所以没有任何意义。 我打算testing把它放在网站项目的“src”文件夹,当我绕过去,但该文件夹目前是空的,并在其中的conf文件似乎不雅。

所以我投票把conf文件放在WEB-INF / commonConfFolder / filename.properties文件夹的旁边 ,这是Balus选项2。

例如:在web.xml文件中的标签

 <context-param> <param-name>chatpropertyfile</param-name> <!-- Name of the chat properties file. It contains the name and description of rooms.--> <param-value>chat.properties</param-value> </context-param> 

而chat.properties你可以像这样声明你的属性

例如:

 Jsp = Discussion about JSP can be made here. Java = Talk about java and related technologies like J2EE. ASP = Discuss about Active Server Pages related technologies like VBScript and JScript etc. Web_Designing = Any discussion related to HTML, JavaScript, DHTML etc. StartUp = Startup chat room. Chatter is added to this after he logs in. 

它只需要在类path中(也就是确保在.war中的/ WEB-INF / classes下作为构build的一部分)。

你可以使用你的源文件夹,所以每当你build立,这些文件被自动复制到类目录。

而不是使用属性文件,使用XML文件。

如果数据太小,甚至可以使用web.xml来访问属性。

请注意,任何这些方法都需要重新启动应用程序服务器才能体现更改。

黑毡帽