在对两个对象说明之前,我们仍需在 web-all 工程下创建一个 demo





目录
[ServletConfig 的使用](#ServletConfig 的使用)
[ServletContext 的使用](#ServletContext 的使用)
[获取参数的 API](#获取参数的 API)
[ServletContext 其他重要的 API](#ServletContext 其他重要的 API)
[域对象的相关 API](#域对象的相关 API)
ServletConfig 的使用
servletConfig 是什么?
为 servlet 提供初始配置参数的一种对象,每个 servlet 都有自己独立唯一的 servletConfig 对象
容器(Tomcat)会为每个 servlet 实例化一个 servletConfig 对象,并且通过 servlet 的生命周期的 init 方法传入给 servlet 作为属性

ServletConfig 是一个接口,定义了如下的 API
java
public interface ServletConfig {
String getServletName();
ServletContext getServletContext();
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();
}

首先为我们的 servlet1 配置 web.xml 如下:
XML
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>com.zzz.servlet.servlet1</servlet-class>
<!-- 配置 servlet 的初始参数 -->
<init-param>
<param-name>keyA</param-name>
<param-value>valueA</param-value>
</init-param>
<init-param>
<param-name>keyB</param-name>
<param-value>valueB</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>/servlet1</url-pattern>
</servlet-mapping>
</web-app>
servlet1 的代码如下:
java
package com.zzz.servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/*
* @author zzr
* @date: 2025/07/05 20:51
* @description: 测试 ServletConfig 和 ServletContext
*/
public class servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = getServletConfig();
// 获取初始配置信息
// 根据参数名获取参数值
String keyA = servletConfig.getInitParameter("keyA");
System.out.println("keyA = " + keyA);
// 获取所有的初始参数的名字
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
// Enumeration 类似于之前的迭代器 Iterator
// hasMoreElements:判断有没有下一个参数,如果有,返回 true,如果没有,返回 false
// nextElement:1. 取出下一个元素 2. 向下移动游标
while (initParameterNames.hasMoreElements()) {
String pname = initParameterNames.nextElement();
System.out.println(pname + " = " + servletConfig.getInitParameter(pname));
}
}
}
运行代码前,还要配置 tomcat:


结果如下,成功打印:

前面我们提到 ServletConfig 对象,是每个 servlet 都有其唯一的一个 ServletConfig 对象,我们可以再创建一个 servlet2 来进行测试:
XML
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<!-- servlet1 的配置 -->
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>com.zzz.servlet.servlet1</servlet-class>
<!-- 配置 servlet 的初始参数 -->
<init-param>
<param-name>keyA</param-name>
<param-value>valueA</param-value>
</init-param>
<init-param>
<param-name>keyB</param-name>
<param-value>valueB</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>/servlet1</url-pattern>
</servlet-mapping>
<!-- servlet2 的配置 -->
<servlet>
<servlet-name>servlet2</servlet-name>
<servlet-class>com.zzz.servlet.servlet2</servlet-class>
<!-- 配置 servlet 的初始参数 -->
<init-param>
<param-name>key2A</param-name>
<param-value>value2A</param-value>
</init-param>
<init-param>
<param-name>key2B</param-name>
<param-value>value2B</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>servlet2</servlet-name>
<url-pattern>/servlet2</url-pattern>
</servlet-mapping>
</web-app>
java
package com.zzz.servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/*
* @author zzr
* @date: 2025/07/05 21:18
* @description:
*/
public class servlet2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = getServletConfig();
String key2A = servletConfig.getInitParameter("key2A");
System.out.println("key2A = " + key2A);
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
while(initParameterNames.hasMoreElements()) {
String pname = initParameterNames.nextElement();
System.out.println(pname + " = " + servletConfig.getInitParameter(pname));
}
}
}


在 @WebServlet 中设置初始参数:
查看类型如下:


注释如下:

ServletContext 的使用
获取参数的 API
ServletContext 是什么?
ServletContext 对象,有时候称为上下文对象,或者叫应用域对象(应用域对象后面会解释)
容器(Tomcat)会为每个 app 创建一个独立的 唯一的 ServletContext 对象
ServletContext 对象为所有的 Servlet 所共享

使用:
先配置 web.xml 如下:
XML
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<servlet>
<servlet-name>servlet3</servlet-name>
<servlet-class>com.zzz.servlet.servlet3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet3</servlet-name>
<url-pattern>/servlet3</url-pattern>
</servlet-mapping>
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
<context-param>
<param-name>username</param-name>
<param-value>zzz</param-value>
</context-param>
</web-app>
再配置 servlet3 代码如下:
java
package com.zzz.servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/*
* @author zzr
* @date: 2025/07/05 21:52
* @description: 测试 ServletContext 对象
*/
public class servlet3 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = getServletConfig();
// 获取 ServletContext
// 法 1:
//ServletContext servletContext = servletConfig.getServletContext();
// 法 2:
//ServletContext servletContext = req.getServletContext();
// 法 3:
ServletContext servletContext = getServletContext();
String encoding = servletContext.getInitParameter("encoding");
System.out.println("encoding = " + encoding);
Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
String pname = initParameterNames.nextElement();
System.out.println(pname + " = " + servletContext.getInitParameter(pname));
}
}
}
运行结果如下:

就算再部署一个 servlet4,其打印的结果也是如上图相同~
ServletContext 其他重要的 API
获取资源的磁盘路径
例如,我们的项目中有一个静态资源的路径:

如果要获取到这个静态资源的路径,应该是这个文件的部署目录中的路径,即上面黄色 out 目录中的位置,而不是下面白色背景中,工程目录中的路径。

这个 path 中的路径,如果换一台电脑,换一个环境,肯定就不适用了!
总结:如果我们的目标是需要获取项目中的某个静态资源的路径,此时我们需要的路径,并不是工程目录中的路径,而是,部署目录中的路径。但我们如果像上图一样,直接拷贝我们电脑中的完整路径,其实是不对的。如果项目部署到公司的服务器,其路径肯定会发生变化。
所以,我们需要使用代码,来动态的,获取资源的真实路径。
可以使用 servletContext 来动态获取资源的真实路径,实现,无论项目的部署路径发生什么变化,都可以动态的,获取项目运行时候的时机磁盘路径~
java
String realPath = servletContext.getRealPath("资源在 web 目录中的路径");
java
package com.zzz.servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* @author zzr
* @date: 2025/07/06 11:24
* @description: 测试 ServletContext 的其他 API
*/
@WebServlet("/servlet5")
public class servlet5 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
// 获取一个指向项目部署位置下的某个文件目录的磁盘真实路径的 API
String path = servletContext.getRealPath("upload");
System.out.println(path + "\\test.html");
}
}
获取项目的上下文路径
项目的上下文路径,即项目的访问路径,也叫项目的上下文路径。我们部署的工程进入 tomcat 时所用的路径。前面一直也提到过,该路径是可能发生变化的,

可以在 Edit Configuration 中随便修改:

我们可以通过 ServletContext 中的一个 API 来动态的获取,项目中的真实的上下文路径,帮助我们解决一些后端路径问题~
java
package com.zzz.servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* @author zzr
* @date: 2025/07/06 11:24
* @description: 测试 ServletContext 的其他 API
*/
@WebServlet("/servlet5")
public class servlet5 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
// 获取一个指向项目部署位置下的某个文件目录的磁盘真实路径的 API
String path = servletContext.getRealPath("upload");
System.out.println(path + "\\test.html");
// 项目部署的上下文路径 / 项目的访问路径
String contextPath = servletContext.getContextPath();
System.out.println(contextPath);
}
}

域对象的相关 API
域对象:一些用于在一些特定的范围内,存储数据和传递数据,的对象,不同的范围,称为不同的"域",不同的域对象,代表不同的域,共享的范围也不同。
ServletContext 代表应用,所以 ServletContext 域也叫做应用域,是 webapp 中最大的域,可以在本应用中实现数据的共享和传递
webapp 中的三大域对象:应用域,会话域,请求域(后续详见~)
三大域对象都有如下的 API:

理解域:

如上图,有两座(或更多座大厦),在大厦中有不同的公司办公。
黄色公司中的快递柜子,就只能黄色公司的职员使用。
但如果大厦中的两家公司,要有东西来回交换,就可以 A 公司,把东西放在绿色的快递驿站,B 公司再去那个快递驿站中取即可~
但两座不同大厦中的两家公司,要有东西来回交换,就可以 C 公司,把东西放在红色的菜鸟驿站,D 公司再取那个菜鸟驿站中取即可~
上面的公司,大厦,不同大厦,就是不同的域~
回到我们的 webapp 中,如果此时 servlet1 想给 servlet2 中传递一个数据,该如何实现呢?
servlet 的对象,都是由 tomcat 来为我们创建的,我们无法像之前那样再在 servlet2 中创建一个 servlet1 对象,这时候就可以用域对象了~
java
package com.zzz.servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* @author zzr
* @date: 2025/07/06 11:55
* @description: 域对象测试
*/
@WebServlet("/servlet6")
public class servlet6 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
// 向域中存储/修改数据
servletContext.setAttribute("kA","kB");
}
}

getAttribute 的方法,返回值是一个 Object,因为无法知道我们放的数据的类型,所以直接用 Object 来接收。
这里我们知道数据类型是 String,可以安全的强转
java
package com.zzz.servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* @author zzr
* @date: 2025/07/06 11:55
* @description: 域对象测试
*/
@WebServlet("/servlet7")
public class servlet7 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
// 从域对象中读取数据
String kA = (String) servletContext.getAttribute("kA");
System.out.println(kA);
}
}
测试:要先访问 servlet6 将数据存进去,再访问 servlet7 来读取数据~
补充:
因为 ServletContext 是代表域对象,所以,一般习惯于,将 ServletContext 对象命名为 application,即:
java
ServletContext application = getServletContext();