补充一个服务器端的全局对象ServletContext,不常用,但功能强大。
本文目录
ServletContext对象
1.概念
ServletContext对象代表整个web应用,可以和程序的容器(服务器)来通信。ServletContext全局对象只有唯一一个。
2.获取ServletContext对象
request.getServletContext();
通过request对象获取this.getServletContext();
通过HttpServlet类中的方法获取
例子:
@WebServlet(name = "servletContextDemo1", urlPatterns = "/servletContextDemo1")
public class servletContextDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
ServletContext对象获取方式:
*/
//1. 通过request对象获取
ServletContext servletContext = request.getServletContext();
//2. 通过HttpServlet获取
ServletContext servletContext1 = this.getServletContext();
System.out.println(servletContext);
System.out.println(servletContext1);
//ServletContext全局对象只有唯一一个
System.out.println(servletContext==servletContext1);//true
}
浏览器访问servletContextDemo1
3.ServletContext对象的功能
3.1 获取文件的MIME类型
MIME类型:是在互联网通信过程中定义的一种文件数据类型。
格式: 大类型/小类型。比如,text/html , image/jpeg
获取的方法:
String getMimeType(String file);
参数是文件的名称,返回值是MIME类型字符串形式
例子:
@WebServlet(name = "servletContextDemo2", urlPatterns = "/servletContextDemo2")
public class servletContextDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.通过HttpServlet获取全局对象
ServletContext context = this.getServletContext();
//2.定义文件名称
String fileName = "1.jpg";//该文件的MIME类型:image/jpeg
//3.获取文件的MIME类型
String mimeType = context.getMimeType(fileName);
System.out.println(mimeType);
}
}
浏览器访问servletContextDemo2
3.2 作为域对象:共享数据,范围是全局的
常用的三种方法
void setAttribute(String name,Object value);
以键值对的方式设置数据。name唯一标识,value值可以是任意对象。Object getAttribute(String name);
获取键对应的值void removeAttribute(String name);
删除键对应的键值对数据。
代码实现:servletContextDemo3设置共享数据,servletContextDemo4获取共享数据。
@WebServlet(name = "servletContextDemo3", urlPatterns = "/servletContextDemo3")
public class servletContextDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.通过HttpServlet获取全局对象
ServletContext context = this.getServletContext();
//2.设置共享数据
context.setAttribute("msg","Hello");
}
}
@WebServlet(name = "servletContextDemo4", urlPatterns = "/servletContextDemo4")
public class servletContextDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.通过HttpServlet获取全局对象
ServletContext context = this.getServletContext();
//2.获取共享数据
Object msg = context.getAttribute("msg");
System.out.println(msg);
}
}
浏览器访问servletContextDemo3,再访问servletContextDemo4,控制台打印:
3.3 获取文件的真实(服务器)路径
ServletContext对象可以获取全局范围下所有文件的真实路径。
- web目录下文件资源访问路径
- WEB-INF目录下文件的资源访问路径
- src目录下文件的资源访问路径
目录结构:
代码演示
@WebServlet(name = "servletContextDemo5", urlPatterns = "/servletContextDemo5")
public class servletContextDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.通过HttpServlet获取全局对象
ServletContext context = this.getServletContext();
//2.获取文件的真实(服务器)路径,可以获取全局范围下所有文件的路径
//2.1 web目录下资源访问
String b_realPath = context.getRealPath("/b.txt");
System.out.println(b_realPath);
//将文件加载进内存,读取内容
FileReader reader = new FileReader(b_realPath);
int len = 0;
char[] chars = new char[1024];
while ((len = reader.read(chars))!=-1){
System.out.println(new String(chars,0,len));
}
//2.2 WEB-INF目录下的资源访问
String c_realPath = context.getRealPath("/WEB-INF/c.txt");
System.out.println(c_realPath);
//2.3 src目录下的资源访问:src目录下的资源最后都会存放在/WEB-INF/classes/目下
String a_realPath = context.getRealPath("/WEB-INF/classes/a.txt");
System.out.println(a_realPath);
}
}
b.txt内容
username=zhangsan
浏览器访问servletContextDemo5,控制台打印:
文件下载案例
一.文件下载需求
- 页面显示超链接
- 点击超链接后弹出下载提示框
- 完成图片文件下载
二.需求分析
- 超链接指向的资源如果能够被浏览器解析,则会在浏览器中展示,如果不能解析(比如视频),则弹出下载提示框。不满足需求
- 任何资源都必须弹出下载提示框
- 使用响应头设置资源的打开方式,以附件的形式打开:
content-disposition:attachment;filename=xxx
浏览器访问不同资源的情况:
点击图片1,超链接访问一张图片资源,可以解析,直接显示。
点击视频,超链接访问视频资源,不能被解析,则弹出下载提示框。
三.案例实现步骤
- 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
- 定义Servlet
- 获取文件名称
- 使用字节输入流加载文件进内存
- 指定response的响应头: content-disposition:attachment;filename=xxx
- 将数据写出到response输出流
代码实现
程序目录结构
1.定义页面,download.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body>
<a href="img/2.jpg">图片1</a>
<a href="img/1.avi">视频</a>
<hr/>
<a href="/DownLoad/DownLoadServlet?fileName=2.jpg">图片1下载</a>
<a href="/DownLoad/DownLoadServlet?fileName=九尾.jpg">中文图片下载</a>
<a href="/DownLoad/DownLoadServlet?fileName=1.avi">视频下载</a>
</body>
</html>
2.定义Servlet,DownLoadServlet.java
@WebServlet(name = "DownLoadServlet", urlPatterns = "/DownLoadServlet")
public class DownLoadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.获取请求参数,文件名称
String fileName = request.getParameter("fileName");
//2.使用输入字节流加载文件进内存
//2.1 找到文件服务器的真实路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/" + fileName);
//2.2 使用字节流加载文件
FileInputStream fis = new FileInputStream(realPath);
//3.设置response的响应头
//3.1 设置响应头类型:content-type,告诉浏览器文件的类型
//获取文件的mime类型
String mimeType = servletContext.getMimeType(fileName);
response.setHeader("content-type",mimeType);
//3.2 设置响应头文件打开方式:content-disposition
//filename为文件打开时显示的文件的名称
response.setHeader("content-disposition","attachment;filename="+fileName);
//4.将输入流的数据写入到输出流中
ServletOutputStream os = response.getOutputStream();
byte[] bytes = new byte[1024*8];
int len = 0;
while((len = fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
os.close();
fis.close();
}
}
运行,浏览器访问download.html
点击图片1下载,变成弹出下载框形式
点击视频下载,弹出下载框
点击中文图片下载,弹出下载框,文件名显示乱码,下面我们解决中文文件乱码问题。
四.存在的问题
中文文件问题
问题描述:中文的文件名,在弹出的下载提示框中是不能正常显示的。并且不同浏览器展示出来的中文文件名不一样。
乱码问题就需要设置filename
编码方式,并且不同的浏览器需要设置编码方式也不同。
解决思路
- 获取客户端使用的浏览器版本信息
- 根据不同的版本信息,设置filename的编码方式不同
代码实现
提供一个解决filename编码问题的工具类,网上也有许多这样的工具类,使用工具类方法编码文件名即可:
DownLoadUtils.java
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;
}
}
优化后的DownLoadServlet.java
@WebServlet(name = "DownLoadServlet", urlPatterns = "/DownLoadServlet")
public class DownLoadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.获取请求参数,文件名称
String fileName = request.getParameter("fileName");
//2.使用输入字节流加载文件进内存
//2.1 找到文件服务器的真实路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/" + fileName);
//2.2 使用字节流加载文件
FileInputStream fis = new FileInputStream(realPath);
//3.设置response的响应头
//3.1 设置响应头类型:content-type,告诉浏览器文件的类型
//获取文件的mime类型
String mimeType = servletContext.getMimeType(fileName);
response.setHeader("content-type",mimeType);
//3.2 设置响应头文件打开方式:content-disposition
//解决中文文件名问题
//1.获取user-agent请求头,浏览器信息
String agent = request.getHeader("user-agent");
//2.使用工具类方法编码文件名即可
fileName = DownLoadUtils.getFileName(agent,fileName);
//filename为文件打开时显示的文件的名称
response.setHeader("content-disposition","attachment;filename="+fileName);
//4.将输入流的数据写入到输出流中
ServletOutputStream os = response.getOutputStream();
byte[] bytes = new byte[1024*8];
int len = 0;
while((len = fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
os.close();
fis.close();
}
}
运行,再次点击中文图片下载,弹出下载框,中文文件名正常显示。
以上,就是一个文件下载的简单案例。
欢迎点赞评论,指出不足,笔者由衷感谢哦!~