4.5.3 访问资源文件
ServletContext接口定义了三个方法来访问当前Web应用程序的资源文件,这三个方法如下:
l getResourcePaths方法
该方法返回指定Web应用程序目录中的所有子目录和文件,这些返回的目录文件不包括嵌套目录和文件。这些返回的子目录和文件都封装在该方法返回的一个Set对象中。getResourcePaths方法的定义如下:
public Set getResourcePaths(String path);
其中path参数表示Web应用程序中的目录,必须以斜杠(/)开头,表示Web应用程序的根目录。如要得到WEB-INF目录中的所有目录和文件,可以使用如下的代码:
Set paths = getServletContext().getResourcePaths("/WEB-INF");
2 getResource方法
该方法返回指定Web应用程序中某个资源的URL对象,getResource方法的定义如下:
public URL getResource(String path) throws MalformedURLException;
其中path表示资源的路径,必须以斜杠(/)开头,表示Web应用程序的根目录。如要得到封装web.xml文件路径的URL对象,可以使有下面的代码:
URL url = getServletContext().getResource("/WEB-INF/web.xml");
3 getResourceAsStream方法
该方法返回某个资源的InputStream对象,getResourceAsStream方法实际上打开的是getResource方法返回的URL所指的资源文件。该方法的定义如下:
public InputStream getResourceAsStream(String path);
其中path参数的含义和getResource方法中的path参数相同。
除了使用ServletContext定义的方法来访问Web应用程序中的资源外,还可以使用如下的两种方法来访问资源文件:
1. 使用FileInputStream来访问资源文件
使用这种方法非常直接,但要通过ServletContext接口的getRealPath方法获得当前Web应用程序的本地目录。如打开web.xml文件的代码如下:
String resourceFileName = getServletContext().getRealPath("/WEB-INF/web.xml");
FileInputStream fis = new FileInputStream(resourceFileName);
要注意的是,FileInputStream可以打开以绝对路径指定的资源文件,也可以打开以相对路径指定的资源文件。如果使用相对路径,该相对路径是相对于当前路径而言的。Web服务器的当前路径可以使用如下的代码获得:
String path = System.getProperty("user.dir");
假设上面的代码返回的路径是D:\eclipse,如果在该目录下有一个abc子目录,并且在abc子目录中有一个xyz.properties目录,也就是说,xyz.properties文件的绝对路径是D:\eclipse\abc\xyz.properties,那么使用绝对路径和相对路径访问xyz..properties文件的代码如下:
// 使用绝对路径访问xyz.properties文件
FileInputStream fis1 = new FileInputStream("D:\eclipse\abc\xyz.properties");
// 使用相对路径访问xyz.properties文件
FileInputStream fis1 = new FileInputStream("abc\xyz.properties");
2. 使用Class.getResourceAsStream方法访问资源文件
Class的getResourceAsStream方法和ServletContext接口的getResourceAsStream方法虽然方法名相同,但却有一定的差异。
Class的getResourceAsStream方法的定义如下:
public InputStream getResourceAsStream(String name);
其中name表示资源的路径,也是以斜杠(/)开头,但这个斜杠是指WEB-INF\classes目录,而ServletContext接口中定义的getResourceAsStream方法的path参数中的斜杠是指Web应用程序的根目录。这一点在使用时要注意。
假设在WEB-INF\classes\chapter4目录中有一个abc.properties文件,使用Class.getResourceAsStream方法访问该文件的代码如下:
InputStream is = getClass().getResourceAsStream("/chapter4/abc.properties");
一个良好的编程习惯是将动态的或可能变化的信息(如连接数据库的信息、连接网络的信息等)保存在资源文件中,以便更容易修改和维护这些资源。
在下面的示例中演示了如何使用上述的三种方法来访问Web应用程序中的资源文件,并从中读取信息。
例子 : 演示访问Web应用程序资源的三种方法
1. 实例说明
本示例分别使用如下的三种方法来访问database.properties文件:
l ServletContext.getResourceAsStream方法
2 Class.getResourceAsStream方法
3 FileInputStream
database.properties文件中内容如下:
server=localhost
database=mydb
username=root
password=1234
在本例中将访问两个位置中的database.properties,一个位置是WEB-INF目录,另一个是WEB-INF\classes\chapter4目录。
在本例中,还演示了getResource方法和getResourcePaths方法的用法。
2. 编写ResourceServlet类
ResourceServlet类是一个Servlet类,在该类的service方法中通过上述的三种方式读取了database.properties文件中的内容,并输出的客户端浏览器。ResourceServlet类的代码如下:
package chapter4;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Properties;
import java.net.URL;
public class ResourceServlet extends HttpServlet
{
// 从InputStream对象中读取信息,并输出到PrintWriter对象中
private void outProperties(InputStream is, PrintWriter out) throws Exception
{
Properties props = new Properties(); // 建立Properties对象
// 装载InputStream对象,并按着Java属性文件的格式进行分析
props.load(is);
// 输出属性文件中的信息
out.println("server=" + props.getProperty("server") + "<br/>");
out.println("database=" + props.getProperty("database") + "<br/>");
out.println("username=" + props.getProperty("username") + "<br/>");
out.println("password=" + props.getProperty("password") + "<br/>");
}
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
try
{
// 用getResource方法返回WEB-INF目录中database.properties文件的URL对象
URL url = getServletContext().getResource("/WEB-INF/database.properties");
out.println(url.toString());
out.println("<p/><p/>");
// 得到/WEB-INF/database.properties文件的本地目录
String resourceFileName = getServletContext().getRealPath("/WEB-INF/database.properties");
// 使用FileInputStream访问/WEB-INF/database.properties文件
FileInputStream fis = new FileInputStream(resourceFileName);
out.println("使用FileInputStream读取属性文件中的内容<br/>");
outProperties(fis, out);
// 使用ServletContext.getResourceAsStream访问
// /WEB-INF/database.properties文件
InputStream is = getServletContext().getResourceAsStream("/WEB-INF/database.properties");
out.println("<br/>");
out.println("使用ServletContext.getResourceAsStream读取属性" + "文件中的内容<br/>");
outProperties(is, out);
// 使用Class.getResourceAsStream方法访问
// /WEB-INF/classes/chapter4/database.properties文件
is = getClass().getResourceAsStream("/chapter4/database.properties");
out.println("<br/>");
out.println("使用Class.getResourceAsStream读取属性文件中的内容<br/>");
outProperties(is, out);
out.println("<br/>");
out.println("WEB-INF中的子目录和文件列表<br/>");
// 得到/WEB-INF目录中的所有子目录和文件
java.util.Set<String> paths =this.getServletContext().getResourcePaths("/WEB-INF");
// 输出/WEB-INF目录中的子目录和文件
for(String path: paths)
{
out.println(path + "<br/>");
}
}
catch (Exception e)
{
out.println(e.getMessage());
}
}
}
在上面的代码中,使用了ServletContext.getResourceAsStream方法和FileInputStream来访问/WEB-INF/database.properties文件,使用了Class.getResourceAsStream方法来访问/WEB-INF/classes/chapter4/database.properties文件。并通过Properties对象来分析database.properties文件中的内容。该功能是由outProperties方法完成的。
ResourceServlet类的配置代码如下:
<servlet>
<servlet-name>ResourceServlet</servlet-name>
<servlet-class>chapter4.ResourceServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ResourceServlet</servlet-name>
<url-pattern>/ResourceServlet</url-pattern>
</servlet-mapping>
3. 测试ResourceServlet类
在浏览器中输入如下的URL:
http://localhost:8080/demo/ResourceServlet
浏览器中显示的信息如图4.8所示。
图4.8 输出database.properties文件中的内容