首页 > 编程笔记 > Java笔记 阅读:48

Servlet ServletConfig和ServletContext接口的用法(附带实例)

通义灵码
本节介绍与 Servlet 相关的两个重要接口,分别为 ServletConfig 接口和 ServletContext 接口。

ServletConfig 封装了当前 Servlet 配置信息,而 ServletContext 代表 Web 应用。

ServletConfig接口

一个 Servlet 对应唯一的 ServletConfig 对象,封装当前 Servlet 配置信息。

ServletConfig 接口包含的方法如下图所示:


图 1 ServletConfig接口包含的方法

ServletConfig 对象由 Servlet 容器(如 Tomcat)创建,并传入生命周期方法 init(ServletConfig config) 中,然后便可以直接获取使用。

值得注意的是,当前 Web 应用的 ServletContext 对象也封装到了 ServletConfig 对象中,使 ServletConfig 对象成为获取 ServletContext对象的一座桥梁。另外,通过 ServletConfig 对象还可以获取 Servlet 名称,以及 Servlet 初始化参数等。

下面通过代码分别演示 ServletConfig 对象的功能。

1) 获得 Servlet 的名字,实际上获取的是 web.xml 文件中 <servlet-name> 标签内的值。
  1. @Override
  2. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  3. // 1. 获得 ServletConfig 对象
  4. ServletConfig servletConfig servletConfig = this.getServletConfig();
  5. // 2. 获取 servlet-name 标签内的名字
  6. String servletName = servletConfig.getServletName();
  7. // 3. 输出展示结果
  8. System.out.println("servletName = " + servletName);
  9. }

2) 获得 ServletContext 对象:
  1. @Override
  2. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  3. // 1. 获得 ServletConfig 对象
  4. ServletConfig servletConfig servletConfig = this.getServletConfig();
  5. // 2. 获取 ServletContext 对象
  6. ServletContext servletContext servletContext = servletConfig.getServletContext();
  7. // 3. 输出展示结果
  8. System.out.println("servletContext = " + servletContext);
  9. }

3) 获得当前 Servlet 的初始化参数。在 web.xml 文件中借助 <init-param> 标签配置初始化参数,示例代码如下:
<servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
    <!-- servlet 标签的全类名下可以通过 init-param 标签配置初始化参数,由键和值组成 -->
    <!-- 配置 url 参数 -->
    <init-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/databasename</param-value>
    </init-param>
    <!-- 配置 driverClass 参数 -->
    <init-param>
        <param-name>driverClass</param-name>
        <param-value>com.mysql.jdbc.Driver</param-value>
    </init-param>
</servlet>

值得注意的是,设置初始化参数 <init-param> 标签的位置必须在 <load-on-startup> 标签前面。通过 ServletConfig 对象的 getInitParameter() 方法,来获取初始化参数 url 和 driverClass 对应的值,示例代码如下:
  1. @Override
  2. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  3. // 1. 获得 ServletConfig 对象
  4. ServletConfig servletConfig servletConfig = this.getServletConfig();
  5. // 2. 根据初始化参数的 key 值获取 value 值
  6. String url = servletConfig.getInitParameter("url");
  7. String driverClass = servletConfig.getInitParameter("driverClass");
  8. // 3. 展示结果
  9. System.out.println("url = " + url);
  10. System.out.println("driverClass = " + driverClass);
  11. // 4. 获取所有初始化参数的 key 值
  12. Enumeration<String> names = servletConfig.getInitParameterNames();
  13. // 循环展示结果
  14. while (names.hasMoreElements()) {
  15. String name = names.nextElement();
  16. System.out.println("name = " + name);
  17. }
  18. }

ServletContext接口

Web 容器在启动时,会为每个 Web 应用程序创建一个唯一对应的 ServletContext 对象,意思是 Servlet 上下文,代表当前 Web 应用。

一个 Web 应用程序中的所有 Servlet 都共享同一个 ServletContext 对象,也因此 ServletContext 对象被称为 Application 对象(Web 应用程序对象)。

ServletContext 对象由 Servlet 容器在项目启动时创建,在项目卸载时销毁。它可以通过 ServletConfig 对象的 getServletContext() 方法获取,也可以通过 service() 方法的参数 ServletRequest 对象获取。

ServletContext 接口包含的方法如下图所示:


图 2 ServletContext接口包含的方法

ServletContext 对象的获取方式包含四种,分别是通过 ServletConfig 对象、当前 Servlet 对象、根据 Session,以及 HttpServletRequest 对象获取,示例代码如下:
  1. @Override
  2. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  3. // 1. 获得 ServletContext 对象
  4. // 1.1 根据 ServletConfig 获得
  5. ServletContext servletContext01 = this.getServletConfig().getServletContext();
  6. // 1.2 根据当前 Servlet 对象获得
  7. ServletContext servletContext02 = this.getServletContext();
  8. // 1.3 根据 request 对象获得
  9. ServletContext servletContext03 = request.getServletContext();
  10. // 1.4 根据 session 对象获取
  11. ServletContext servletContext04 = request.getSession().getServletContext();
  12. }
需要注意的是,不管通过哪种方式获取的都是同一个 ServletContext 对象,因为一个 Web 应用只有一个 ServletContext 对象。

下面通过代码来演示 ServletContext 对象的常用功能。

1) 获取项目的上下文路径,示例代码如下:
  1. @Override
  2. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  3. //1. 获得 ServletContext 对象
  4. ServletContext servletContext = this.getServletContext();
  5. //2. 获得上下文路径
  6. String contextPath = servletContext.getContextPath();
  7. //3. 展示结果
  8. System.out.println("contextPath = " + contextPath);
  9. }
上下文路径即部署在服务器端上的项目名,可以手动设置该值,如下图所示,单击“Edit Configurations”。


图 3 单击“Edit Configurations”

进入“Run/Debug Configurations”新窗口,选择“Deployment”选项,便可设置“Application context”,对于chapter07_servlet项目的上下文路径默认值为“/chapter07_servlet_war_exploded”,如下图所示。


图 4 手动设置上下文路径

另外,从图 4 中还可以看到“chapter07_servlet:war exploded”WAR包,指的是编译后的项目。对此,我们也可以手动添加或删除。

2) 通过 getRealPath(String path) 方法,获取虚拟路径映射的本地真实路径。虚拟路径是指浏览器访问 Web 应用中某个资源时所使用的路径。本地路径是指资源在文件系统中的实际保存路径。
  1. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. //1. 获得 ServletContext 对象
  3. ServletContext servletContext = this.getServletContext();
  4. //2. 获取 index.html 的本地路径
  5. // index.html 的虚拟路径是 "/index.html", 其中 "/" 表示当前 Web 应用的根目录
  6. String realPath = servletContext.getRealPath("/index.html");
  7. //3. 查看结果
  8. System.out.println("realPath = " + realPath);
  9. }

3) 获取 Web 应用程序的全局初始化参数。首先在 web.xml 文件的根标签下设置 Web 应用初始化参数,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!-- Web 应用初始化参数 -->
    <context-param>
        <param-name>ParamName</param-name>
        <param-value>ParamValue</param-value>
    </context-param>
</web-app>
然后通过 getInitParameter() 方法,根据参数名获取Web应用初始化参数,示例代码如下:
  1. protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. //1. 获得 ServletContext 对象
  3. ServletContext servletContext = this.getServletContext ();
  4. //2. 获取全局初始化参数
  5. String paramValue = servletContext.getInitParameter ("ParamName");
  6. System.out.println ("paramValue=" + paramValue);
  7. //3. 获取全部全局初始化参数的 key 值
  8. Enumeration<String> contextInitParameterNames = servletContext.getInitParameterNames();
  9. while (contextInitParameterNames.hasMoreElements()) {
  10. System.out.println(contextInitParameterNames.nextElement());
  11. }
  12. }

4) ServletContext 对象还可以作为最大的域对象,在整个项目的不同 Web 资源内共享数据。域对象的作用是实现在一定作用域范围内,起到共享数据的目的。

Servlet 包括三类域对象,分别为应用域对象、会话域对象和请求域对象。ServletContext 对象属于应用域对象,请求域对象是 HttpServletRequest,会话域对象是 HttpSession。

ServletContext 对象作为域对象共享数据所涉及的方法,如下图所示。


图 5 ServletContext对象作为域对象共享数据的相关方法

其中,setAttribute(key, value) 方法为 ServletContext 对象设置属性,该属性可以在任意位置取出并使用。getAttribute(key) 方法根据 key 值获取对应的属性值。removeAttribute(key) 方法根据 key 值移除该属性。

下面通过创建三个 Servlet,分别实现设置共享数据、获取共享数据,以及移除共享数据操作,来演示 ServletContext 应用域对象在不同 Servlet 间传递数据。

创建 SetMsgServlet 实现在 ServletContext 应用域对象中设置属性,示例代码如下:
  1. package com.atguigu.servlet;
  2. //省略 import 语句
  3.  
  4. @WebServlet("/setMsg")
  5. public class SetMsgServlet extends HttpServlet {
  6. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  7. this.doGet(request, response);
  8. }
  9.  
  10. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  11. System.out.println("访问到 SetMsgServlet 的 doGet 方法...");
  12. //向应用域中设置共享数据
  13. //1.获取 ServletContext 应用域对象
  14. ServletContext servletContext = this.getServletContext();
  15. //2.设置共享数据
  16. servletContext.setAttribute("servletContextKey", "servletContextValue");
  17. }
  18. }

创建 GetMsgServlet 实现从 ServletContext 应用域对象中通过属性名获取属性,示例代码如下:
  1. package com.atguigu.servlet;
  2.  
  3. @WebServlet("/getMsg")
  4. public class GetMsgServlet extends HttpServlet {
  5. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  6. this.doGet(request, response);
  7. }
  8.  
  9. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  10. System.out.println("访问到 GetMsgServlet 的 doGet 方法...");
  11. //1.获取 ServletContext 应用域对象
  12. ServletContext servletContext = this.getServletContext();
  13. //2.获取共享数据
  14. Object servletContextKey = servletContext.getAttribute("servletContextKey");
  15. System.out.println("servletContextKey = " + servletContextKey);
  16. }
  17. }

创建 RemoveMsgServlet 实现从 ServletContext 应用域对象中通过属性名移除属性,示例代码如下:
  1. package com.atguigu.servlet;
  2. //省略导包代码
  3.  
  4. @WebServlet("/removeMsg")
  5. public class RemoveMsgServlet extends HttpServlet {
  6. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  7. this.doGet(request, response);
  8. }
  9.  
  10. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  11. System.out.println("访问到 RemoveMsgServlet 的 doGet 方法...");
  12. //1.获取 ServletContext 应用域对象
  13. ServletContext servletContext = this.getServletContext();
  14. //2.移除共享数据
  15. servletContext.removeAttribute("servletContextKey");
  16. }
  17. }
在 index.html 中编写如下代码,单击超链接访问其对应的 Servlet:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>首页</title>
  6. </head>
  7. <body>
  8. <!--测试应用域对象共享数据-->
  9. <a href="setMsg">单击访问设置共享数据的Servlet</a><br/>
  10. <a href="getMsg">单击访问获取共享数据的Servlet</a><br/>
  11. <a href="removeMsg">单击访问移除共享数据的Servlet</a><br/>
  12. </body>
  13. </html>
启动项目测试应用域对象共享数据的首页面如下图所示:


图 6 测试应用域对象共享数据的首页面

单击“单击访问设置共享数据的Servlet”,然后返回首页再次单击“单击访问获取共享数据的Servlet”,查看控制台,如下图所示。


图 7 获取共享数据后查看控制台

可以看出,首先访问 SetMsgServlet 类向 ServletContext 应用域中设置属性,并且在 GetMsgServlet 类中成功通过该域对象获取其属性值,实现了 SetMsgServlet 和 GetMsgServlet 之间的数据传递。

如果没有提前在 SetMsgServlet 类中设置数据,就直接获取 ServletContext 应用域中数据的话,肯定是获取不到的。例如,直接单击“单击访问获取共享数据的Servlet”,然后查看控制台,如下图所示。


图 8 未设置共享数据直接获取的结果

从图 8 中可知,获取的结果为“null”,表示该值不存在,获取失败。

最后,使用完数据后,为了节省空间资源,我们还可以手动从 ServletContext 应用域中移除该值。

单击移除原来设置的数据后,再次单击“单击访问获取共享数据的Servlet”,并查看控制台,如下图所示。


图 9 移除共享数据

从图中可知,在移除数据后,再次获取数据的结果为“null”,表示原来的数据已经不存在了。

相关文章