在 servlet 的 init() 中加载属性文件而不使用 web.xml 中的 context-param 标记 [重复]
Posted
技术标签:
【中文标题】在 servlet 的 init() 中加载属性文件而不使用 web.xml 中的 context-param 标记 [重复]【英文标题】:loading properties file in init() of servlet without using context-param tag in web.xml [duplicate] 【发布时间】:2012-04-11 03:47:36 【问题描述】:我有一个 servlet,它在 init() 上读取 .properties 文件。如果我在 web.xml 中设置了上下文参数,我的代码(不是下面的代码)可以工作,但我读到上下文参数是全局可访问的,我不希望这样,因为这个 servlet 只是一个更大的Web应用程序。我只是希望能够使用 init-param 标签来做到这一点 我试过这个:
public void init(ServletConfig config) throws ServletException
try
String fileName = config.getInitParameter("configFile");
System.out.println(fileName);
File file = new File(fileName);
FileInputStream fis = new FileInputStream(file);
p = new Properties();
p.load(fis);
catch (IOException e)
e.printStackTrace();
但我不断收到文件未找到异常。我搜索了互联网,但大多数人使用 servlet 上下文。如果不在 web.xml 中包含 context-param 标记,我还能如何加载我的属性文件?
谢谢!
编辑:
java.io.FileNotFoundException: C:\WEB-INF\classes\myapp.properties (The system cannot find the path specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:120)
at java.io.FileInputStream.<init>(FileInputStream.java:79)
at ipadService.ProxyServlet.init(ProxyServlet.java:53)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1206)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:827)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:129)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)
【问题讨论】:
既然您打印的是 fileName 参数的名称 (configFile
),会发生这种情况吗?您是否看到您在 web.xml 中指定的参数?如果是这样,则该参数似乎有效,并且问题出在您尝试加载文件的方式中。你能添加你得到的异常吗?
相关:getResourceAsStream() vs FileInputStream 和 Where to place configuration files?
是的,它会正确打印出文件名。错误是''
是的,谢谢。我现在明白为什么这不起作用了。我试过'p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));'但我仍然遇到同样的错误
【参考方案1】:
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
@WebServlet("/Propertyloader")
public class Propertyloader extends HttpServlet
private static final long serialVersionUID = 1L;
public static Logger logger;
public static Properties props=new Properties();
public Propertyloader()
super();
public void init(ServletConfig sconfig)
try
logger = Logger.getLogger(Propertyloader.class.getName());
props.load(Propertyloader.class.getClassLoader().getResourceAsStream("books.properties"));
【讨论】:
欢迎来到 SO :) 最好在您发布的代码中添加解释作为答案,这样可以帮助访问者理解为什么这是一个很好的答案。【参考方案2】:不知道你的web.xml是怎么设置的,应该是这样的:
<servlet>
<servlet-name>MyServletName</servlet-name>
<servlet-class>com.mycompany.MyServlet</servlet-class>
<init-param>
<param-name> param1 </param-name>
<param-value> value1 </param-value>
</init-param>
<init-param>
<param-name> param2 </param-name>
<param-value> value2 </param-value>
</init-param>
...
</servlet>
和你的代码一样,你没有使用绝对路径,所以这个文件会在 classes 目录中找到,你应该确保这个文件存在于 WEB-INF/classes 目录中。
【讨论】:
OP 的具体问题是他使用了FileInputStream
,它应该不在应该是可移植的 web 应用程序中使用。参数等是正确的,正如 OP 的 cmets 和异常消息所证实的那样。【参考方案3】:
问题不在于初始化参数设置。问题是您如何访问该文件。确保你的类路径中有一个配置文件,例如在 Web-Inf 目录下;然后更改您的代码以访问文件,如
InputStream is = getClass().getResourceAsStream(fileName);
p = new Properties();
p.load(is);
【讨论】:
你的建议很好,但你的代码错了。 由于 Sandip 没有编辑他的答案,我已经发布了另一个答案。 抱歉代码错误。请在下面找到更正后的代码: InputStream is = getClass().getResourceAsStream("/"+fileName); p = 新属性(); p.load(is); OP 已在文件名中包含/WEB-INF/classes
,因此这种确切的方法将不起作用。【参考方案4】:
鉴于fileName
是/WEB-INF/classes/myapp.properties
,您需要将其作为webapp 资源获取,而不是作为本地磁盘文件系统文件。
所以,替换
String fileName = config.getInitParameter("configFile");
System.out.println(fileName);
File file = new File(fileName);
FileInputStream fis = new FileInputStream(file);
p = new Properties();
p.load(fis);
通过
String fileName = config.getInitParameter("configFile");
InputStream input = config.getServletContext().getResourceAsStream(fileName);
p = new Properties();
p.load(input);
更简单的方法是将fileName
设置为myapp.properties
并将其作为类路径资源获取。
String fileName = config.getInitParameter("configFile");
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
p = new Properties();
p.load(input);
另见:
getResourceAsStream() vs FileInputStream Where to place and how to read configuration resource files in servlet based application?【讨论】:
我可以发誓我在某个时候尝试过这个!我可能错过了什么。谢谢!谢谢大家分享你的知识,我从堆栈溢出中学到了很多东西! 考虑到文件已按上述方式加载 - 我们现在也可以写入吗? - 我正在寻找的是一种使用 web-inf/classes 中的文件路径初始化输出流的方法。这可能吗? @sttaq:没有。另见***.com/questions/2161054/… 嗯,这就是我最终得到的结果 - 必须将我的文件放在其他地方。谢谢 @sttaq:不客气。请注意,理论上您可以使用ServletContext#getRealPath()
将 Web 资源路径转换为绝对磁盘文件系统路径,但是当您重新部署 webapp 时,所有这些更改都会丢失,因为这些更改不包含在原始 WAR 中。作为完全不同的选择,请查看java.util.prefs.Preferences
。它将首选项存储在特定于操作系统的注册表中。然而,它很少在 Java EE webapps 中使用,因为系统管理员更喜欢自我记录的配置文件,他们可以在 vi/notepad 中进行编辑。以上是关于在 servlet 的 init() 中加载属性文件而不使用 web.xml 中的 context-param 标记 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
PyQt -> PySide:在 __init__ 中加载 ui 文件