一、HttpServletResponse对象
1、概念
- HttpServletResponse专门负责响应的,它是一个接口,是ServletResponse接口的子接口
- 实现类是服务器做的实现
- 它带有http协议,那么我们就可以按照之前学习Http响应协议的方法来学习它
2、http响应协议
2.1 组成部分
响应行、响应头、响应体
2.2 操作响应行
格式:协议/版本 状态码 状态码说明
常见的响应状态码
状态码 | 说明 |
---|---|
200 | 正常响应 |
302 | 重定向 |
304 | 读缓存 |
404 | 找不到资源 |
405 | 访问的方法不存在 |
500 | 服务器内部错误 |
设置响应状态码
- setStatus(int 状态码);-----针对于1XX,2XX,3XX
- sendError(int 状态码);-----针对于4XX,5XX
2.3 操作响应头
格式:key/value(value可以是多个值)
方法 | 说明 |
---|---|
public void setHeader(String name,String value); | 设置HTTP协议的响应头字段,一头一值,会覆盖 |
public void addHeader(String name,String value); | 设置HTTP协议的响应头字段,一头多值,不会覆盖,设置cookie |
public void setCharacterEncoding(String encoding); | 设置服务器向客户端响应数据的编码 |
public void setContentType(String type); | 设置的mime类型; 解决响应乱码问题的方法 除了设置服务器向客户端响应数据的编码外,还告诉浏览器使用什么编码来解析 |
public void setContentLength(int len); | 设置响应消息的实体内容的大小 |
常用的响应头:
- location:重定向
- refresh:定时刷新
- content-type:设置文件的mime类型,设置响应流的编码及告诉浏览器用什么编码打开
- content-disposition:文件下载
操作响应体
- getWriter(); //字符流
- getOutputStream(); //字节流 (只要是文件下载或者文件上传,都必须使用这个)
- 注意:不要同时使用这2个流
package com.itheima.web.servlet;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.itheima.domain.User;
import com.itheima.service.UserService;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
}
@Override
public void init() throws ServletException {
// 1.定义一个变量进行初始化
int count = 0;
// 2.获取ServletContext域对象
ServletContext servletContext = this.getServletContext();
// 3.将变量保存到域对象中
servletContext.setAttribute("count", count);
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 处理中文乱码
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
// 1.获取请求参数
String username = request.getParameter("username");
String password = request.getParameter("password");
// 2.封装数据
User user = new User();
user.setUsername(username);
user.setPassword(password);
// 3.调用service层方法
UserService service = new UserService();
User existUser = null;
try {
existUser = service.login(user);
// 4.对查询结果进行判断
if (existUser != null) {
// 5.获取ServletContext对象
ServletContext servletContext = this.getServletContext();
// 6.从ServletContext域对象中获取值
int count = (int) servletContext.getAttribute("count");
// 7.自增
count++;
// 8.放入域对象中
servletContext.setAttribute("count", count);
// 9.给出提示信息
response.getWriter().write("<h3 style='color:blue'>"+"亲,您是第" + count + "次登录..."+"</h3>");
} else {
response.getWriter().write("<h3 style='color:red'>"+"登录失败"+"</h3>");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
二、文件下载
1、下载方式
1.1 超链接下载(不靠谱)
直接将服务器上的文件的路径写到href属性中
- 如果浏览器不支持该格式文件,那么就会提示进行下载
- 如果浏览器支持这个格式的文件,那么直接打开
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body>
<h3>超链接方式:不靠谱</h3>
<a href="http://localhost:8080/web_day35/download/feiji03.gif">feiji03.gif</a><br>
<a href="http://localhost:8080/web_day35/download/DownloadServlet.java">DownloadServlet.java</a><br>
<a href="http://localhost:8080/web_day35/download/document.zip">document.zip</a><br>
</body>
</html>
1.2 编码下载(重点)
无论浏览器是否识别该格式的文件,都会提示下载
需要的信息 | 说明 |
---|---|
Content-Type | 要下载文件类型的MIME的类型 |
Content-Disposition:"attachment;filename="+filename | 浏览器识别该格式文件,提示下载 |
文件的输入流 | 需要文件的真实路径 |
2、文件下载案例
download.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Refresh" content="3; url=http://www.itcast.cn">
<title>文件下载</title>
</head>
<body>
<h3>手动编码方式:靠谱</h3>
<a href="http://localhost:8080/web_day35/DownloadServlet?filename=feiji.gif">feiji.gif</a><br>
<a href="http://localhost:8080/web_day35/DownloadServlet?filename=DownloadServlet.java">DownloadServlet.java</a><br>
<a href="http://localhost:8080/web_day35/DownloadServlet?filename=document.zip">document.zip</a><br>
<a href="http://localhost:8080/web_day35/DownloadServlet?filename=飞机.gif">飞机.gif</a><br>
</body>
</html>
</html>
DownloadServlet.java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import sun.misc.BASE64Encoder;
/**
* 文件下载 文件下载:(1一个流2个头)
* 文件输入流:直接创建即可(需要知道这个文件的真实路径)
* Content-Type:执行文件的MIME类型(ServletContext.getMimeType(文件名称))
* Content-Disposition:"attachment;filename="+filename(从页面获得)
*/
public class DownloadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 1.获取请求参数(文件名)
String filename = request.getParameter("filename");
// 2.解决请求乱码问题
filename = new String(filename.getBytes("iso8859-1"), "utf-8");
ServletContext context = this.getServletContext();
// 3.获取文件的真实路径
String realPath = context.getRealPath("download/" + filename);
// 4.获取文件的MIME类型
String mimeType = context.getMimeType(filename);
// 5.解决下载框的乱码(根据不同的浏览器来处理:只有火狐不一样,其它 的处理一样)
// 获得User-Agent
String header = request.getHeader("User-Agent");
if (header.contains("Firefox")) {
// 说明是火狐浏览器
filename = base64EncodeFileName(filename);
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
// 6.设置Content-Type头
response.setHeader("Content-Type", mimeType);
// 7.设置Content-Disposition头(告诉浏览器无论如何都要给我弹出下载框)
response.addHeader("Content-Disposition", "attachment;filename=" + filename);
// 8.创建一个文件输入流
InputStream is = new FileInputStream(realPath);
// 9.获得输出流
ServletOutputStream os = response.getOutputStream();
// 10.流对拷
IOUtils.copy(is, os);
// 11.关闭流
os.close();
is.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
/**
* @MethodName:base64EncodeFileName
* @Description:火狐浏览器编码问题
* @param fileName
* @return
*/
public static String base64EncodeFileName(String fileName) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
return "=?UTF-8?B?" + new String(base64Encoder.encode(fileName.getBytes("UTF-8"))) + "?=";
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
案例--点击获取验证码
页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<img alt="验证码" src="/day10/code" title="看不清除,换一张" onclick="changeImg(this)">
</body>
<script type="text/javascript">
function changeImg(obj){
//操作src属性
obj.src="/day10/code?i="+Math.random();
//obj.src="/day10/code";
//alert(1)
}
</script>
</html>
CodeServlet.java
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 使用java图形界面技术绘制一张图片
int charNum = 4;
int width = 30 * 4;
int height = 30;
// 1. 创建一张内存图片
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 2.获得绘图对象
Graphics graphics = bufferedImage.getGraphics();
// 3、绘制背景颜色
graphics.setColor(Color.YELLOW);
graphics.fillRect(0, 0, width, height);
// 4、绘制图片边框
graphics.setColor(Color.BLUE);
graphics.drawRect(0, 0, width - 1, height - 1);
// 5、输出验证码内容
graphics.setColor(Color.RED);
graphics.setFont(new Font("宋体", Font.BOLD, 20));
// 随机输出4个字符
Graphics2D graphics2d = (Graphics2D) graphics;
String s = "ABCDEFGHGKLMNPQRSTUVWXYZ23456789";
Random random = new Random();
// session中要用到
String msg = "";
int x = 5;
for (int i = 0; i < 4; i++) {
int index = random.nextInt(32);
String content = String.valueOf(s.charAt(index));
msg += content;
double theta = random.nextInt(45) * Math.PI / 180;
// 让字体扭曲
graphics2d.rotate(theta, x, 18);
graphics2d.drawString(content, x, 18);
graphics2d.rotate(-theta, x, 18);
x += 30;
}
// 6、绘制干扰线
graphics.setColor(Color.GRAY);
for (int i = 0; i < 5; i++) {
int x1 = random.nextInt(width);
int x2 = random.nextInt(width);
int y1 = random.nextInt(height);
int y2 = random.nextInt(height);
graphics.drawLine(x1, y1, x2, y2);
}
// 释放资源
graphics.dispose();
// 图片输出 ImageIO
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}