Response
一. response 对象的原理
1.reponse 对象由服务器创建,被程序员使用。
2.reponse 对象用来设置响应消息。
二. response 对象继承体系结构
ServletResponse(接口)— HttpServletResponse(接口)— org.apache.catalina.connector.ResponseFacade(类)
三. response 设置响应消息数据功能
1. 设置响应行
- 设置状态码:
setStatus(int sc)
2. 设置响应头
setHeader(String name, String value)
3. 设置响应体
1.获取输出流
- 字符输出流:
PrintWriter getWriter()
- 字节输出流:
ServletOutputStream getOutputStream()
2.通过输出流将数据输出到客户端浏览器
四. response Demo
1. 完成重定向
1.重定向:资源跳转的方式
2.特点(与转发的特点相反)
- 浏览器地址栏路径发生变化
- 可以访问其他站点(服务器)的资源
- 重定向在两次请求中进行,不能使用 request 对象共享数据。
3.路径写法
- 相对路径:以
.
开头的路径,不能确定唯一资源。e.g../index.html
- 找到当前资源和目标资源的相对位置关系
./
:当前目录../
:后退一级目录
- 绝对路径:以
/
开头的路径,确定唯一资源。e.g. http://localhost:8080/response_demo/responseDemo2 -->/response_demo/responseDemo2
- 判断定义的路径是给谁用的,即判断请求从哪里发出。
- 客户端浏览器:+虚拟目录(项目的访问路径)
- 建议动态获取虚拟目录:
request.getContextPath()
<a>
、<form>
、重定向 redirect
- 建议动态获取虚拟目录:
- 服务器:不需要+虚拟目录
- 转发 forward
System.out.println("ResponseDemo1...");
request.setAttribute("msg", "hello");
// 访问 /responseDemo1 会自动跳转到 /responseDemo2
// 1. 设置状态码为 302
// response.setStatus(302);
// 2. 设置响应头 location
// response.setHeader("location", "/response_demo/responseDemo2");
// response.sendRedirect("/response_demo/responseDemo2");
// 动态获取虚拟目录
String contextPath = request.getContextPath();
response.sendRedirect(contextPath + "/responseDemo2");
// response.sendRedirect("https://www.baidu.com");
System.out.println("ResponseDemo2...");
// 结果为 null,重定向对应两次请求,不共享 request 域的数据
System.out.println(request.getAttribute("msg"));
System.out.println("ResponseDemo3...");
// 服务器转发到 responseDemo2,路径不用写虚拟目录
request.getRequestDispatcher("/responseDemo2").forward(request, response);
2. 服务器输出字符数据到浏览器
1.步骤
- 获取字符输出流
- 输出数据
2.乱码问题:编码格式与解码格式不同
- 获取流的默认编码格式是 ISO-8859-1:
PrintWriter pw = response.getWriter();
- 设置流的编码格式,并告诉浏览器响应体数据的数据格式和编码格式(令浏览器以哪种编码格式去解码):
response.setContentType("text/html;charset=UTF-8");
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.io.IOException;
import java.io.PrintWriter;
/**
* 服务器输出字符数据到浏览器,并解决乱码问题
*/
@WebServlet("/responseDemo4")
public class ResponseDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取流对象之前,改变流的默认编码 ISO-8859-1 为 UTF-8
// response.setCharacterEncoding("UTF-8");
// 告诉浏览器,服务器返回的响应体数据的数据格式和编码格式,建议浏览器使用该编码格式来解码(还可以设置流的编码)
// response.setHeader("Content-Type", "text/html;charset=UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 1. 获取字符输出流
PrintWriter pw = response.getWriter();
// 2. 输出数据
// pw.write("<h1>hello response</h1>");
pw.write("你好 response");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
3. 服务器输出字节数据到浏览器
1.步骤
- 获取字节输出流
- 输出数据
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 服务器输出字节数据到浏览器
*/
@WebServlet("/responseDemo5")
public class ResponseDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
// 1. 获取字节输出流
ServletOutputStream sos = response.getOutputStream();
// 2. 输出数据
sos.write("hello".getBytes());
sos.write("你好".getBytes("UTF-8"));
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
4. 验证码
1.本质:图片
2.目的:防止恶意注册表单
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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;
/**
* 验证码
*/
@WebServlet("/checkCodeServlet")
public class checkCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 100; // 验证码图片的宽度
int height = 50; // 验证码图片的高度
// 1. 创建一个对象,代表在内存中的验证码图片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 2. 美化图片
// 2.1 填充背景色
Graphics g = image.getGraphics(); // 画笔对象
g.setColor(Color.PINK); // 设置画笔颜色
g.fillRect(0, 0, width, height);
// 2.2 画边框
g.setColor(Color.BLUE);
// 边框占 1 像素,所以宽高相应 - 1
g.drawRect(0, 0, width - 1, height - 1);
// 2.3 写验证码
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random ran = new Random();
// 随机生成四个验证码字符
for(int i = 1; i <= 4; i++) {
// 生成随机角标
int index = ran.nextInt(str.length());
// 获取随机字符
char ch = str.charAt(index);
g.drawString(ch + "", width / 5 * i, height / 2);
}
// 2.4 画干扰线
g.setColor(Color.GREEN);
// 随机生成 10 条干扰线
for(int i = 0; i < 10; i++) {
// 随机生成 4 个坐标点
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1, x2, y1, y2);
}
// 3. 将图片输出到页面
ImageIO.write(image, "jpg", response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}