起因
最近在学习Servlet,发现每一次读取资源文件的时候都会有路径错误的问题,通过研究后总结了些经验,记录下来以备后人查询。
配置文件的位置
以properties配置文件为示例,在工程里面放置的经典位置有三种:
- 在src目录下
- 在src目录下的package中
在WebRoot目录下
(db.properties为例子配置文件)
路径配置
提醒:
在Eclipes/MyEclipse中,在项目提交到tomcat后,tomcat把src中的所以java文件编译为class文件,然后默认放到WEB-INF的classes文件夹中,如果src有非java文件,则这些文件直接放到WEB-INF的classes文件夹,而src文件是不存在web项目中的。以下为我ServletDemo11.java的代码,请注意下面的相对路径。
package top.cheungchingyin.demo;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ServletDemo11
*/
@WebServlet("/ServletDemo11")
public class ServletDemo11 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ServletDemo11() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
test5();
}
private void test1() throws IOException {
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(in);
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
System.out.println("读取src目录下的配置文件");
System.out.println(url);
System.out.println(user);
System.out.println(password);
}
private void test2() throws IOException {
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/top/cheungchingyin/demo/db.properties");
Properties properties = new Properties();
properties.load(in);
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
System.out.println("读取src目录下top.cheungchingyin.demo包内的配置文件");
System.out.println(url);
System.out.println(user);
}
private void test3() throws IOException {
InputStream in = this.getServletContext().getResourceAsStream("/db.properties");
Properties properties = new Properties();
properties.load(in);
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
System.out.println("读取webRoot目录下的配置文件");
System.out.println(url);
System.out.println(user);
}
//test4为错误示范
private void test4() throws IOException {
FileInputStream in = new FileInputStream("classes/db.properties");
Properties properties = new Properties();
properties.load(in);
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
System.out.println("使用传统方法读取配置文件(错误示范)");
System.out.println(url);
System.out.println(user);
}
private void test5() throws IOException {
String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");//返回一个当前服务器的绝对地址
FileInputStream in = new FileInputStream(path);
Properties properties = new Properties();
properties.load(in);
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
System.out.println("使用传统方法读取配置文件(正确示范)");
System.out.println(url);
System.out.println(user);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
所以所有配置文件的相对路径都需要围绕着项目在webapps下的项目名称文件夹(在这个例子就是Day05文件夹)为起点开始写。
还有在代码中的test4()方法是一个错误例子,ServletContext对象是掌管着整个web项目的资源,这句代码:
InputStream in = this.getServletContext().getResourceAsStream("/db.properties");
是使用ServletContext对象访问web项目来获取目标资源文件的资源流。
而方法test4()中直接使用这个语句:
FileInputStream in = new FileInputStream("classes/db.properties");
并没有通过ServletContext对象来获得资源,即意味着通过Java虚拟机来获取资源,可是Java虚拟机中并没有这些资源文件,所以最终会Error500说找不到资源。而方法test5()虽然大致上和test4()一样,但是它是通过了ServletContext对象获得了资源的地址,然后再转为该服务器的绝对地址,所以能够使用。
总结
写web项目的时候一定要注意相对路径的位置,获取web项目中的资源时,请务必通过ServletContext对象来获取资源文件。