在何处放置以及如何读取基于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来访问属性。
请注意,任何这些方法都需要重新启动应用程序服务器才能体现更改。
黑毡帽