Response 对象功能介绍
功能:设置响应消息(响应头、响应行、响应体)
-
设置响应行:
- 格式:HTTP/1.1 200 ok
- 设置状态码:setStatus(int sc)
-
设置响应头:setHeader(String name, String value)
-
设置响应体:
使用步骤:
-
获取输出流
PrintWriter getWriter() // 字符输出流 ServletOutputStream getOutputStream() // 字节输出流
-
使用输出流,将数据输出到客户端浏览器
-
Response 对象的学习案例
完成重定向
-
要求:用户通过浏览器访问
demo01
资源,重定向到demo02
资源 -
实现:
-
创建一个 JavaEE - Tomcat项目(ResponseHttp)
-
定义两个类:demo01、demo02
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; @WebServlet("/demo01") public class ResponseDemo01 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("demo01 被访问啦!!!"); // 要求:用户通过浏览器访问 /demo01 资源,会自动跳转到 /demo02 资源 // 实现如下: // 1. 设置状态码为 302 ———— 重定向状态码 response.setStatus(302); // 2. 设置响应头location,对应 demo02 的资源路径 response.setHeader("location", "/ResponseHttp_war_exploded/demo02"); /* 简单的重定向方法 response.sendRedirect("/ResponseHttp_war_exploded/demo02"); 这里的虚拟目录/ResponseHttp_war_exploded,推荐动态获取,因为一旦虚拟目录改变, 如果不是动态获取的虚拟目录,将于全部进行修改。 response.sendRedirect(request.getContextPath() + "/demo02"); */ } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
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; @WebServlet("/demo02") public class ResponseDemo02 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("demo02 被访问啦!!!"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
-
启动服务器,用户访问:http://localhost:8080/ResponseHttp_war_exploded/demo01
-
服务器端输出(即编译器控制台输出)
demo01 被访问啦!!!
-
用户浏览器页面跳转到:http://localhost:8080/ResponseHttp_war_exploded/demo02
-
服务器端输出
demo02 被访问啦!!!
-
-
浏览器中检查Network如下:
-
demo01
-
demo02
-
重定向的特点
重定向(redirect)特点不同于 Request请求转发(forward)。
- 地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求。不能使用request对象来共享数据
服务器输出字符数据到浏览器
-
实现代码:
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("/demo03") public class ResponseDemo03 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 乱码问题的解决 // 解决方式1 // 获取流对象之前,将流对象默认的编码(ISO-8859-1)修改为 GBK request.setCharacterEncoding("GBK"); response.setCharacterEncoding("GBK"); // 解决方式2 // 告诉浏览器,服务器发送的消息体数据编码,建议浏览器使用该编码 // response.setHeader("content-type", "text/html;charset=utf-8"); // 解决方式3 // response.setContentType("text/html;charset=utf-8"); // 获取字符输出流 PrintWriter responseWriter = response.getWriter(); // 输出数据 responseWriter.write("<h1>你好,Response!</h1><br><h2>你好,Response!</h2>"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
浏览器访问:http://localhost:8080/ResponseHttp_war_exploded/demo03
-
乱码问题
-
获取的流的默认编码是ISO-8859-1
-
设置该流的默认编码
-
告诉浏览器响应体使用的编码
// 简单的形式,设置编码,是在获取流之前设置 response.setContentType("text/html;charset=utf-8");
-
服务器输出字节数据到浏览器
-
实现代码:
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; import java.nio.charset.StandardCharsets; @WebServlet("/demo04") public class ResponseDemo04 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 告诉浏览器,服务器发送的消息体数据编码,建议浏览器使用该编码(设置响应头中的content-type值) response.setContentType("text/html;charset=utf-8"); // 获取字节输出流 ServletOutputStream responseOutputStream = response.getOutputStream(); // 输出数据 responseOutputStream.write("你好,Response!".getBytes(StandardCharsets.UTF_8)); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
开启服务器,浏览器访问:http://localhost:8080/ResponseHttp_war_exploded/demo04,浏览器页面输出
你好,Response!
验证码
-
Java 代码:
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; @WebServlet("/checkCodeServlet") public class CheckCodeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 定义验证码方框长和宽 int width = 100, height = 50; // 创建一个对象,在内存中画图(验证码图片对象) BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); // 美化图片 // 创建画笔对象 Graphics graphics = bufferedImage.getGraphics(); // 设置画笔的颜色 graphics.setColor(Color.PINK); // 用画笔,将制定的长方形区域,画满(画验证码图片背景 -> 粉红色) graphics.fillRect(0, 0, width, height); // 画验证码图片边框 // 设置画笔的颜色 graphics.setColor(Color.BLACK); graphics.drawRect(0, 0, width - 1, height - 1); // 定义一个包含所有字幕和数字的字符串(验证码) String strings = "QqWwEeRrTtYyUuIiOoPpAaSsDdFfGgHhJjKkLlZzXxCcVvBbNnMm1234567890"; // 创建随机数对象,用来获取字符串中的一个字符 Random random = new Random(); // 写入四个字符在验证码方框中 int codeNumber = 4; for (int i = 1; i <= codeNumber; i++) { // strings 索引 int index = random.nextInt(strings.length()); // 通过索引获取字符 char indexString = strings.charAt(index); // 写入一个验证符 graphics.drawString(indexString + "", width / 5 * i, height / 2); } // 在验证码方框中画干扰线 graphics.setColor(Color.GREEN); int lineNumber = 10; for (int i = 0; i < lineNumber; 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); } // 将图片输出到页面展示 ImageIO.write(bufferedImage, "png", response.getOutputStream()); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
启动服务器,浏览器中访问:http://localhost:8080/ResponseHttp_war_exploded/checkCodeServlet
上面这需要刷新页面,才能更新验证码。
-
下面编写html页面,指定对应的CheckCodeServlet.java
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>验证码</title> <script> /* 分析: 点击超链接或者图片,需要换一张 1.给超链接和图片绑定单击事件 2.重新设置图片的src属性值 */ window.onload = function(){ // 1.获取图片对象 const img = document.getElementById("checkCode"); // 2.绑定单击事件 img.onclick = function(){ // 加时间戳(因为需要每次请求的url都不一样) const date = new Date().getTime(); img.src = "/ResponseHttp_war_exploded/checkCodeServlet?"+date; } } </script> </head> <body> <div> <img id="checkCode" src="/ResponseHttp_war_exploded/checkCodeServlet" /> <a id="change" href=""> 看不清换一张?</a> </div> </body> </html>
-
启动服务器,浏览器访问:http://localhost:8080/ResponseHttp_war_exploded/CheckCodeHtml.html
每次点击图片,都会直接更换验证码,请求的url都是随时间的变化而变化的,而点击
看不清换一张
则仅仅只是刷新了一次该页面。
参考文献
无