- Response
- 设置响应消息数据
- 1.设置响应行
- 2.设置响应头
- 3.设置响应体
- 案例
- 1.重定向
- 2.输出字符数据到 Response 对象
- 乱码的问题
- 解决办法一
- 解决办法二
- 3.输出字节数据到 Response 对象
- 4.验证码案例
- 继承与实现体系
该对象的功能就是用来设置响应消息(响应报文)。
程序员将响应数据封装到 Response 对象中,Tomcat 会从 Response 对象中取出程序员设置的响应数据,并将这些响应数据、响应头数据、响应行数据封装成响应报文(即响应数据包)返回给浏览器端。
设置响应消息数据 1.设置响应行响应行格式:HTTP/1.1 200 OK 设置状态码:void setStatus(int sc)
2.设置响应头void setHeader(String name, String value)
3.设置响应体1.获取输出流 获取输出流:PrintWriter getWriter()
获取字节流:ServletOutputStream getOutputStream()
2.使用输出流,将响应数据输出到 ServletResponse 对象中
案例 1.重定向// 设置重定向的状态码
resp.setStatus(302);
// 设置响应头
resp.setHeader("Location","/servlet_demo/response_demo02");
或者
// 重定向到ResponseDemo02
resp.sendRedirect("/servlet_demo/response_demo02");
2.输出字符数据到 Response 对象
// 获取字符输出流
PrintWriter pw = response.getWriter();
// 输出数据,写入数据。先写入到流对象的缓冲区,再写入到 Response 对象中,服务器再从 Response 对象中读取数据封装成响应报文返回给客户端
pw.write("hello");
乱码的问题
乱码的原因分析: 服务端输出数据,需要编码,而浏览器加载解析数据需要解码,乱码的原因就是编码和解码使用的编码格式不同所导致的。
浏览器用于解码的默认字符编码与操作系统有关,中文系统默认的字符编码是 GBK 或者 GB2312,而服务器端获取的输出流对象,是由 Tomcat 创建的,所以使用的字符编码是 ISO-8859-1,所以使用 GBK 或者 GB2312 去解码 ISO-8859-1 编码肯定出现乱码了。
解决办法一不要使用 ISO-8859-1 进行编码,改为使用 GBK 进行编码。
示例代码如下:
// 在获取输出流之前将Response对象的字符编码设置为GBK,默认的是ISO-8859-1
resp.setCharacterEncoding("GBK");
// 获取字符输出流
PrintWriter pw = resp.getWriter();
// 输出数据
pw.write("刘德华");
解决办法二
在解决办法一种,直接将 Response 对象的字符编码设为 GBK,是因为你知道浏览器默认使用的是 GBK,如果你不知道呢?或者用户使用的浏览器默认的编码不是 GBK 呢?所以上述的写法还不够,你还需要告诉客户端响应数据所使用的字符编码,建议浏览器使用该编码进行解码。这样就不要管浏览器默认的字符编码是啥,浏览器在解析数据的时候会使用服务端建议的编码进行解码。
所以完整的示例代码如下:
// 在获取输出流之前将Response对象的字符编码设置为GBK,默认的是 ISO-8859-1
resp.setCharacterEncoding("utf-8");
// 告诉浏览器,服务器返回的响应体数据的字符编码,建议浏览器使用该编码进行解码
resp.setHeader("content-type","text/html;charset=utf-8");
// 获取字符输出流
PrintWriter pw = resp.getWriter();
// 输出数据
pw.write("刘德华");
上述代码中的 resp.setCharacterEncoding("utf-8");
可以去掉,因为 resp.setHeader("content-type","text/html;charset=utf-8");
已经指明输出数据时需要使用什么字符编码,并且还告诉浏览器需要使用什么字符编码进行解码。
另外 resp.setHeader("content-type","text/html;charset=utf-8");
可以替换成另外一个 API 进行简写,如下:
// 简单的写法,设置响应头Content-Type的值
resp.setContentType("text/html;charset=utf-8");
最终的示例代码如下:
// 设置响应头Content-Type的值
resp.setContentType("text/html;charset=utf-8");
// 获取字符输出流
PrintWriter pw = resp.getWriter();
// 输出数据
pw.write("刘德华");
3.输出字节数据到 Response 对象
示例代码:
// 设置Response对象的字符编码为utf-8
resp.setContentType("text/html;charset=utf-8");
// 获取字节输出流
ServletOutputStream sos = resp.getOutputStream();
// 获取字符的字节数组作为参数传递,写入到字节输出流中,最后会从字节输出流写入到Response对象中
sos.write("中国人".getBytes());
那么将消息头 Content-Type
的值设为 text/html;charset=gbk
行不行呢?
答:不行。设为 gb2312 也不行。因为通过响应消息头 Content-Type
设 置字符编码为 GBK,那么字符输出流会按 GBK 进行编码,而字节输出流是写入字节数据,需要获取字符的字节数组,通过 getBytes 方法获取字节数组,如果没有指定字符编码默认使用的是 UTF-8,所以写入的是 UTF-8 的字节数组,因此浏览器端收到的响应数据的编码格式是 UTF-8,而你又通过消息头Content-Type
告诉浏览器使用 GBK 解码,所以中文字符肯定出现乱码了。
我们知道浏览器在中文操作系统中默认的字符编码是 GBK,如果希望服务端在使用字节输出流输出数据时使用 GBK 编码,必须这样写:
// 获取字节输出流
ServletOutputStream sos = resp.getOutputStream();
// 获取字符的字节数组作为参数传递,写入到字节输出流中,最后会从字节输出流写入到Response对象中
// getBytes方法指定字符编码参数为“GBK”才能得到”GBK“格式的字节数组
sos.write("中国人".getBytes("gbk"));
4.验证码案例
package priv.lwx.javaex.servlet_demo.web.servlet.response;
import javax.imageio.ImageIO;
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.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* 验证码示例代码
*
* @author liaowenxiong
* @date 2022/1/10 11:01
*/
@WebServlet("/check_code")
public class CheckCodeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int width = 100; // 表示图片的宽度,单位像素
int height = 50; // 表示图片的高度,单位像素
// 1.创建一个图片对象,代表内存中的验证码图片。图片对象创建好之后,就表示在内存中创建了一个图片(内存中存储的是二进制数据),图片背景色默认黑色
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
// 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, -1, height - 1);
// 画随机字符
// 随机字符的来源
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
// 创建随机数对象
Random ran = new Random();
// 2.3.画随机字符。循环四次,画4个随机的字符
for (int i = 1; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?