14. Servlet入门 - ServletContext类作为全局域对象共享数据使用

2022-01-14 17:45:50 浏览数 (1)

14. Servlet入门 - ServletContext类作为全局域对象共享数据使用

ServletContext

image-20201112001610037

什么是 ServletContext?

2、一个 web 工程,只有一个 ServletContext 对象实例。

3、ServletContext 对象是一个域对象。

4、ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。

什么是域对象?

域对象,是可以像 Map 一样存取数据的对象,叫域对象。

这里的域指的是存取数据的操作范围,整个 web 工程。

代码语言:javascript复制
        存数据                 取数据                删除数据 
Map      put()                get()                 remove() 
域对象 setAttribute()          getAttribute()       removeAttribute();

ServletContext 类的作用

1、获取 web.xml 中配置的上下文参数 context-param

2、获取当前的工程路径,格式: /工程路径

3、获取工程部署后在服务器硬盘上的绝对路径

4、像 Map 一样存取数据

5、获得文件mini类型(文件下载)

6、获取web资源路径 ,可以将Web资源转换成字节输入流(掌握)

获取 web.xml 上下文、工程路径、部署路径
1.首先创建一个新的Servlet用来测试

image-20201112081828738

代码语言:javascript复制
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author Aron.li
 * @date 2020/11/12 8:18
 */
public class ContextServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}
2.配置该Servlet 的 XML 以及 上下文参数 context-param

image-20201112082219781

代码语言:javascript复制
<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
    <param-name>username</param-name>
    <param-value>root</param-value>
</context-param>

<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
    <param-name>password</param-name>
    <param-value>123abc</param-value>
</context-param>

<!--  ContextServlet  -->
<servlet>
    <servlet-name>ContextServlet</servlet-name>
    <servlet-class>com.test01.ContextServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ContextServlet</servlet-name>
    <url-pattern>/context</url-pattern>
</servlet-mapping>
3.获取 web.xml 中配置的上下文参数 context-param

image-20201112082706231

代码语言:javascript复制
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("ContextServlet的Get方法:");
    //1. 获取 web.xml 中配置的上下文参数 context-param
    ServletContext context = getServletContext(); // 获取ServletContext对象
    // 获取上下文username参数
    String username = context.getInitParameter("username");
    System.out.println("context-param参数username的值是:"   username);
    // 获取上下文password参数
    String password = context.getInitParameter("password");
    System.out.println("context-param参数password的值是:"   password);
}
4.获取当前的工程路径,格式: /工程路径

image-20201112083059383

代码语言:javascript复制
// 获取ServletContext对象
ServletContext context = getServletContext(); 
//2.获取当前的工程路径,格式: /工程路径
System.out.println("当前工程路径:"   context.getContextPath());
5. 获取工程部署后在服务器硬盘上的绝对路径
5.1 获取工程的根路径部署地址

image-20201112084010482

代码语言:javascript复制
//3. 获取工程部署后在服务器硬盘上的绝对路径
/**
 *  / 斜杠被服务器解析地址为:http://ip:port/工程名/  映射到IDEA代码的web目录<br/>
 */
System.out.println("工程部署的路径是:"   context.getRealPath("/"));

我们可以看到打印硬盘部署路径,可以打开该路径看看,如下:

image-20201112084103281

5.2 除了获取工程的根路径,还可以任意拼接其他路径,就算该路径在硬盘中并不存在

image-20201112084432449

代码语言:javascript复制
//  除了获取工程的根路径,还可以任意拼接其他路径,就算该路径在硬盘中并不存在
System.out.println("工程下css目录的绝对路径是:"   context.getRealPath("/css"));
System.out.println("工程下imgs目录1.jpg的绝对路径是:"   context.getRealPath("/imgs/1.jpg"));
6.演示代码
ServletContext 演示代码:
代码语言:javascript复制
package com.test01;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author Aron.li
 * @date 2020/11/12 8:18
 */
public class ContextServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ContextServlet的Get方法:");
        //1. 获取 web.xml 中配置的上下文参数 context-param
        ServletContext context = getServletContext(); // 获取ServletContext对象
        // 获取上下文username参数
        String username = context.getInitParameter("username");
        System.out.println("context-param参数username的值是:"   username);
        // 获取上下文password参数
        String password = context.getInitParameter("password");
        System.out.println("context-param参数password的值是:"   password);

        //2.获取当前的工程路径,格式: /工程路径
        System.out.println("当前工程路径:"   context.getContextPath());

        //3. 获取工程部署后在服务器硬盘上的绝对路径
        /**
         *  / 斜杠被服务器解析地址为:http://ip:port/工程名/  映射到IDEA代码的web目录<br/>
         */
        System.out.println("工程部署的路径是:"   context.getRealPath("/"));

        //  除了获取工程的根路径,还可以任意拼接其他路径,就算该路径在硬盘中并不存在
        System.out.println("工程下css目录的绝对路径是:"   context.getRealPath("/css"));
        System.out.println("工程下imgs目录1.jpg的绝对路径是:"   context.getRealPath("/imgs/1.jpg"));
    }
}
web.xml 中的配置
代码语言:javascript复制
<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
    <param-name>username</param-name>
    <param-value>root</param-value>
</context-param>

<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
    <param-name>password</param-name>
    <param-value>123abc</param-value>
</context-param>

<!--  ContextServlet  -->
<servlet>
    <servlet-name>ContextServlet</servlet-name>
    <servlet-class>com.test01.ContextServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ContextServlet</servlet-name>
    <url-pattern>/context</url-pattern>
</servlet-mapping>
ServletContext 像 Map 一样存取数据
1.创建一个 ContextServlet1 来进行演示

image-20201112234407498

代码语言:javascript复制
public class ContextServlet1 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

}

配置 web.xml 如下:

image-20201112234436149

代码语言:javascript复制
<!--  ContextServlet1  -->
<servlet>
    <servlet-name>ContextServlet1</servlet-name>
    <servlet-class>com.test01.ContextServlet1</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ContextServlet1</servlet-name>
    <url-pattern>/context1</url-pattern>
</servlet-mapping>
2.在 ContextServlet1 存储数据 以及 读取数据

image-20201112234728361

代码语言:javascript复制
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 获取ServletContext对象
    ServletContext context = getServletContext();
    //在 ContextServlet1 存储数据 以及 读取数据
    context.setAttribute("key1", "value1"); // 存储数据
    System.out.println("ContextServlet1 读取数据: "   context.getAttribute("key1")); // 读取数据
}
3.启动 tomcat 服务,请求测试如下:

image-20201112235130305

可以看到能够读取数据。另外,context 存储的数据是共享于整个 web 工程的,也就是说其他的 Servlet 程序也是可以读取的。

4.再创建一个 ContextServlet2 ,尝试读取 ContextServlet1 存储的值

image-20201112235422146

代码语言:javascript复制
public class ContextServlet2 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取ServletContext对象
        ServletContext context = getServletContext();
        //在 ContextServlet2 读取数据
        System.out.println("ContextServlet2 读取数据: "   context.getAttribute("key1")); // 读取数据
        System.out.println("ContextServlet2 读取数据: "   context.getAttribute("key1")); // 读取数据
        System.out.println("ContextServlet2 读取数据: "   context.getAttribute("key1")); // 读取数据
    }
}

在 web.xml 配置如下:

image-20201112235448775

代码语言:javascript复制
<!--  ContextServlet2  -->
<servlet>
    <servlet-name>ContextServlet2</servlet-name>
    <servlet-class>com.test01.ContextServlet2</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ContextServlet2</servlet-name>
    <url-pattern>/context2</url-pattern>
</servlet-mapping>
5.重新部署 tomcat 服务,尝试首先请求 ContextServlet2 能否读取到值

image-20201112235608372

也就是说,如果想要读取数据,首先需要设置数据。

6.访问 ContextServlet1 设置数据,然后再 ContextServlet2 读取数据

image-20201112235713767

image-20201112235749863

获得文件mime类型(文件下载)

对于这个用法了解一下就好,下面我们快速用代码示例一下。

获取文件mime类型的方法:

代码语言:javascript复制
getServletContext().getMimeType(String file)
1.读取 a.mp3b.png 的 文件mime类型

image-20201225000808315

不需要实际文件,根据字符串的后缀,可以直接识别对应的类型。测试如下:

image-20201225000930357

代码语言:javascript复制
@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //根据文件名获得文件的mini类型
        //1.获得ServletContext
        //2.调用getMimeType()方法
        String file01 = "a.mp3";
        String file02 = "b.png";
        String mimeType01 = getServletContext().getMimeType(file01);
        String mimeType02 = getServletContext().getMimeType(file02);
        resp.getWriter().print("ServletDemo4... file01 mimetype: "   mimeType01   ", file02 mimetype: "   mimeType02 );
    }
}
获取web资源路径 ,可以将Web资源转换成字节输入流(掌握)

我们在项目工程中获取文件的资源一般操作如下:

API

  • String getRealPath(String path);根据资源名称得到资源的绝对路径.
  • getResourceAsStream(String path) ;返回制定路径文件的流

“注意: filepath:直接从项目的根目录开始写 ”

在web项目中,将文件转换成流,有两种方式

如果文件在resources里面,使用类加载器

代码语言:javascript复制
InputStream is = ServletDemo04.class.getClassLoader().getResourceAsStream("文件路径");

如果文件在web里面,使用ServletContext获取文件的路径后,再将其转为文件输入流。

代码语言:javascript复制
InputStream resourceAsStream = servletContext.getResourceAsStream("1.jpeg");
1.拷贝一张图片在 webapp 目录下,并使用 ServletContext 获取编译后的存储路径

image-20201225083417208

代码语言:javascript复制
@WebServlet("/demo5")
public class ServletDemo5 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 获取 图片 编译后的 存储路径
        ServletContext servletContext = getServletContext();
        String realPath = servletContext.getRealPath("1.jpeg");
        System.out.println(realPath);
    }

}
2.使用文件输入流读取文件内容

image-20201225083629036

代码语言:javascript复制
@WebServlet("/demo5")
public class ServletDemo5 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 获取 图片 编译后的 存储路径
        ServletContext servletContext = getServletContext();
        String realPath = servletContext.getRealPath("1.jpeg");
        System.out.println(realPath);

        // 2. 使用文件输入流读取文件内容
        FileInputStream fileInputStream = new FileInputStream(realPath);
        System.out.println(fileInputStream);
    }

}

可以看到,通过这种方式已经成功获取到了 webapp 目录下的图片资源了。但是还可以直接通过 ServletContext 对象获取文件资源。

3.使用ServletContext可以获取web里面的资源的真实路径

image-20201225084129069

代码语言:javascript复制
@WebServlet("/demo5")
public class ServletDemo5 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 获取 图片 编译后的 存储路径
        ServletContext servletContext = getServletContext();
        String realPath = servletContext.getRealPath("1.jpeg");
        System.out.println(realPath);

        // 2. 使用文件输入流读取文件内容
        FileInputStream fileInputStream = new FileInputStream(realPath);
        System.out.println("fileInputStream: "   fileInputStream);

        // 3. 使用ServletContext可以获取web里面的资源的真实路径
        InputStream resourceAsStream = servletContext.getResourceAsStream("1.jpeg");
        System.out.println("resourceAsStream: "   resourceAsStream);

    }

}

小结

  1. 作为域对象存取数据【共享】
    • setAttribute(String name,Object value) 存
    • getAttribute(String name) 取
    • removeAttribute(String name) 移除
  2. 获得文件的Mime类型
    • getMineType(String fileName);
  3. 获得全局初始化参数
    • 在web.xml配置
    • getInitParameter(String name);
  4. 获得web资源路径【已经在web目录了】
    • getRealPath(String file); 获得文件的绝对路径
    • getReSourceAsStream(String file); 获得文件流

0 人点赞