• Http协议


    目录

    为什么引入Http协议

    HTTP的发展 

     HTTP协议流程

    请求格式中携带的信息有哪些

     响应格式的信息有哪些

    HTTP举例

    认识 URL  

    基本格式

    URL 中的可省略部分

    URL内容的要求

    动态资源

    HTTP方法


    为什么引入Http协议

    • web应用中的基本单位是web资源,但是web资源是分布在网络中的任意主机上,所以本机的浏览器想要获取这些web资源,必须通过一种网络协议来实现——Http协议 
    • Hyper 超Text 文本 Transer传输 Protocol协议
    • HTTP协议的是以web资源为基本单位,每次请求也是针对一个web资源进行
    • Http协议设计之初,是为传输超文本,HTML的前身,随着互联网的发展,HTTP协议传输的不仅仅是超文本,目前其实任意类型都是可以的,其前端三剑客的主流,但是其他多媒体资源也是可以的

    HTTP的发展 

    • HTTP协议是一套应用层协议,(一开始是专注于业务,但现在HTTP协议本身也成为了基础的协议之一了),所以HTTP协议必须在一套传输层协议(TCP UDP)的基础上进行传输,
    • HTTP在1.0,1.1.,2.0是基于TCP协议进行工作,HTTP本身没有做什么可靠性的服务,必须依靠传输层的可靠性(我们从HTTP1.0,1.1协议)
    • HTTP在3.0之后,开始基于UDP协议进行,(HTTP协议内部自己完成了可靠性的工作)

     HTTP协议流程

    一次完整的HTTP分为

    1. 请求 客户端发起  服务器接收
    2. 响应 客户端接收  服务器发起

    所以对应着两种格式:请求格式,响应格式

    请求格式中携带的信息有哪些

    • 访问的是那个web资源(URL来标识)
    • 当前获取的这个资源的内容(还是将用户的输入提交到资源上,不同的请求方法来表明)
    • 本次采用的是那个HTTP协议(请求行带有协议的版本号)
    • 本次请求的一些描述信息(请求头)
    • 如果本次是要提交信息给服务器,这些信息也得携带

    例子

     响应格式的信息有哪些

    • 本次响应的版本号(响应行带有版本号)
    • 本次响应的结果(响应行带有状态)
    • 本次响应的一些描述信息(响应头)
    • 返回给请求方的资源(响应体)

    为什么 HTTP 报文中要存在 "空行"?
    • 因为 HTTP 协议并没有规定报头部分的键值对有多少个. 空行就相当于是 "报头的结束标记", 或者 是 "报头和正文之间的分隔符".
    • HTTP 在传输层依赖 TCP 协议, TCP 是面向字节流的. 如果没有这个空行, 就会出现 "粘包问题".

    HTTP举例

    自己写的HTTP协议

    1. package com.lsc.demo;
    2. import java.io.IOException;
    3. import java.io.InputStream;
    4. import java.io.OutputStream;
    5. import java.net.Socket;
    6. import java.net.UnknownHostException;
    7. import java.nio.charset.StandardCharsets;
    8. import java.util.Scanner;
    9. public class MyHttpClient {
    10. public static void main(String[] args) throws Exception {
    11. // 只能进行一次请求-响应的 HTTP 客户端
    12. // 主机 127.0.0.1
    13. // 端口(进程) 8080
    14. // 资源路径 /hello.html
    15. try (Socket socket = new Socket("127.0.0.1", 8080)) {
    16. // 准备 HTTP 请求内容
    17. // 文本 String
    18. // 格式:请求行
    19. String requestLine = "GET /hello.html HTTP/1.0\r\n";
    20. // 请求头:完全可以没有,但必须一个空行结尾
    21. String requestHeader1 = "Name: peixinchen\r\n\r\n"; // 请求头中共有 1对 key-value
    22. String requestHeader2 = "Name: peixinchen\r\nAge: 1993\r\n\r\n"; // 请求头中共有 2对 key-value
    23. String requestHeader3 = "\r\n"; // 请求头中共有 0 对 key-value
    24. // 请求体,GET 是没有请求体
    25. // 最终的请求 —— 要发送给服务器的东西
    26. String request = requestLine + requestHeader3;
    27. // 发送服务器的过程
    28. byte[] requestBytes = request.getBytes("ISO-8859-1"); // 字符集编码
    29. // 发送(数据会经由 TCP、IP、以太网发送给服务器)
    30. OutputStream os = socket.getOutputStream();
    31. os.write(requestBytes);
    32. os.flush();
    33. // 请求既然已经发送,我们要做的就是等待响应
    34. InputStream is = socket.getInputStream();
    35. Scanner scanner = new Scanner(is, "UTF-8"); // 响应的前面字符集应该是 ISO-8859-1,后边是 UTF-8
    36. while (scanner.hasNextLine()) {
    37. String line = scanner.nextLine();
    38. System.out.println(line);
    39. }
    40. }
    41. }
    42. }

    自己写的服务器

    1. package com.lsc.demo;
    2. import java.io.IOException;
    3. import java.io.OutputStream;
    4. import java.net.ServerSocket;
    5. import java.net.Socket;
    6. import java.nio.charset.StandardCharsets;
    7. public class MyHttpServer {
    8. public static void main(String[] args) throws IOException {
    9. try (ServerSocket serverSocket=new ServerSocket(8080)){
    10. while (true){
    11. Socket socket=serverSocket.accept();//三次握手建立结束
    12. // 读取用户的请求 这里就不具体读了,一律采用相同的方式回应
    13. //发送响应 响应体 资源内容
    14. // Content-Type: 浏览器应该按照什么格式来看到我们响应的资源内容的(资源内容放在响应体中)
    15. //响应体的资源
    16. String responseBody="

      Welcome MyHttpServer

      "
      ;
    17. byte[] responseBodyBytes=responseBody.getBytes(StandardCharsets.UTF_8);
    18. int contentLength=responseBody.length();
    19. String response="HTTP/1.0 200 OK \r\n"
    20. +"Sever: lsc\r\n"
    21. +"ContentType: text/html; charset=utf-8\r\n"
    22. +"ContentLength:"+contentLength+"\r\n"
    23. +"\r\n";
    24. byte[] responseBytes=response.getBytes("ISO-8859-1");
    25. OutputStream os=socket.getOutputStream();
    26. os.write(responseBytes);
    27. os.write(responseBodyBytes);
    28. os.flush();
    29. //发送完毕之和,直接关闭TCP连接
    30. socket.close();
    31. }
    32. }
    33. }
    34. }

    我们自己写的服务器的信息

    认识 URL  

    基本格式

    • 作用:平时我们俗称的 "网址" 其实就是说的 URL (Uniform Resource Locator 统一资源定位符). 互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它.

    • https : 协议方案名. 常见的有 http https, 也有其他的类型. (例如访问 mysql 时用的jdbc:mysql ),换句话说,URL不仅仅针对HTTP协议设计的,网络中是所有资源都可以用URL来命名 ftp://协议,文件传输协议 
    • user:pass : 登陆信息. 现在的网站进行身份认证一般不再通过 URL 进行了. 一般都会省略
    • www.example.jp: 服务器地址 . 此处是一个 " 域名 ", 域名会通过 DNS 系统解析成一个具体的 IP 地址 . (通过 ping 命令可以看到 ),通过IP来确定处于网络中的那台主机
    • 端口号 : 端口号来确定资源是由服务器的那个进程提供的 . 当端口号省略的时候 , 浏览器会根据协议类型自动决定使用 哪个端口. 例如 http 协议默认使用 80 端口 , https 协议默认使用 443 端口
    • /dir/index.html: 带层次的文件路径. 因为即便是同一个进程,也会管理着多个资源,所以需要通过路径确定
    •  uid=100: 查询字符串(query string). 本质是一个键值对结构. 键值对之间使用& 分隔. 键和值之间使用 = 分隔.其形式是?name1=v1&name=v2
    • 片段标识: URL 中省略了片段标识. 片段标识主要用于页面内跳转.

    URI和URL的区别

    • URL是唯一资源路径
    • URI是唯一的资源标识符,URL是URI的子集

    URL 中的可省略部分

    • 协议名: 可以省略, 省略后默认为 http://
    • ip 地址 / 域名: HTML 中可以省略(比如 img, link, script, a 标签的 src 或者 href 属性). 略后表示服务器的 ip / 域名与当前 HTML 所属的 ip / 域名一致.
    • 端口号: 可以省略. 省略后如果是 http 协议, 端口号自动设为 80; 如果是 https 协议, 端口号自动设为 443.
    • 带层次的文件路径: 可以省略. 省略后相当于 / . 有些服务器会在发现 / 路径的时候自动访问 /index.html
    • 查询字符串: 可以省略
    • 片段标识: 可以省略

    情景一

     情景二通过资源来引用另一个资源

    •  /dir/world.html表示的是绝对路径,以static为根目录
    • ./chengoeixin.html相对路径,以当前文件所在的目录为根目录./表示就是当前文件目录java,../表示当前文件目录的父级目录

    URL内容的要求

    • URL中的字符是有一定的要求,出现在URL中的字符必须在一个特顶的集合中,比如汉字这种都有不允许出现在URL中的,但是如果想在URL中携带这些非标准的字符,就需要通过URL编码,将其转换为标准字符集

    URL编码的大体规则

    • 并且有些字符有着特顶的用途,?# & /都有其标准的含义的

    动态资源

    • 表示动态资源要接收两个参数 name值放到String name 变量中
    • required=false,表示可以不传,默认值为null

    基于SSM进行的Web开发

    • SSM SpringBoot+SpringMVC+Mybatis组合形成的一套框架。是为了方便的进行Web开发,会大量使用注解进行代码标注
    • SpringBoot 提供了loC功能(DI服务)
    • SpringMVC:提供了Web开发的能力
    • Mybatis提供了比直接使用JDBC进入另一种编程范式中

    几个Spring常用的注解

    • @Controller :表示这个类可以作为动态资源的承载容器存在,具体的动态资源是Java方法实现

    • 被这几个注解其中的一个修饰的方法(并且存在于@Controller修饰的类中),会被作为一个动态资源存在,资源的最终的URL路径就是注解中标注的这个路径 
    • 如果存在路径完全相同的两个动态资源,则服务器就会启动失败,因为违法了URL是资源的唯一标识符

    @ResponseBody

    • 响应体,这个注解修饰方法的,表示该方法完整地返回整个响应体的内容,
    • 方法返回的String类型的值,会被当成HTTP的响应的响应体,然后及那个HTTP协议,传递给客户端(浏览器),内容格式类型,默认采用text/html(HTML的格式体现)
    • 响应体就是

      ....

      ,默认的格式是HTML格式在网页显示 

    总结

    1. @Controller创建一个类
    2. @RequestMapping/@GetMapping/@PostMapping来修饰一个方法并且带上唯一的资源路径(绝对路径)
    3. 方法返回值类型是String,无形成
    4. @ResponseBody修饰方法
    5. 返回HTML内容

    HTTP方法

    1. 利用表单
      ,from表单的提交浏览器会使用post方法,如果默认不写,其就是GET
    2. 使用JS发起HTTP请求(一般称为ajax)

    关于form表单发起POST

     img标签的自动请求

     a标签的点击之后请求

    使用JavaScripts来发起请求 

    1. //1实例化一个XMLHttpRequest对象
    2. var xhr=new XMLHttpRequest()
    3. //2调用对象的open方法, 设置发送请求的方法 资源路径
    4. xhr.open('get','/demo')
    5. //xhr.open('post,'/demo')
    6. //设置回调函数,当/demo资源响应返回的时候,应该干什么
    7. //提供事件绑定机制
    8. //事件:load事件(当响应返回的时候)
    9. //事件处理 回调函数
    10. xhr.onload=function(){
    11. console.log(xhr.status)//打印响应的状态 成功是200
    12. console.log(xhr.responseText)//打印响应的响应体
    13. //还有其他东西,现在不关心
    14. }
    15. //4真正的发送请求出去
    16. xhr.send()

    执行顺序 

     面试题 GET VS POST

    • 两个方法表示的语义不同,GET表示的是获取,POST表示的是发布
    •  表现现象不同,GET应该具有幂等性的,并且无副作用,POST应该不具备幂等性,并且有副作用,具有幂等性且无副作用的HTTP请求是可以被缓存的
    • GET请求不允许有HTTP请求体,但是POST方法请求允许有请求体(不是必须有)
    • POST稍微比GET安全一点点,对于GET数据放在URL中很容易被看到,POST放在了请求体中(两者都是不安全的),GET是通过query string中不论携带什么数据,总体上必须满足key=value的形式,但是POST非常灵活

     

    何为缓存

    • 基于性能的考虑,所以每次的请求并不是都需要服务器参加(请求服务器需要经过网络,相对来说性能耗时比较久),暂时的保留一段事件,供下次使用

     状态码

     

    • 1xx表示处于一定的流程中,基本很少见到 HTTP->WebSocket
    • 2xx表成功
    • 3xx表示重定向/缓存等操作
    • 4xx客户端导致的失败
    • 5xx服务器导致的失败
    • 200(成功) 400(请求错误,最常见的就是确实必要的参数) 405(请求的方法,该资源不支持,比如不支持方法),500(服务器错误,代码出现异常) 404(访问了不正确的资源路径)

     

    如何做到200

    • 访问正确的资源路径
    • 使用正确的方法
    • 参数必须符合

    如何做到400

    • 访问正确的资源路径
    • 访问正确的方法
    • 由于客户端的错误,可能是用户没有按照资源的要求来

    如何做到404

    • 访问不正确的资源路径

    如何做到405

    • 资源路径正确,但是访问的HTTP方法不正确

    如何做到500

    • 服务器出现异常,服务器的代码出现了问题

    重定向问题 

     站内和站外重定向

     

    永久重定向和临时重定向

    • 永久重定向的意思就是我去买石头记,说石头记以后都没有,要买就买红楼梦了,永久重定向的状态码是301,用的非常少
    • 临时重定向的意思,这几天没有了石头记,先买红楼梦,以后再买石头记就可以直接买302

    临时重定向的继续划分

     发送请求的方式根重定向的联系

     

     转发

     

  • 相关阅读:
    python机器学习与深度学习在气象领域中的实践技术应用
    【idea】查看类或方法中的实现
    进阶版JavaScript学习-第三期
    监控与运维,主流it运维监控工具
    C++——异常
    权限系统设计
    C++PrimerPlus 第七章 函数-C++的编程模块-7.5 函数和C-风格字符串
    javavue基层社区管理服务网计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    鸿蒙ArkUI-X跨端应用开发,一套代码构建多平台应用
    第一届电子纸产业创新应用论坛
  • 原文地址:https://blog.csdn.net/qq_50985215/article/details/126274592