ServletContext和ServletConfig类似,也可以为Servlet提供一些初始配置参数,ServletConfig
是为每一个Servlet提供独立的初始配置参数;而 ServletContext
是为所有的Servlet提供公共的配置参数。
在内存上,ServletConfig
是多例的,即会产生很多config对象;而 ServletContext
是单例的,整个app中,只会出现一个 ServletContext对象
。
文章目录
一、概念
- ServletContext对象有称呼为上下文对象,或者叫应用域对象(后面统一讲解域对象)
- 容器会为每个app创建一个独立的唯一的ServletContext对象
- ServletContext对象为所有的Servlet所共享
- ServletContext可以为所有的Servlet提供初始配置参数
二、代码示例
1)配置ServletContext参数
<?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">
<!--
1、PS:这个是和servlet同级的,并不是写在某个Servlet里面的
2、<context-param> 会被Tomcat读取,由Tomcat给我们创建一个ServletContext对象
-->
<context-param>
<param-name>paramA</param-name>
<param-value>valueA</param-value>
</context-param>
<context-param>
<param-name>paramB</param-name>
<param-value>valueB</param-value>
</context-param>
</web-app>
2)在Servlet中获取ServletContext并获取参数
package com.atguigu.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;
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ServletContext对象一共有三种获取方法,这三种方法获取到的都是同一个ServletContext对象
// getServletContext()是从GenericServlet里面继承来的
ServletContext servletContext1 = getServletContext();
ServletContext servletContext2 = getServletConfig().getServletContext();
ServletContext servletContext2 = resp.getServletContext();
// 从ServletContext中获取为所有的Servlet准备的参数
String valueA = servletContext.getInitParameter("paramA");
System.out.println("paramA:"+valueA);
// 获取所有参数名
Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
// 迭代并获取参数名
while (initParameterNames.hasMoreElements()) {
String paramaterName = initParameterNames.nextElement();
System.out.println(paramaterName+":"+servletContext.getInitParameter(paramaterName));
}
}
}
三、获取资源的真实路径
目的:向upload目录中写入一个文件
我们可以使用IO流,但重点是,这个磁盘文件的地址怎么写才能让这个IO流正确的指向 a.txt
。
![image-20240728165625126](https://img-blog.csdnimg.cn/img_convert/3242e603ed06955ce67fb647ff92af06.png)
首先我们要明确,我们要找的 a.txt
绝对不是上图框起来的文件,因为我们项目叫工程,工程经过构建之后,out/artifact
中才是我们要部署的app,也就是说我们要找的 a.txt
是 out/artifact/部署包名
下的 upload/a.txt
。
我们的目标是需要获取项目中某个静态资源的路径,不是工程目录中的路径,而是部署目录中的路径;我们如果直接拷贝其在我们电脑中的完整路径的话其实是有问题的,因为如果该项目以后部署到公司服务器上的话,路径肯定是会发生改变的,所以我们需要使用代码动态获取资源的真实路径. 只要使用了servletContext动态获取资源的真实路径,那么无论项目的部署路径发生什么变化,都会动态获取项目运行时候的实际路径,所以就不会发生由于写死真实路径而导致项目部署位置改变引发的路径错误问题
String realPath = servletContext.getRealPath("资源在web项目目录中的路径");
示例
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
// 获取一个指向项目部署位置下的某个文件/目录的磁盘真实路径的APIservletContext.getRealPath()方法会帮我们去找 资源在web项目目录中的路径 部署完毕后 在磁盘中的具体位置
String path = servletContext.getRealPath("upload");
FileOutputStream fos = new FileOutputStream(path + "/a.txt");
}
四、获取项目部署的上下文路径
项目的访问路径(默认是项目的部署名称),也叫项目的上下文路径,在部署进入tomcat时所使用的路径,该路径是可能发生变化的,通过该API动态获取项目真实的上下文路径,可以帮助我们解决一些后端页面渲染技术或者请求转发和响应重定向中的路径问题。
后续我们会学习在项目中使用相对和绝对路径去找目标资源,如果使用绝对路基去找一些目标资源的时候,往往要带上上下文路径的,而上下文路径又是容易变化的。
String contextPath = servletContext.getContextPath(); // /d03
如果传递了查询参数,?key=value
,那么contextPath获取出来的路径还是 /d03
五、域对象的相关API
-
域对象: 一些用于存储数据和传递数据的对象,传递数据不同的范围,我们称之为不同的域,不同的域对象代表不同的域,共享数据的范围也不同。
-
域表示的就是不同的范围和区域,每一个范围和每一个区域都可以用一个对象来代表,所以我们管这个代表不同区域、不同数据存储的区域称之为域对象。
-
ServletContext代表应用,所以ServletContext域也叫作应用域,是webapp中最大的域,可以在本应用内实现数据的共享和传递
因此很多程序员喜欢将拿到的
ServletContext对象
取名为application
,即ServletContext application = getServletContext();
-
webapp中的三大域对象,分别是应用域、会话域、请求域
-
后续我们会将三大域对象统一进行讲解和演示,三大域对象都具有的API如下
API | 功能解释 |
---|---|
void setAttribute(String key,Object value); | 向域中存储/修改数据 |
Object getAttribute(String key); | 从域对象中获取数据,由于这个方法不知道你 需要往里面放的数据是什么类型的,因此这里就是返回Object 根据程序员的自己判断,可以将结果进行强转 |
void removeAttribute(String key); | 移除域中的数据 |
示例
// 作为域对象,一定会有的API
void setAttribute(String key, Object value); // 向域中存储/修改数据
servletContext1.setAttribute("ka", "va");
servletContext1.setAttribute("ka", "vaa");
Object getAttribute(String key); // 获取域中的数据
void removeAttribute(String key); // 移除域中的数据