ServletContext对象
1. 概念:代表整个web应用,可以和程序的容器(服务器)来通信
特点:
- 产生:部署了Web的服务器一启动,ServletContext对象就会创建,服务器不关闭,就会一直存在。
- 销毁:关闭服务器或者是从web服务器上卸载该程序的时候,该对象销毁。
功能:ServletContext对象保存着 所有用户所有请求的数据,所以可以从当前启动的Web服务器项目中Servlet类中拿去任何用户的请求数据。
2. 获取
- 通过request对象获取
request.getServletContext(); - 通过HttpServlet获取
this.getServletContext();
为什么可以通过this来调用getServletContext方法获取ServletContext对象
- GenericServlet抽象类实现了Servlet
- HttpServlet继承了GenericServlet
- 一个类要想成为Servlet类要先继承HttpServlet或者实现servlet类。
- GenericServlet抽象类中有getServletContext方法,方法体如下图:
- 总结:HttpServlet继承了GenericServlet,servlet实现类又继承了HttpServlet,所以继承了方法,所以可以直接通过this来调用。
3. 功能
1. 获取MIME类型:
1.1 MIME类型的具体用途:
- 当我们打开一个照片的时候,我们要用照片相对应的打开器打开
- 我我们打开一个视频的时候,我们要用视频相对应的播放器打开
总结:所以MIME类型就是在服务端发数据到客户端(前端页面)的时候,告诉客户端,我发给你的数据是什么格式的,你需要用该格式相对应的应用打开。
1.2 MIME类型的简单介绍和获取:
-
MIME类型:在互联网通信过程中定义的一种文件数据类型
- 格式: 大类型/小类型 text/html image/jpeg
-
获取:String getMimeType(String file)
2. 域对象:共享数据
- setAttribute(String name,Object value)
- getAttribute(String name)
- removeAttribute(String name)
- ServletContext对象范围:所有用户所有请求的数据
3. 获取文件的真实(服务器)路径
- 方法:String getRealPath(String path)
各种路径下的访问资源String b = context.getRealPath("/b.txt");//web目录下资源访问 String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问 String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
客户端请求资源,是向服务器上部署的Web项目发送的请求
- IDEA中开发的Web项目,部署到Tomcat服务器然后发布,
- 在IDEA工作目录下会有一个Web项目,部署到Tomcat服务器上后,
- Tomcat服务器也会有一个相同的Web项目,
- 所以客户端(前端页面)请求后端资源(servlet资源)的时候,请求的是Tomcat服务器上部署的项目
怎样查找Web项目部署的真实路径?(以Tomcat服务器为例)
- 在Tomcat服务器启动后,在server菜单栏下,有一个Using CATALINA_BASE
- Using CATALINA_BASE后的路径中有一个conf配置目录,conf目录下有个Catalina目录
- Catalina目录中可以找到一个.XML的文件,打开文件找到docBase属性,docBase的属性值就是Web项目部署的真实路径。
- 在Web部署的真实路径下会有一个WEB-INF目录,WEB-INF目录下的classes目录中存放着所有的java类资源,也就是src下的资源。
4.案例
文件下载需求:
- 页面显示超链接
- 点击超链接后弹出下载提示框
- 完成图片文件下载
分析:
- 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框。不满足需求
- 任何资源都必须弹出下载提示框
- 使用响应头设置资源的打开方式:
- content-disposition:attachment;filename=文件名.xxx
步骤:
- 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
- 定义Servlet
- 获取文件名称
- 使用字节输入流加载文件进内存
- 指定response的响应头: content-disposition:attachment;filename=xxx
- 将数据写出到response输出流
问题:
- 中文文件问题
* 解决思路:- 获取客户端使用的浏览器版本信息
- 根据不同的版本信息,设置filename的编码方式不同
代码演示:
前端代码:
后端代码:
@WebServlet("/downServlet")
public class DownServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取filename属性的属性值
String filename = request.getParameter("filename");
//获取servletContext对象
ServletContext servletContext = this.getServletContext();
//获取Tomcat服务器中部署的Web项目下img目录中的文件真实路径。
String realPath = servletContext.getRealPath("/img/"+filename);
//获取字符输入流,将真实文件路径作为参数传入,写入到内存。
FileInputStream fileInputStream = new FileInputStream(realPath);
//通过getParameter获取属性值,值有后缀名,传入得到的属性值,根据后缀得到mimeType类型
String mimeType = servletContext.getMimeType(filename);
//Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
response.setHeader("content-type",mimeType);
//user-agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
String agent = request.getHeader("user-agent");
//使用工具类方法编码文件名即可
filename = DownLoadUtils.getFileName(agent, filename);
//设置超链接以什么方式来打开文件,attachment表示以附件的形式
response.setHeader("content-disposition", "attachment;filename=" + filename);
//通过response来获取输出流,获取的输出流在请求结束后会自动销毁,所以不用释放。
//获取输出流,将输入流的数据写入到输出流中
ServletOutputStream outputStream = response.getOutputStream();
byte[] bytes = new byte[2048];
int length = 0;
while ( (length = fileInputStream.read(bytes)) != -1){
outputStream.write(bytes,0,length);
}
fileInputStream.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
用到的DownLoadUtils 工具类
作用:将浏览器的版本型号和文件传入,通过浏览器的版本型号来获取指定的编码方式,并将文件重新编码返回。
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}