动态Web项目中conf.properties在Servlet不识别但main方法可用的原因
问题描述
我在Web应用根目录下放置了conf.properties文件,在ManageBDD类中编写了init方法用于初始化参数。当在Servlet中调用该init方法时,文件无法被识别;但在ManageBDD类的main方法中调用该方法却可以正常工作。请问为何会出现这种差异?(throws Exception仅用于测试该方法)
相关代码
ManageBDD类的init方法
public static void init() throws Exception { FileInputStream file = new FileInputStream("conf.properties"); Properties prop = new Properties(); prop.load(file); pDriver = prop.getProperty("jdbc.driver"); pUrl = prop.getProperty("jdbc.url"); pLogin = prop.getProperty("jdbc.login"); pPass = prop.getProperty("jdbc.pass"); System.out.println("in class : " + prop.getProperty("jdbc.login")); System.out.println("in class : " + prop.getProperty("jdbc.pass")); System.out.println("in class : " + prop.getProperty("jdbc.driver")); System.out.println("in class : " + prop.getProperty("jdbc.url")); }
项目目录结构

可正常运行的调用(main方法)
public static void main(String[] args) throws Exception { init(); }
无法正常工作的调用(Servlet)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { ManageBDD.init(); } catch (Exception e) { e.printStackTrace(); } //request.getRequestDispatcher("/index.jsp").forward(request, response); }
原因分析
两种场景的核心差异是当前工作目录不同:
- 用
main方法运行时,程序的当前工作目录就是你的项目根目录,刚好是conf.properties所在的位置,所以FileInputStream能直接找到文件。 - 当Web应用部署到服务器运行时,程序的当前工作目录是服务器的启动目录(比如Tomcat的
bin目录),不是你的Web应用根目录,自然找不到这个配置文件。
另外,FileInputStream是基于本地文件系统读取的,一旦Web应用打包成WAR包,配置文件会被嵌入包内,此时用文件系统路径也无法访问到包里的资源。
解决方法
针对Web应用场景,推荐两种正确的资源读取方式:
方法一:类加载器读取(推荐)
把conf.properties放到项目的src/main/resources目录下(编译后会自动进入类路径),然后用类加载器读取资源流:
public static void init() throws Exception { InputStream inputStream = ManageBDD.class.getClassLoader().getResourceAsStream("conf.properties"); Properties prop = new Properties(); prop.load(inputStream); pDriver = prop.getProperty("jdbc.driver"); pUrl = prop.getProperty("jdbc.url"); pLogin = prop.getProperty("jdbc.login"); pPass = prop.getProperty("jdbc.pass"); // 保留原打印逻辑 }
方法二:通过Servlet上下文获取Web根路径
如果要保留conf.properties在Web应用根目录,可以在Servlet中获取Web根的绝对路径,再传递给init方法:
修改Servlet中的调用代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { String webRootPath = getServletContext().getRealPath("/"); ManageBDD.init(webRootPath); } catch (Exception e) { e.printStackTrace(); } }
修改ManageBDD的init方法
public static void init(String webRootPath) throws Exception { FileInputStream file = new FileInputStream(webRootPath + "conf.properties"); Properties prop = new Properties(); prop.load(file); pDriver = prop.getProperty("jdbc.driver"); pUrl = prop.getProperty("jdbc.url"); pLogin = prop.getProperty("jdbc.login"); pPass = prop.getProperty("jdbc.pass"); // 保留原打印逻辑 }
内容的提问来源于stack exchange,提问作者Nicolas Zanforlini
相关产品推荐
相关产品推荐

