ServletContext接口
当Servlet容器启动时,会为每个Web应用创建一个唯一的ServletContext对象代表当前Web应用,该对象不仅封装了当前Web应用的所有信息,而且实现了多个Servlet之间数据的共享。接下来,针对ServletContext接口的不同作用分别进行讲解,具体如下:
1、获取Web应用程序的初始化参数
在web.xml文件中,不仅可以配置Servlet的初始化信息,还可以配置整个Web应用的初始化信息。Web应用初始化参数的配置方式具体如下所示:
<context-param>
<param-name>companyName</param-name>
<param-value>itcast</param-value>
</context-param>
<context-param>
<param-name>address</param-name>
<param-value>beijing</param-value>
</context-param>
在上面的示例中,<context-param>元素位于根元素<web-app>中,它的子元素<param-name>和<param-value>分别用来指定参数的名字和参数值。要想获取这些参数信息,可以使用ServletContext接口,它定义了getInitParameterNames()和getInitParameter(String name)方法分别用来获取参数名和参数值。接下来,通过一个案例来演示如何使用ServletContext接口获取Web应用程序的初始化参数,如例1所示。
例1 TestServlet03.java
1 package cn.itcast.chapter04.servlet;
2 import java.io.*;
3 import java.util.*;
4 import javax.servlet.*;
5 import javax.servlet.http.*;
6 public class TestServlet03 extends HttpServlet {
7 public void doGet(HttpServletRequest request,
HttpServletResponse response)
8 throws ServletException, IOException {
9 response.setContentType("text/html;charset=utf-8");
10 PrintWriter out = response.getWriter();
11 // 得到ServletContext对象
12 ServletContext context = this.getServletContext();
13 // 得到包含所有初始化参数名的Enumeration对象
14 Enumeration<String> paramNames =
context.getInitParameterNames();
15 // 遍历所有的初始化参数名,得到相应的参数值,打印到控制台
16 out.println("all the paramName and paramValue are
following:");
17 // 遍历所有的初始化参数名,得到相应的参数值并打印
18 while (paramNames.hasMoreElements()) {
19 String name = paramNames.nextElement();
20 String value = context.getInitParameter(name);
21 out.println(name + ": " + value);
22 out.println("<br>");
23 }
24 }
25 public void doPost(HttpServletRequest request,
HttpServletResponse response)
26 throws ServletException, IOException {
27 this.doGet(request, response);
28 }
29 }
在例1中,当通过this.getServletContext()方法获取到ServletContext对象后,首先调用getInitParameterNames ()方法,获取到包含所有初始化参数名的Enumeration对象,然后遍历Enumeration对象,根据获取到的参数名,通过getInitParamter(String name)方法得到对应的参数值。
启动Tomcat服务器,在浏览器的地址栏中输入URL地址http:/``/localhost:8080/chapter04/TestServlet03访问TestServlet03,浏览器显示的结果如图1所示。
图1 运行结果
从图1中可以看出,在web.xml文件中配置的信息被读取了出来。由此可见,通过ServletContext对象可以获取到Web应用的初始化参数。
2、实现多个Servlet对象共享数据
由于一个Web应用中的所有Servlet共享同一个ServletContext对象,因此ServletContext对象的域属性可以被该Web应用中的所有Servlet访问。在ServletContext接口中定义了分别用于增加、删除、设置ServletContext域属性的四个方法,如表1所示。
表1 ServletContext接口的方法
方法说明 | 功能描述 |
---|---|
Enumeration getAttributeNames() | 返回一个Enumeration对象,该对象包含了所有存放在ServletContext中的所有域属性名 |
Object getAttibute(String name) | 根据参数指定的属性名返回一个与之匹配的域属性值 |
void removeAttribute(String name) | 根据参数指定的域属性名,从ServletContext中删除匹配的域属性 |
void setAttribute(String name,Object obj) | 设置ServletContext的域属性,其中name是域属性名,obj是域属性值 |
了解了ServletContext接口中操作属性的方法,接下来通过一个案例来学习这些方法的使用,如例2、3所示。
例2 TestServlet04.java
1 package cn.itcast.chapter04.servlet;
2 import java.io.*;
3 import javax.servlet.*;
4 import javax.servlet.http.*;
5 public class TestServlet04 extends HttpServlet {
6 public void doGet(HttpServletRequest request,
HttpServletResponse response)
7 throws ServletException, IOException {
8 ServletContext context = this.getServletContext();
9 // 通过setAttribute()方法设置属性值
10 context.setAttribute("data", "this servlet save data");
11 }
12 public void doPost(HttpServletRequest request,
HttpServletResponse response)
13 throws ServletException, IOException {
14 this.doGet(request, response);
15 }
16 }
例3 TestServlet05.java
1 package cn.itcast.chapter04.servlet;
2 import java.io.*;
3 import javax.servlet.*;
4 import javax.servlet.http.*;
5 public class TestServlet05 extends HttpServlet {
6 public void doGet(HttpServletRequest request,
HttpServletResponse response)
7 throws ServletException, IOException {
8 PrintWriter out = response.getWriter();
9 ServletContext context = this.getServletContext();
10 // 通过getAttribute()方法获取属性值
11 String data = (String) context.getAttribute("data");
12 out.println(data);
13 }
14 public void doPost(HttpServletRequest request,
HttpServletResponse response)
15 throws ServletException, IOException {
16 this.doGet(request, response);
17 }
18 }
在例2中,setAttribute()方法用于设置ServletContext对象的属性值。在例3中,getAttribute()方法用于获取ServletContext对象的属性值。为了验证ServletContext对象是否可以实现多个Servlet数据的共享,启动Tomcat服务器,首先在浏览器的地址栏中输入URL地址http://localhost:8080/chapter04/TestServlet04
访问TestServlet04,将数据存入ServletContext对象,然后在浏览器的地址栏中输入URL地址http://localhost:8080/chapter04/TestServlet05
访问TestServlet05,浏览器显示的结果如图2所示。
图2 运行结果
从图2中可以看出,浏览器显示出了ServletContext对象存储的属性。由此说明,ServletContext对象所存储的数据可以被多个Servlet所共享。
3、读取Web应用下的资源文件
有时候,希望读取Web应用中的一些资源文件,比如配置文件,图片等等。为此,在ServletContext接口中定义了一些读取Web资源的方法,这些方法是依靠Servlet容器来实现的。Servlet容器根据资源文件相对于Web应用的路径,返回关联资源文件的IO流、资源文件在文件系统的绝对路径等。表2列举了ServletContext接口中用于获取资源路径的相关方法,具体如下:
表2 ServletContext接口的常用方法
方法说明 | 功能描述 |
---|---|
Set getResourcePaths(String path) | 返回一个Set集合,集合中包含资源目录中子目录和文件的路径名称。参数path必须以正斜线(/)开始,指定匹配资源的部分路径 |
String getRealPath(String path) | 返回资源文件在服务器文件系统上的真实路径(文件的绝对路径)。参数path代表资源文件的虚拟路径,它应该以正斜线开始(/)开始,“/”表示当前Web应用的根目录,如果Servlet容器不能将虚拟路径转换为文件系统的真实路径,则返回null |
URL getResource(String path) | 返回映射到某个资源文件的URL对象。参数path必须以正斜线(/)开始,“/”表示当前Web应用的根目录 |
InputStream getResourceAsStream(String path) | 返回映射到某个资源文件的InputStream输入流对象。参数path传递规则和getResource()方法完全一致 |
了解了ServletContext接口中用于获得Web资源路径的方法,接下来通过一个案例,分步骤演示如何使用ServletContext对象读取资源文件,具体如下:
(1)创建一个资源文件。在Eclipse中右击src目录,选择【New】—>【Other】选项,进入创建文件的界面,如图3所示。
图3 新建文件的界面
点击图3所示的【Next】按钮,进入填写文件名称的界面,如图4所示。
图4 填写文件名称的界面
在图4中,【File name】文本框中的内容为资源文件的名称,在此,我们创建的资源文件名为itcast.properties,并且选择存放的目录为src目录。点击【Finish】按钮,完成配置文件的创建。在创建好的itcast.properties文件中,输入如下所示的配置信息:
Company = itcast
Address = Beijing
需要注意的是,Eclipse中src目录下创建的资源文件在Tomcat服务器启动时会被复制到WEB-INF/classes目录下,如图5所示。
图5 WEB-INF/classes目录
(2)编写读取itcast.properties资源文件的TestServlet06,TestServlet06的实现代码如例4所示。
例4 TestServlet06.java
1 package cn.itcast.chapter04.servlet;
2 import java.io.*;
3 import java.util.Properties;
4 import javax.servlet.*;
5 import javax.servlet.http.*;
6 public class TestServlet06 extends HttpServlet {
7 public void doGet(HttpServletRequest request,
HttpServletResponse response)
8 throws ServletException, IOException {
9 response.setContentType("text/html;charset=utf-8");
10 ServletContext context = this.getServletContext();
11 PrintWriter out = response.getWriter();
12 InputStream in = context
13 .getResourceAsStream("/WEB-
INF/classes/itcast.properties");
14 Properties pros = new Properties();
15 pros.load(in);
16 out.println("Company=" + pros.getProperty("Company") + "
<br>");
17 out.println("Address=" + pros.getProperty("Address") + "
<br>");
18 }
19 public void doPost(HttpServletRequest request,
HttpServletResponse response)
20 throws ServletException, IOException {
21 this.doGet(request, response);
22 }
23 }
在例4中,使用ServletContext的getResourceAsStream(String path)方法获得了关联itcast.properties资源文件的输入流对象,其中的path参数必须以正斜线“/”开始,表示itcast.properties文件相对于Web应用的相对路径。
(3)启动Tomcat服务器,在浏览器的地址栏中输入URL地址http://localhost:8080/chapter04/TestServlet06
访问TestServlet06,浏览器显示的结果如图6所示。
图6 运行结果
从图6中可以看出,itcast.properties资源文件的内容被读取出来了。由此可见,使用ServletContext可以读取到Web应用中的资源文件。
(4)有的时候,我们需要获取的是资源的绝对路径。接下来,对例6进行修改,通过使用getRealPath(String path)方法获取资源文件的绝对路径,修改后的代码如例7所示。
例5 TestServlet06.java
1 package cn.itcast.chapter04.servlet;
2 import java.io.*;
3 import java.util.Properties;
4 import javax.servlet.*;
5 import javax.servlet.http.*;
6 public class TestServlet06 extends HttpServlet {
7 public void doGet(HttpServletRequest request,
HttpServletResponse response)
8 throws ServletException, IOException {
9 PrintWriter out = response.getWriter();
10 ServletContext context = this.getServletContext();
11 String path = context.getRealPath("/WEB- INF/classes/itcast.properties");
12 FileInputStream in = new FileInputStream(path);
13 Properties pros = new Properties();
14 pros.load(in);
15 out.println("Company=" + pros.getProperty("Company") + "
<br>");
16 out.println("Address=" + pros.getProperty("Address") + "
<br>");
17 }
18 public void doPost(HttpServletRequest request,
HttpServletResponse response)
19 throws ServletException, IOException {
20 this.doGet(request, response);
21 }
22 }
在例5中,使用ContextServlet对象的getRealPath(String path)方法获得itcast.properties资源文件的绝对路径path,然后使用这个路径创建关联itcast.properties文件的输入流对象。
(5)启动Tomcat服务器,在浏览器的地址栏中再次输入URL地址http://localhost:8080/chapter04/
TestServlet06访问TestServlet06,同样可以看到图6所显示的内容。