Response对象学习笔记

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. 使用输出流,将数据输出到客户端浏览器


Response 对象的学习案例

完成重定向

  1. 要求:用户通过浏览器访问 demo01 资源,重定向到 demo02 资源

  2. 实现:

    1. 创建一个 JavaEE - Tomcat项目(ResponseHttp)

    2. 定义两个类: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);
          }
      }
      
  3. 启动服务器,用户访问:http://localhost:8080/ResponseHttp_war_exploded/demo01

    1. 服务器端输出(即编译器控制台输出)

      demo01 被访问啦!!!
      
    2. 用户浏览器页面跳转到:http://localhost:8080/ResponseHttp_war_exploded/demo02

    3. 服务器端输出

      demo02 被访问啦!!!
      
  4. 浏览器中检查Network如下:

    1. demo01

      20200528011649
    2. demo02

      20200528011759

重定向的特点

重定向(redirect)特点不同于 Request请求转发(forward)

  1. 地址栏发生变化
  2. 重定向可以访问其他站点(服务器)的资源
  3. 重定向是两次请求。不能使用request对象来共享数据

服务器输出字符数据到浏览器

  1. 实现代码:

    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);
        }
    }
    
  2. 浏览器访问:http://localhost:8080/ResponseHttp_war_exploded/demo03

    20200528020921
  3. 乱码问题

    1. 获取的流的默认编码是ISO-8859-1

    2. 设置该流的默认编码

    3. 告诉浏览器响应体使用的编码

      // 简单的形式,设置编码,是在获取流之前设置
      response.setContentType("text/html;charset=utf-8");
      

服务器输出字节数据到浏览器

  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;
    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);
        }
    }
    
  2. 开启服务器,浏览器访问:http://localhost:8080/ResponseHttp_war_exploded/demo04,浏览器页面输出

    你好,Response!
    

验证码

  1. 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);
        }
    }
    
  2. 启动服务器,浏览器中访问:http://localhost:8080/ResponseHttp_war_exploded/checkCodeServlet

    20200528034555

    上面这需要刷新页面,才能更新验证码。

  3. 下面编写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>
    
  4. 启动服务器,浏览器访问:http://localhost:8080/ResponseHttp_war_exploded/CheckCodeHtml.html

    20200528035652

    每次点击图片,都会直接更换验证码,请求的url都是随时间的变化而变化的,而点击 看不清换一张 则仅仅只是刷新了一次该页面。

参考文献

Good Good Write Bug, Day Day Up
原文地址:https://www.cnblogs.com/liyihua/p/14477460.html