• Servlet | HTTP协议、模板方法设计模式


    目录

    一:HTTP协议概述

    二:HTTP协议实操

    三:模板方法设计模式 


    一:HTTP协议概述

    • 什么是协议?

      • 协议实际上是某些人,或者某些组织提前制定好的一套规范、一套标准。

    • 什么是HTTP协议?

      • HTTP协议:是W3C制定的一种超文本传输协议。(通信协议:发送消息的模板提前被制定好)

      • W3C:万维网联盟组织

        • 负责制定标准的,例如:HTTP HTML4.0 HTML5 XML DOM等规范都是W3C制定的。

        • 万维网之父:蒂姆·伯纳斯·李

      • 什么是超文本

        • 超文本说的就是不是普通文本,比如流媒体:声音、视频、图片等。

        • HTTP协议支持:不但可以传送普通字符串,同样支持传递声音、视频、图片等流媒体信息。

      • 这种协议游走在B和S之间;B向S发数据要遵循HTTP协议,S向B发数据同样需要遵循HTTP协议;这样B和S才能解耦合(B不依赖S,S也不依赖B)。

      • B/S表示:B/S结构的系统(浏览器访问WEB服务器的系统)

      • 浏览器 向 WEB服务器发送数据,叫做:请求(request)

      • WEB服务器 向 浏览器发送数据,叫做:响应(response)

      • HTTP协议包括:

        • 请求协议

          • 浏览器 向 WEB服务器发送数据的时候,这个发送的数据需要遵循一套标准,这套标准中规定了发送的数据具体格式。

        • 响应协议

          • WEB服务器 向 浏览器发送数据的时候,这个发送的数据需要遵循一套标准,这套标准中规定了发送的数据具体格式。

          • HTTP协议就是提前制定好的一种消息模板。浏览器不依赖具体的服务器品牌,WEB服务器也不依赖具体的浏览器品牌。 

    二:HTTP协议实操

    定义两个类实现GenericServlet

    1. package com.bjpowernode.javaweb.servlet;
    2. import javax.servlet.GenericServlet;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.ServletRequest;
    5. import javax.servlet.ServletResponse;
    6. import java.io.IOException;
    7. import java.io.PrintWriter;
    8. public class GetServlet extends GenericServlet {
    9. @Override
    10. public void service(ServletRequest request, ServletResponse response)
    11. throws ServletException, IOException {
    12. // 设置响应的类型
    13. response.setContentType("text/html");
    14. // 打印到浏览器上
    15. PrintWriter out = response.getWriter();
    16. // out.println() 是输出信息到浏览器,最终源代码中换行。
    17. // (不是网页上有换行效果,网页上有换行效果必须使用
    18. out.println("");
    19. out.println("");
    20. out.println(" ");
    21. out.println(" from get servlet");
    22. out.println(" ");
    23. out.println(" ");
    24. out.println("

      from post servlet

      "
      );
    25. out.println(" ");
    26. out.println("");
    27. }
    28. }
    1. package com.bjpowernode.javaweb.servlet;
    2. import javax.servlet.GenericServlet;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.ServletRequest;
    5. import javax.servlet.ServletResponse;
    6. import java.io.IOException;
    7. import java.io.PrintWriter;
    8. public class PostServlet extends GenericServlet {
    9. @Override
    10. public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
    11. // 设置响应的类型
    12. response.setContentType("text/html");
    13. // 打印到浏览器上
    14. PrintWriter out = response.getWriter();
    15. // out.println() 是输出信息到浏览器,最终源代码中换行。
    16. // (不是网页上有换行效果,网页上有换行效果必须使用
    17. out.println("");
    18. out.println("");
    19. out.println(" ");
    20. out.println(" from post servlet");
    21. out.println(" ");
    22. out.println(" ");
    23. out.println("

      from post servlet

      "
      );
    24. out.println(" ");
    25. out.println("");
    26. }
    27. }

     编写web.xml配置文件

    1. "1.0" encoding="UTF-8"?>
    2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    5. version="4.0">
    6. <servlet>
    7. <servlet-name>getservlet-name>
    8. <servlet-class>com.bjpowernode.javaweb.servlet.GetServletservlet-class>
    9. servlet>
    10. <servlet-mapping>
    11. <servlet-name>getservlet-name>
    12. <url-pattern>/getServleturl-pattern>
    13. servlet-mapping>
    14. <servlet>
    15. <servlet-name>postservlet-name>
    16. <servlet-class>com.bjpowernode.javaweb.servlet.PostServletservlet-class>
    17. servlet>
    18. <servlet-mapping>
    19. <servlet-name>postservlet-name>
    20. <url-pattern>/postServleturl-pattern>
    21. servlet-mapping>
    22. web-app>

    编写一个index.html文件,里面定义两个表单:一个get请求的表单、一个post请求的表单

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>http协议title>
    6. head>
    7. <body>
    8. <h1>get请求h1>
    9. <form action = "/servlet05/getServlet" method="get">
    10. username<input type="text" name="username" /><br>
    11. password<input type="password" name="userpwd" /><br>
    12. <input type="submit" value="login">
    13. form>
    14. <h1>post请求h1>
    15. <form action = "/servlet05/postServlet" method="post">
    16. username<input type="text" name="username" /><br>
    17. password<input type="password" name="userpwd" /><br>
    18. <input type="submit" value="login">
    19. form>
    20. body>
    21. html>

     

    1、HTTP的请求协议(B --> S)

    • HTTP的请求协议包括:4部分

      • 请求行

      • 请求头

      • 空白行

      • 请求体

    HTTP请求协议的具体报文:GET请求

    1. GET /servlet05/getServlet?username=jack&userpwd=123 HTTP/1.1 请求行
    2. Host: localhost:8080 请求头
    3. Connection: keep-alive
    4. Cache-Control: max-age=0
    5. Upgrade-Insecure-Requests: 1
    6. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
    7. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    8. Sec-Fetch-Site: none
    9. Sec-Fetch-Mode: navigate
    10. Sec-Fetch-User: ?1
    11. Sec-Fetch-Dest: document
    12. Accept-Encoding: gzip, deflate, br
    13. Accept-Language: zh-CN,zh;q=0.9
    14. 空白行
    15. 请求体

    HTTP请求协议的具体报文:POST请求

    1. POST /servlet05/postServlet HTTP/1.1 请求行
    2. Host: localhost:8080 请求头
    3. Connection: keep-alive
    4. Content-Length: 29
    5. Cache-Control: max-age=0
    6. Upgrade-Insecure-Requests: 1
    7. Origin: http://localhost:8080
    8. Content-Type: application/x-www-form-urlencoded
    9. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
    10. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    11. Sec-Fetch-Site: same-origin
    12. Sec-Fetch-Mode: navigate
    13. Sec-Fetch-User: ?1
    14. Sec-Fetch-Dest: document
    15. Referer: http://localhost:8080/servlet05/index.html
    16. Accept-Encoding: gzip, deflate, br
    17. Accept-Language: zh-CN,zh;q=0.9
    18. 空白行
    19. username=zhangsan&userpwd=123 请求体

    ①请求行(包括三部分): 

    • 第一部分:请求方式(7种)

      • get(常用)

      • post(常用)

      • delete

      • put

      • head

      • options

      • trace

    • 第二部分:URI

      • 什么是URI统一资源标识符。代表网络中某个资源的名字。但是通过URI是无法定位资源的

      • 什么是URL统一资源定位符。代表网络中某个资源,同时,通过URL是可以定位到该资源的

      • URI和URL什么关系,有什么区别?

    • 第三部分:HTTP协议版本号

    ②请求头

    • 请求的主机

    • 主机的端口

    • 浏览器信息

    • 平台信息

    • cookie等信息

    • ....

    ③空白行

    • 空白行是用来区分“请求头”和“请求体”

    ④请求体

    • 向服务器发送的具体数据。 

    2、HTTP的响应协议(S --> B)

    • HTTP的响应协议包括:4部分

      • 状态行

      • 响应头

      • 空白行

      • 响应体

    • HTTP响应协议的具体报文:

    1. HTTP/1.1 200 ok 状态行
    2. Content-Type: text/html;charset=UTF-8 响应头
    3. Content-Length: 32
    4. Date: Sat, 05 Nov 2022 08:12:19 GMT
    5. Keep-Alive: timeout=20
    6. Connection: keep-alive
    7. 空白行
    8. html> 响应体
    9. <html>
    10. <head>
    11. <title>from post servlettitle>
    12. head>
    13. <body>
    14. <h1>from get servleth1>
    15. body>
    16. html>

    ①状态行(由三部分组成): 

    • 第一部分:协议版本号(HTTP/1.1)

    • 第二部分:状态码(HTTP协议中规定的响应状态号,不同的响应结果对应不同的号码)。

      • 以4开始的,一般是浏览器端的错误导致的。

      • 以5开始的,一般是服务器端的错误导致的。

      • 500表示服务器端的程序出现了异常。例如:没有无参构造方法,无法创建对象  

      • 405表示前端发送的请求方式与后端请求的处理方式不一致时发生,例如:

        • 前端是POST请求,后端的处理方式按照get方式进行处理时,发生405

      • 404表示访问的资源不存在,通常是因为路径写错了,或者是路径写对了,但是服务器中对应的资源并没有启动成功。总之404错误是前端错误!

      • 200 表示请求响应成功,正常结束。

    • 第三部分:状态的描述信息

      • ok 表示正常成功结束。

      • not found 表示资源找不到。

    ②响应头(了解): 

    • 响应的内容类型

    • 响应的内容长度

    • 响应的时间

    • ....

    ③空白行:

    • 用来分隔“响应头”和“响应体”的。

    ④响应体:

    • 响应体就是响应的正文,这些内容是一个长的字符串,这个字符串被浏览器渲染,解释并执行,最终展示出效果。

    3、怎么查看的协议内容?

    使用chrome浏览器:F12。然后找到network,通过这个面板可以查看协议的具体内容。

    4、怎么向服务器发送GET请求,怎么向服务器发送POST请求?  

    • 到目前为止,只有一种情况可以发送POST请求:使用form表单,并且form标签中的method属性值为:method="post"。

    • 其他所有情况一律都是get请求:

      • 在浏览器地址栏上直接输入URL,敲回车,属于get请求。

      • 在浏览器上直接点击超链接,属于get请求。

      • 使用form表单提交数据时,form标签中没有写method属性,默认就是get

      • 或者使用form的时候,form标签中method属性值为:method="get"

    5、 GET请求和POST请求有什么区别?(重点)

    • get请求发送数据的时候,数据会挂在URI的后面,并且在URI后面添加一个“?”,"?"后面是数据。这样会导致发送的数据回显在浏览器的地址栏上。(get请求在“请求行”上发送数据

    • post请求发送数据的时候,在请求体当中发送。不会回显到浏览器的地址栏上也就是说post发送的数据,在浏览器地址栏上看不到。(post在“请求体”当中发送数据

    • get请求只能发送普通的字符串。并且发送的字符串长度有限制,不同的浏览器限制不同。

    • post请求可以发送任何类型的数据,包括普通字符串,流媒体等信息:视频、声音、图片,理论上没有长度限制

    • get请求无法发送大数据量,post请求可以发送大数据量。

    • get请求比较适合从服务器端获取数据,post请求比较适合向服务器端传送数据。

    • get请求是安全的。get请求是绝对安全的。为什么?因为get请求只是为了从服务器上获取数据,不会对服务器造成威胁。

    • post请求是危险的。为什么?因为post请求是向服务器提交数据,如果这些数据通过后门的方式进入到服务器当中,服务器是很危险的。另外post是为了提交数据,所以一般情况下拦截请求的时候,大部分会选择拦截(监听)post请求。 

    • get请求支持缓存。

      • 任何一个get请求最终的“响应结果”都会被浏览器缓存起来。

      • 在浏览器缓存当中:一个get请求的路径 对应 一个资源。

      • 实际上,你只要发送get请求,浏览器做的第一件事都是先从本地浏览器缓存中找,找不到的时候才会去服务器上获取。这种缓存机制目的是为了提高用户的体验。

      • 有没有这样一个需求:我们不希望get请求走缓存,怎么办?怎么避免走缓存?我希望每一次这个get请求都去服务器上找资源,我不想从本地浏览器的缓存中取。

        • 只要每一次get请求的请求路径不同即可。

        • 怎么解决?可以在

        • 路径的后面添加一个每时每刻都在变化的“时间戳”,这样,每一次的请求路径都不一样,浏览器就不走缓存了。

    • post请求不支持缓存。(POST是用来修改服务器端的资源的。)

      • post请求之后,服务器“响应的结果”不会被浏览器缓存起来。因为这个缓存没有意义。

    6、GET请求和POST请求如何选择,什么时候使用GET请求,什么时候使用POST请求?

    • 怎么选择GET请求和POST请求呢?衡量标准是什么呢?

      • 看这个请求是想获取服务器端的数据,还是想向服务器发送数据。

      • 如果你是想从服务器上获取资源,建议使用GET请求,

      • 如果你这个请求是为了向服务器提交数据,建议使用POST请求。

    • 大部分的form表单提交,都是post方式,因为form表单中要填写大量的数据,这些数据是收集用户的信息,一般是需要传给服务器,服务器将这些数据保存/修改等。

    • 如果表单中有敏感信息,还是建议适用post请求,因为get请求会回显敏感信息到浏览器地址栏上。(例如:密码信息)

    • 做文件上传,一定是post请求,要传的数据不是普通文本。

    • 其他情况都可以使用get请求。

    7、不管是get请求还是post请求,发送的请求数据格式是完全相同的,只不过位置不同,格式都是统一的

    • 格式:name=value&name=value&name=value&name=value

    • name是什么?

      • 以form表单为例:form表单中输入域input标签的name属性。

    • value是什么?

      • 以form表单为例:form表单中输入域input标签的value属性。

    三:模板方法设计模式 

    • 什么是设计模式?

      • 某个问题的固定的解决方案。(可以被重复使用。)

    • 有哪些设计模式?

      • GoF设计模式:通常我们所说的23种设计模式。(Gang of Four:4人组提出的设计模式)

        • 单例模式

        • 工厂模式

        • 代理模式

        • 门面模式

        • 责任链设计模式

        • 观察者模式

        • 模板方法设计模式

        • .....

      • JavaEE设计模式:

        • DAO

        • DTO

        • VO

        • PO

        • pojo

        • ....

      • ....

    • 什么是模板方法设计模式?

      • 在模板类的模板方法当中定义核心算法骨架,具体的实现步骤可以延迟到子类当中完成。

      • 模板类通常是一个抽象类模板类当中的模板方法定义核心算法,这个方法通常是final的(但也可以不是final的)

      • 模板类当中的抽象方法就是不确定实现的方法,这个不确定怎么实现的事交给子类去做。

    例1:定义两个Student类和Teacher类,其它方法都相同,只有doSome()方法不同

    存在的问题:

            第一:算法没有得到重复的使用。
            第二:代码没有得到复用。

    Student类

    1. package com.bjpowernode.template1;
    2. public class Student {
    3. //这个方法描述学生的一天
    4. public void day(){
    5. // 和Teacher的算法相同。
    6. qiChuang();
    7. xiShu();
    8. chiZaoCan();
    9. doSome();
    10. chiWanFan();
    11. shuiJiao();
    12. }
    13. public void qiChuang(){
    14. System.out.println("起床");
    15. }
    16. public void xiShu(){
    17. System.out.println("洗漱");
    18. }
    19. public void chiZaoCan(){
    20. System.out.println("吃早餐");
    21. }
    22. // 只有doSome()方法不同
    23. public void doSome(){
    24. System.out.println("学生上学,学习");
    25. }
    26. public void chiWanFan(){
    27. System.out.println("吃晚饭");
    28. }
    29. public void shuiJiao(){
    30. System.out.println("睡觉");
    31. }
    32. }

    Teacher类 

    1. package com.bjpowernode.template1;
    2. public class Teacher {
    3. // 这个方法描述老师的一天
    4. public void day(){
    5. // 和Student的算法相同。
    6. qiChuang();
    7. xiShu();
    8. chiZaoCan();
    9. doSome();
    10. chiWanFan();
    11. shuiJiao();
    12. }
    13. public void qiChuang(){
    14. System.out.println("起床");
    15. }
    16. public void xiShu(){
    17. System.out.println("洗漱");
    18. }
    19. public void chiZaoCan(){
    20. System.out.println("吃早餐");
    21. }
    22. // 只有这个方法不同
    23. public void doSome(){
    24. System.out.println("老师正在课堂上授课,教授学生知识");
    25. }
    26. public void chiWanFan(){
    27. System.out.println("吃晚饭");
    28. }
    29. public void shuiJiao(){
    30. System.out.println("睡觉");
    31. }
    32. }

    例2:使用模板方法设计模式进行优化

     Teacher和Student都是Person
            第一:Person就是模板方法设计模式当中的模板类。
            第二: day()方法就是模板方法设计模式当中的模板方法。

    模板类Person类

    1. package com.bjpowernode.template2;
    2. public abstract class Person { // 模板类通常是抽象类。
    3. // 模板方法
    4. // 添加了final之后,这个方法无法被覆盖,这样核心的算法也可以得到保护。
    5. // 模板方法定义核心的算法骨架,具体的实现步骤可以延迟到子类当中去实现。
    6. // 核心算法一方面是得到了保护,不能被改变。另外一方面就是算法得到了重复使用。
    7. // 另外代码也得到了复用,因为算法中某些步骤的代码是固定的。这些固定的代码不会随着子类的变化而变换,这一部分代码可以写到模板类当中。
    8. public final void day(){
    9. // 第一步
    10. qiChuang();
    11. // 第二步
    12. xiShu();
    13. // 第三步
    14. chiZaoCan();
    15. // 第四步
    16. doSome();
    17. // 第五步
    18. chiWanFan();
    19. // 第六步
    20. shuiJiao();
    21. }
    22. // 其中的某些步骤,不会随着子类的变化而变化,这些代码可以写到父类中,得到代码复用。
    23. public void qiChuang(){
    24. System.out.println("起床");
    25. }
    26. public void xiShu(){
    27. System.out.println("洗漱");
    28. }
    29. public void chiZaoCan(){
    30. System.out.println("吃早餐");
    31. }
    32. // 写成抽象方法:这一步是要做,但是具体这一步怎么做,子类说了算。
    33. public abstract void doSome();
    34. public void chiWanFan(){
    35. System.out.println("吃晚饭");
    36. }
    37. public void shuiJiao(){
    38. System.out.println("睡觉");
    39. }
    40. }

    Student类继承Person类

    1. package com.bjpowernode.template2;
    2. public class Student extends Person {
    3. public void doSome(){
    4. System.out.println("学生上学,学习");
    5. }
    6. }

    Teacher类继承Person类

    1. package com.bjpowernode.template2;
    2. public class Teacher extends Person{
    3. public void doSome(){
    4. System.out.println("老师正在课堂上授课,教授学生知识");
    5. }
    6. }

    Test类进行测试调用

    1. package com.bjpowernode.template2;
    2. public class Test {
    3. public static void main(String[] args) {
    4. // 实用多态
    5. Person p1 = new Teacher();
    6. p1.day();
    7. System.out.println("-----------------");
    8. Person p2 = new Student();
    9. p2.day();
    10. }
    11. }

  • 相关阅读:
    windows查看并关闭端口对应进程占用的命令
    题目 1924: 蓝桥杯-01背包
    【面试题】JS使用parseInt()、正则截取字符串中数字
    设计模式 -- 策略模式(Strategy Pattern)
    痞子衡嵌入式:MCUXpresso IDE下高度灵活的FreeMarker链接文件模板机制
    C++异常
    10分钟搞定manim安装与vscode配置
    7个技巧帮助你进行更有吸引力的脉动/脉搏调查
    访问共享故障解决方法
    全网最详细的下载、安装和使用绘图神器draw.io(drawio),它比visio,processon,wps,亿图图示等更好用,最重要的是它免费
  • 原文地址:https://blog.csdn.net/m0_61933976/article/details/127703419