前言

该技术博客是我的学习笔记,自我总结并非复制粘贴。

学会Request请求,吃透这篇足够

一、Response功能介绍

  1. 功能:设置响应消息
  2. 1.设置响应行
  3. 1.格式:HTTP/1.1 200 ok
  4. 2.设置状态码:setStatus(int sc)
  5. 2.设置响应头:setHeader(String name,String value)
  6. 3.设置响应体:
  7. 使用步骤:
  8. 1.获取输出流
  9. 字符输出流:PrintWriter getWriter()
  10. 字节输出流:ServletOutputStream getOutputStream()
  11. 2.使用输出流,将数据输出到客户端浏览器中
  12. 123456789101112

二、案例步骤:

  1. 1.完成重定向
  2. 重定向:资源跳转的方式
  3. 代码实现:
  4. //1.设置状态码为302
  5. response.setStatus(302);
  6. //2.设置响应头location
  7. response.setHeader("location","/day15/responseDemo2");
  8. //简单的重定向方法
  9. response.sendRedirect("/day15/responseDemo2");
  10. 重定向的特点:redirect
  11. 1.地址栏发生变化
  12. 2.重定向可以访问其他站点(服务器)的资源
  13. 3.重定向是两次请求,不能使用request对象来共享数据
  14. 转发的特点:forward
  15. 1.转发地址栏路径不变
  16. 2.转发只能访问当前服务器下的资源
  17. 3.转发是一次请求,可以使用request对象共享数据
  18. 路径写法:
  19. 1.路径分类
  20. 1.相对路径:通过相对路径不可以确定唯一资源
  21. 如:./index.html
  22. 不以/开头,以.开头的路径
  23. 规则:确定访问的当前资源和目标资源之间的相对位置关系
  24. ./:表示当前目录
  25. ../:后退一级目录
  26. 2.绝对路径:通过绝对路径可以确定唯一资源
  27. 如:http://localhost/day15/responseDemo2
  28. 以/开头的路径
  29. 规则:判断定义的路径是给谁用的?判断请求将来从哪发出
  30. 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
  31. 介意虚拟目录动态获取:request.getContextPath()
  32. 给服务器使用:不需要加虚拟目录
  33. 转发路径
  34. 2.服务器输出字符数据到浏览器
  35. 步骤:
  36. 1.获取字符输出流
  37. 2.输出数据
  38. 注意:
  39. 乱码问题:
  40. 1.PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-88859-1
  41. 2.设置该的默认编码
  42. 3.告诉浏览器响应体使用的编码
  43. //简单的形式,设置编码,是在获取流之前设置
  44. response.setContentType("text/html;Charset=utf-8");
  45. 3.服务器输出字节数据到浏览器
  46. 步骤:
  47. 1.获取字节输出流
  48. 2.输出数据
  49. 4.验证码
  50. 1.本质:图片
  51. 2.目的:放置恶意表单注册
  52. 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859

三、案例1:重定向代码实现

重定向图解:红线表示的就是重定向
Response - 图1代码实现

  1. package cn.itcast.web.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. /**
  9. * 完成重定向
  10. */
  11. @WebServlet("/responseDemo1")
  12. public class ResponseDemo1 extends HttpServlet {
  13. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  14. System.out.println("demo1........");
  15. /*//访问/responseDemo1资源,会自动跳转到/responseDemo2资源
  16. //1.设置状态码为302
  17. response.setStatus(302);
  18. //2.设置响应头location
  19. response.setHeader("location","/day15/responseDemo2");*/
  20. //简单的重定向方法
  21. response.sendRedirect("/day15/responseDemo2");
  22. }
  23. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  24. this.doPost(request,response);
  25. }
  26. }
  27. =========================================================================================
  28. package cn.itcast.web.servlet;
  29. import javax.servlet.ServletException;
  30. import javax.servlet.annotation.WebServlet;
  31. import javax.servlet.http.HttpServlet;
  32. import javax.servlet.http.HttpServletRequest;
  33. import javax.servlet.http.HttpServletResponse;
  34. import java.io.IOException;
  35. @WebServlet("/responseDemo2")
  36. public class ResponseDemo2 extends HttpServlet {
  37. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  38. System.out.println("demo2......");
  39. }
  40. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  41. this.doPost(request,response);
  42. }
  43. }
  44. 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455

四、案例2:输出字符数据

不墨迹,直接看代码:

  1. package cn.itcast.web.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.io.PrintWriter;
  9. @WebServlet("/responseDemo4")
  10. public class ResponseDemo4 extends HttpServlet {
  11. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  12. //1.获取字符输出流
  13. PrintWriter pw = response.getWriter();
  14. //2.输出数据
  15. pw.write("<h1>hello response</h1>");
  16. }
  17. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  18. this.doPost(request,response);
  19. }
  20. }
  21. 123456789101112131415161718192021222324

debug方式启动后,直接在页面上显示:

Response - 图2很明显,输出字符数据真的非常的简单。

接下来讲一个比较麻烦的事:中文乱码的问题
因为我们输出的数据在所难免会遇到中文的数据。代码如下:

  1. //2.输出数据
  2. pw.write("你好,response");
  3. 12

这样就会出现乱码情况:

Response - 图3那么接下来我们分析一下乱码的原因:无外乎就是编码和解码的码表不一致。
Response - 图4如上图所示:
浏览器打开默认的字符集跟当前操作系统的语言和环境有关系,我们现在用的windows操作系统默认的字符集编码表是GBK(gb2312)
服务器用的不是GBK,否则不会乱码。

字符输出流的编码是ISO的,该编码被GBK解码一定会乱码。
找到原因之后,解决这个乱码就会变得很简单:我们可以设置流的编码是GBK就可以了。

  1. package cn.itcast.web.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.io.PrintWriter;
  9. @WebServlet("/responseDemo4")
  10. public class ResponseDemo4 extends HttpServlet {
  11. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  12. //获取流对象之前去设置流的默认编码:ISO-8859-1 设置为:GBK
  13. response.setCharacterEncoding("GBK");
  14. //1.获取字符输出流
  15. PrintWriter pw = response.getWriter();
  16. //2.输出数据
  17. pw.write("你好,response");
  18. }
  19. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  20. this.doPost(request,response);
  21. }
  22. }
  23. 1234567891011121314151617181920212223242526

设置完流的默认编码后刷新一下服务器就发现,可以识别中文了:
Response - 图5
但是仅仅是一种巧合,为什么?
因为我们明确的知道客户端用的是GBK才可以这样设置。将来有的浏览器就是utf-8,就意味着设置GBK不好使。
我们还需要告诉浏览器,服务器发送的消息体数据的编码,建议浏览器使用该编码解码。如何完成代码如下:

  1. package cn.itcast.web.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.io.PrintWriter;
  9. import java.nio.charset.Charset;
  10. @WebServlet("/responseDemo4")
  11. public class ResponseDemo4 extends HttpServlet {
  12. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  13. //获取流对象之前去设置流的默认编码:ISO-8859-1 设置为:GBK
  14. //response.setCharacterEncoding("utf-8");
  15. //告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码
  16. response.setHeader("content-type","text/html;Charset=utf-8");
  17. //1.获取字符输出流
  18. PrintWriter pw = response.getWriter();
  19. //2.输出数据
  20. pw.write("你好,response");
  21. }
  22. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  23. this.doPost(request,response);
  24. }
  25. }
  26. 12345678910111213141516171819202122232425262728

但是这段代码写起来还是挺麻烦的,因为头信息是固定的,也就是说每一次都要写这行代码。所以response对象给我们提供的一个简单的型式来设置编码:

  1. package cn.itcast.web.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.io.PrintWriter;
  9. import java.nio.charset.Charset;
  10. @WebServlet("/responseDemo4")
  11. public class ResponseDemo4 extends HttpServlet {
  12. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  13. //获取流对象之前去设置流的默认编码:ISO-8859-1 设置为:GBK
  14. response.setCharacterEncoding("utf-8");
  15. //告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码
  16. //response.setHeader("content-type","text/html;Charset=utf-8");
  17. //简单的形式,设置编码
  18. response.setContentType("text/html;Charset=utf-8");
  19. //1.获取字符输出流
  20. PrintWriter pw = response.getWriter();
  21. //2.输出数据
  22. pw.write("你好啊啊啊啊,response");
  23. }
  24. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  25. this.doPost(request,response);
  26. }
  27. }
  28. 12345678910111213141516171819202122232425262728293031

以后我们要记住,在获取字符输出流并且写中文数据之前,就要把这行代码写到最前面:

  1. response.setContentType("text/html;Charset=utf-8");
  2. 1

五、案例3:输出字节数据

接下来说,输出字节数据,代码如下:

  1. package cn.itcast.web.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletOutputStream;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.IOException;
  9. @WebServlet("/responseDemo5")
  10. public class ResponseDemo5 extends HttpServlet {
  11. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  12. //1.获取字节输出流
  13. ServletOutputStream sos = response.getOutputStream();
  14. //2.输出数据
  15. sos.write("hello".getBytes());
  16. }
  17. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  18. this.doPost(request,response);
  19. }
  20. }
  21. 123456789101112131415161718192021222324

hello就被访问到了:
Response - 图6
当我们想输出中文,并且设置的是utf-8就会乱码:

  1. //2.输出数据
  2. sos.write("你好".getBytes("utf-8"));
  3. 12

解决方式:

  1. response.setHeader("content-type","text/html;Charset=utf-8");
  2. 1

六、案例4:验证码

创建验证码步骤非常简单,我们直接代码演示:

  1. package cn.itcast.web.servlet;
  2. import javax.imageio.ImageIO;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.ServletOutputStream;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import java.awt.*;
  10. import java.awt.image.BufferedImage;
  11. import java.io.IOException;
  12. import java.nio.Buffer;
  13. import java.security.DigestOutputStream;
  14. import java.util.Random;
  15. @WebServlet("/checkCodeServlet")
  16. public class CheckCodeServlet extends HttpServlet {
  17. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  18. int width = 100;
  19. int height = 50;
  20. // 1.创建一个对象,在内存中画图(验证码图片对象)
  21. BufferedImage image = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
  22. // 2.美化图片
  23. // 2.1填充背景色
  24. Graphics g = image.getGraphics(); // 获取画笔对象
  25. g.setColor(Color.pink);
  26. g.fillRect(0,0,width,height);
  27. // 2.2画边框
  28. g.setColor(Color.blue);
  29. g.drawRect(0,0,width - 1,height - 1);
  30. String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  31. // 生成随机角标
  32. Random ran = new Random();
  33. for (int i = 1; i <= 4; i++) {
  34. int index = ran.nextInt(str.length());
  35. // 获取字符
  36. char ch = str.charAt(index); // 随机字符
  37. // 2.3写验证码
  38. g.drawString(ch + "" ,width / 5 * i,height / 2);
  39. }
  40. // 2.4画干扰线
  41. g.setColor(Color.green);
  42. // 随机生成坐标点
  43. for (int i = 0; i < 10; i++) {
  44. int x1 = ran.nextInt(width);
  45. int x2 = ran.nextInt(width);
  46. int y1 = ran.nextInt(height);
  47. int y2 = ran.nextInt(height);
  48. g.drawLine(x1,y1,x2,y2);
  49. }
  50. // 3.将图片输出到页面展示
  51. ImageIO.write(image,"jpg",response.getOutputStream());
  52. }
  53. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  54. this.doPost(request,response);
  55. }
  56. }
  57. 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

代码效果如下,重新加载会呈现不同的验证码:

Response - 图7学习完了使用代码的方式来实现验证码,接下来,说一下真正将来在程序开发过程中如何使用验证码,当然不是在页面上显示一个验证码,是配合注册表单一起来显示验证码。(只能是一张图片)

接下来说一下验证码切换效果
我们写一个HTML页面,代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script>
  7. /*
  8. 分析:
  9. 点击超链接或者图片,需要换一张
  10. 1.给超链接和图片绑定单击事件
  11. 2.重新设置图片的src属性值
  12. */
  13. window.onload = function () {
  14. // 1.获取图片对象
  15. let img = document.getElementById("checkCode");
  16. // 2.绑定单击事件
  17. img.onclick = function () {
  18. // 加时间戳
  19. var date = new Date().getTime();
  20. img.src = "/day15/checkCodeServlet?" + date;
  21. }
  22. }
  23. </script>
  24. </head>
  25. <body>
  26. <img id="checkCode" src="/day15/checkCodeServlet" alt="">
  27. <a id="change" href="">看不清换一张?</a>
  28. </body>
  29. </html>
  30. 123456789101112131415161718192021222324252627282930