HttpServletResponse Response对象
* 功能: 设置响应消息
1. 设置响应行
1. 格式: HTTP/1.1 200 OK
2. 设置状态码: setStatus(int sc)
2. 设置响应头: setHeader(String name, String value)
3. 设置响应体:
* 使用步骤:
1. 获取输出流
* 字符输出流: PrintWriter getWriter()
* 字节输出流: ServletOutputStream getOutputStream()
2. 使用输出流, 将数据输出到客户端浏览器
* 案例:
1. 完成重定向
* 重定向: 资源跳转的方式
* 代码实现:
1. 第一种方式:
// 1. 设置状态码为302
response.setStatus(302);
// 2. 设置响应头location, 重定向的路径
response.setHeader("location", "/responseDemo2");
2. 第二种方式(重点掌握):
// 简单的重定向方法
response.sendRedirect("/responseDemo2");
* 重定向的特点: redirect
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求, 不能使用request对象来共享数据
* 转发的特点: forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求, 可以使用request对象来共享数据
* 路径写法:
1. 路径分类:
1. 相对路径: 通过相对路径不可以确定唯一资源
* 如: ./index.html
* 不以/开头, 以.开头路径
* 规则: 找到当前资源和目标资源之间的相对位置关系
* ./: 当前目录
* ../: 后退一级目录
2. 绝对路径: 通过绝对路径可以确定唯一资源
* 如: http://localhost:8080/responseDemo2 /responseDemo2
* 以/开头的路径
* 规则: 判断定义的路径是给谁用的? 判断请求从哪儿发出
* 给客户端浏览器使用: 需要加虚拟目录(项目的想问路径)
* 建议虚拟目录动态获取: request.getContextPath()
* 给服务器使用: 不需要加虚拟目录
* 转发路径
3. 动态获取虚拟目录: 以后不管服务器的虚拟目录怎么改, 你之前定义的转发, 或者重定向都不用再手动改.(注意: 虚拟目录千万不要写死)
String contextPath = request.getContextPath();
2. 服务器输出字符数据到浏览器
* 步骤:
1. 获取字符输出流
2. 输出数据
3. 代码:
/*
// 获取流对象之前, 设置流的默认编码: ISO-8859-1 设置为:utf-8,
response.setCharacterEncoding("utf-8");
// 告诉浏览器, 服务器发送的消息体数据的编码. 要浏览器使用该编码解码
response.setHeader("content-type", "text/html;charset=utf-8");
这两句可以省略成一句
response.setHeader("content-type", "text/html;charset=utf-8");
这一句又很麻烦, 所有重点记住这行(简化模式)
response.setContentType("text/html;charset=utf-8");
*/
// (写在最前边)设置响应格式, 不设置响应格式, 浏览器无法识别编码, 会出现中文乱码
response.setContentType("text/html;charset=utf-8");
// 1. 获取字符输出流
PrintWriter pw = response.getWriter();
// 2. 输出数据, write也行 print也行
pw.write("<h1>哈哈哈哈</h1>");
pw.println("<h2>嘻嘻<h2>");
* 注意:
* 乱码问题:
1. PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-8859-1
2. 设置该流的默认编码
3. 告诉浏览器响应体使用的编码
* 注意: 是在获取流之前设置
response.setContentType("text/html;charset=utf-8"); 一行搞定2、3问题
3. 服务器输出字节数据到浏览器
* 步骤:
1. 获取字节输出流
2. 输出数据
3. 代码:
/*
// 获取流对象之前, 设置流的默认编码: ISO-8859-1 设置为:utf-8,
response.setCharacterEncoding("utf-8");
// 告诉浏览器, 服务器发送的消息体数据的编码. 要浏览器使用该编码解码
response.setHeader("content-type", "text/html;charset=utf-8");
这两句可以省略成一句
response.setHeader("content-type", "text/html;charset=utf-8");
这一句又很麻烦, 所有重点记住这行(简化模式)
response.setContentType("text/html;charset=utf-8");
*/
// (写在最前边)设置响应格式, 不设置响应格式, 浏览器无法识别编码, 会出现中文乱码
response.setContentType("text/html;charset=utf-8");
// 1. 获取字节输出流
ServletOutputStream sos = response.getOutputStream();
// 2. 输出数据, write
/*
getBytes把字符串改成字节数组, 不传编码默认是得到一个操作系统默认的
编码格式的字节数组。这个表示在不同OS下,返回的东西不一样
*/
sos.write("<h1>哈哈哈<h1>".getBytes("utf-8"));
4. 验证码:
1. 本质: 图片
2. 目的: 防止恶意表单注册
3. 代码:
int width = 100;
int height = 50;
// 1. 创建一对象, 在内存中画图(验证码图片对象)
/*
第一个参数: 宽度
第二个参数: 高度
第三个参数: 常量值, 都在BufferedImage这个类下
*/
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 2. 美化图片
// 2.1 填充背景色
Graphics graphics = image.getGraphics(); // 获取画笔对象
// 设置画笔的颜色-->粉色
graphics.setColor(Color.PINK);
// 填充矩形
graphics.fillRect(0, 0, width, height);
// 2.2 画边框
graphics.setColor(Color.blue); // 设置画笔的颜色为蓝色
// 画边框
graphics.drawRect(0, 0, width-1, height-1);
// 定义字符集
String str = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890";
// 生成随机角标
Random random = new Random();
// 2.3 写验证码
for (int i = 1; i <= 4; i++){
// 生成随机下标
int index = random.nextInt(str.length());
// 获取随机字符
char ch = str.charAt(index);
graphics.drawString(ch+"", width/5*i, height/2);
}
// 2.4 画干扰线
graphics.setColor(Color.GREEN);
// 随机生成坐标点
for (int i = 0; i < 10; 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);
}
// 3. 将图片输出到页面展示
/*
第一个参数: BufferedImage对象
第二个参数: 图片的后缀
第三个参数: 字节流对象
*/
ImageIO.write(image, "jpg", response.getOutputStream());
* 文件下载:
* 文件下载需求:
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的编码方式不同
* 代码实现:
// 1. 获取ServletContext对象
ServletContext servletContext = this.getServletContext();
// 2. 接受参数
String fileName = request.getParameter("filename");
// 3. 校验参数
if (fileName == null) {
response.setContentType("text/html;charset=utf-8");
response.setStatus(404);
response.getWriter().write("Not Found...");
return; // 结束该方法
}
// 4. 设置响应头类型
String mimeType = servletContext.getMimeType(fileName);
response.setContentType(mimeType);
// 5. 获取文件路径
String realPath = servletContext.getRealPath("/img/" + fileName);
// 6. 把文件加载进内存
FileInputStream fis = new FileInputStream(realPath);
/*
重点:
把文件加载进内存
一定要放在编码文件名之前, 因为先编码文件名, 那么还怎么把文件加载进内存
使用工具类方法编码文件名
*/
// 7. 解决中文名文件
// 7.1 获取user-agent请求头, 获取浏览器版本信息
String agent = request.getHeader("user-agent");
// 7.2 使用工具类方法编码文件名即可
fileName = DownLoadUtils.getFileName(agent, fileName);
// 7.3 设置响应头打开方式
response.setHeader("content-disposition", "attachment;filename=" + fileName);
// 8. 将输入流的数据写出到输出流中
ServletOutputStream sos = response.getOutputStream();
// 8.1 使用数组缓冲读取多个字节, 写入多个字节
byte[] buff = new byte[1024 * 8];
// 8.2 每次读取的有效字节数
int len = 0;
// 8.3 把read读取到的数据存到buff里, 每次读取的长度赋值给len 在跟-1对比
while((len = fis.read(buff)) != -1){
// 8.4 使用response字节输出流中的方法write, 把读取到的字节回写到浏览器客户端
sos.write(buff, 0, len); // 写入从bytes数组 0位置开始写入的长度为len
}
// 8.5 关闭文件字节输入流
fis.close();
* 解决文件中文名->工具类网上很多:
package cn.xiaoge.web.utils;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
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;
}
}