ServletContext 对象的学习笔记

ServletContext对象概述

ServletContext用来存放全局变量,每个Java虚拟机每个Web项目只有一个ServletContext,这个ServletContext是由Web服务器创建的,来保证它的唯一性。由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象通讯。ServletContext对象通常也被称之为Context域对象。

  • 获取方式

    • 通过request对象获取

      request.getServletContext();
      
    • 通过HttpServlet获取

      this.getServletContext();
      

获取ServletContext对象

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

@WebServlet("/demo01")
public class ServletContextDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 通过 Request 对象获取 ServletContext 对象
        ServletContext requestServletContext = request.getServletContext();
        // 通过 HttpServlet 获取 ServletContext 对象
        ServletContext servletContext = this.getServletContext();
        System.out.println(requestServletContext);
        System.out.println(servletContext);
        System.out.println(requestServletContext == servletContext);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}

启动服务器,浏览器访问:http://localhost:8080/ServletContext_war_exploded/demo01

控制台输出:

org.apache.catalina.core.ApplicationContextFacade@86cb2b8
org.apache.catalina.core.ApplicationContextFacade@86cb2b8
true

ServletContext对象功能

  1. 获取MIME类型

    • MIME类型:在互联网通信过程中定义的一种文件数据类型

      如:大类型/小类型 text/html image/jpeg

    • 获取方法:

      String getMimeType(String file) 
      
  2. 域对象:共享数据

    setAttribute(String name,Object value)
    getAttribute(String name)
    removeAttribute(String name)
    
  3. 获取文件的真实(服务器)路径

    String getRealPath(String path)
    

获取mime 类型

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

@WebServlet("/demo02")
public class ServletContextDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 通过 HttpServlet 获取 ServletContext 对象
        ServletContext servletContext = this.getServletContext();
        // 定义文件名称
        String fileName01 = "a.png";
        String fileName02 = "b.jpeg";
        // 获取 MIME 类型
        String mimeType01 = servletContext.getMimeType(fileName01);
        System.out.println(mimeType01);
        String mimeType02 = servletContext.getMimeType(fileName02);
        System.out.println(mimeType02);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}

启动服务器,浏览器访问:http://localhost:8080/ServletContext_war_exploded/demo02

控制台输出:

image/png
image/jpeg

域对象:共享数据

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

@WebServlet("/demo03")
public class ServletContextDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 通过 HttpServlet 获取 ServletContext 对象
        ServletContext servletContext = this.getServletContext();
        // 设置数据
        servletContext.setAttribute("demo03's data", "我是demo03这里设置的数据!!!");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/demo04")
public class ServletContextDemo04 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 通过 HttpServlet 获取 ServletContext 对象
        ServletContext servletContext = this.getServletContext();
        // 获取demo03中设置的数据
        System.out.println(servletContext.getAttribute("demo03's data"));
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}

启动服务器,浏览器中访问:http://localhost:8080/ServletContext_war_exploded/demo03,目的是,访问demo03,设置数据。

然后,浏览器中访问:http://localhost:8080/ServletContext_war_exploded/demo04。控制台输出:

我是demo03这里设置的数据!!!

获取文件的真实(服务器)路径

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

@WebServlet("/demo05")
public class ServletContextDemo05 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 通过 HttpServlet 获取 ServletContext 对象
        ServletContext servletContext = this.getServletContext();
        // 获取文件的服务器路径
        System.out.println(servletContext.getRealPath("/file01.txt"));
        System.out.println(servletContext.getRealPath("/WEB-INF/file02.txt"));
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}

启动服务器,浏览器中访问:http://localhost:8080/ServletContext_war_exploded/demo05

控制台输出:

/Users/liyihua/IdeaProjects/ServletContext/out/artifacts/ServletContext_war_exploded/file01.txt
/Users/liyihua/IdeaProjects/ServletContext/out/artifacts/ServletContext_war_exploded/WEB-INF/file02.txt

案例

  • 文件下载需求:

    1. 页面显示超链接
    2. 点击超链接后弹出下载提示框
    3. 完成图片文件下载
  • 分析:

    1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框。不满足需求
    2. 任何资源都必须弹出下载提示框
    3. 使用响应头设置资源的打开方式:
      • content-disposition:attachment;filename=xxx
  • 步骤:

    1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
    2. 定义Servlet
      1. 获取文件名称
      2. 使用字节输入流加载文件进内存
      3. 指定response的响应头: content-disposition:attachment;filename=xxx
      4. 将数据写出到response输出流
    • 问题:
      • 中文文件问题
        • 解决思路:
          1. 获取客户端使用的浏览器版本信息
          2. 根据不同的版本信息,设置filename的编码方式不同
  • 实现:

    • java

      import javax.servlet.ServletContext;
      import javax.servlet.ServletException;
      import javax.servlet.ServletOutputStream;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.FileInputStream;
      import java.io.IOException;
      
      @WebServlet("/downloadServlet")
      public class DownloadServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response)
                  throws ServletException, IOException {
              // 获取用户请求参数(文件名称)
              String fileName = request.getParameter("filename");
              // 获取 ServletContext 对象
              ServletContext servletContext = request.getServletContext();
      
              // 根据文件名称,找到服务器中文件的路径
              String filePath = servletContext.getRealPath("/downloadFile/" + fileName);
              // 根据文件名称,获取文件类型
              String mimeType = servletContext.getMimeType(fileName);
      
              // 设置 response 的响应头 —————— 响应头类型:content-type
              response.setHeader("content-type", mimeType);
              // 响应头的打开方式:content-disposition
              response.setHeader("content-disposition", "attachment;filename=" + fileName);
      
              // 使用字节输入流加载文件进内存
              FileInputStream fileInputStream = new FileInputStream(filePath);
              // 将字节输入流的数据写出到输出流中
              ServletOutputStream responseOutputStream = response.getOutputStream();
              byte[] bytes = new byte[1024 * 8];
              int len = 0;
              while ((len = fileInputStream.read(bytes)) != -1) {
                  responseOutputStream.write(bytes, 0, len);
              }
              fileInputStream.close();
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response)
                  throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    • html

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
          <!-- 虚拟路径:/ResponseDownload_war_exploded -->
          <!-- /downloadServlet 为Servlet的访问路径 -->
          <!-- 资源名称:image06.png、view.avi -->
          <a href="/ResponseDownload_war_exploded/downloadServlet?filename=image06.png">下载图片</a>
          <a href="/ResponseDownload_war_exploded/downloadServlet?filename=view.avi">下载视频</a>
      
      </body>
      </html>
      
    • 启动服务器,浏览器中访问:http://localhost:8080/ResponseDownload_war_exploded/download.html

      20200528221013

      点击下载图片,会下载: image06.png

      点击下载视频,会下载:view.avi


参考文献

  1. ServletContext对象详解
Good Good Write Bug, Day Day Up
原文地址:https://www.cnblogs.com/liyihua/p/14477501.html