Skip to content

SpringMVC教程 - 3 HTTP协议介绍

下面简单介绍一下 HTTP 协议的一些内容,帮助我们理解 HTTP 发送数据和返回数据的格式。

HTTP 协议包括请求协议和响应协议,也就是规定了请求服务器的数据格式、服务器返回的数据格式。


我们使用最多的发起 HTTP 的方式,就是通过浏览器浏览网页,打开浏览器的开发者工具,我们可以看到每个请求的详细信息。

举个栗子:

下面我们就来详细介绍一下 HTTP 请求协议的格式。

3.1 请求协议

我们在发起网络请求的时候,请求的格式大概如下:

http
POST /users HTTP/1.1                               ← ① 请求行
Host: example.com                                  ← ② 请求头,下面多行都是
Content-Type: application/json
Content-Length: 47
                                                   ← ③ 空白行
{"username": "foooor", "password": "123456"}       ← ④ 请求体

内容分为下面四个部分:

  • 请求行(POST /users HTTP/1.1
  • 请求头(Content-Type 等),请求头有很多,是 key-value 形式;
  • 空白行,Header 与 Body 之间的分隔符;
  • 请求体({"username": "foooor", "password": "123456"}),请求体有不同的格式,请求体的格式 是由请求头中的 Content-Type 指定的。

3.2 响应协议

当浏览器或客户端发送请求到服务器后,服务器会返回响应,响应的格式与请求类似,也分为几个部分:

http
HTTP/1.1 200 OK                                    ← ① 响应行
Content-Type: application/json; charset=utf-8      ← ② 响应头(下面多行都是 key-value 形式)
Content-Length: 35
Server: Apache/2.4.41 (Ubuntu)
                                                    ← ③ 空白行
{"message": "User created", "id": 1}                ← ④ 响应体

响应也分为下面四个部分:

  • 响应行HTTP/1.1 200 OK):包含协议版本、状态码、状态描述。
  • 响应头:如 Content-TypeServerSet-Cookie 等,用来说明返回信息的格式、长度、服务器信息等。
  • 空白行:用于分隔响应头和响应体。
  • 响应体:服务器返回的真实数据,可能是 JSON、HTML、文件等。

常见状态码:

状态码描述
200 OK请求成功
201 Created创建资源成功
400 Bad Request请求参数错误
401 Unauthorized未授权
404 Not Found资源不存在
500 Internal Server Error服务器错误

3.3 请求方法

我们请求服务器最常用的两种方法就是 Get 请求和 Post 请求:

  • GET 用于从服务器获取资源,一般用于读操作;
  • POST 用于向服务器提交数据(如表单、JSON),一般用于写操作。

通过浏览器地址栏像服务器发送请求,只能发送 Get 请求,如果想发起 Post 请求,只能使用 Form 表单、JavaScript 或者一些第三方的工具(例如 Postman、Apifox )。

Get 请求和 Post 请求的主要区别如下:

特性GETPOST
参数位置参数是拼接在 URL 后面的,例如 http://www.foooor.com?userId=123&username=doubi (userId和username是参数)放在请求体中(Request Body)
参数长度受URL长度限制(不同浏览器限制不同,约2KB-8KB)理论上无限制(实际受服务器配置限制)
数据可见性明文暴露在URL中,可被浏览器历史、日志记录相对安全,参数在请求体内,不可见
书签/分享可被收藏为书签,URL包含所有参数无法直接收藏
缓存可被缓存(浏览器、CDN等)默认不可缓存
幂等性多次请求结果相同(使用Get请求不应修改数据)非幂等:多次提交可能导致重复数据

HTTP 其实定义了很多请求方法,用来告诉服务器你想对资源做什么。我们常用的是 GET、POST、PUT、DELETE,还有 HEAD、PATCH、OPTIONS 等。比如 HEAD 和 GET 很像,但它只返回响应头,常用来检查资源是否存在;其他方法知道有这个方法就可以了。

协议层面 来说,GET 和 DELETE 请求都是可以带请求体的,POST、PUT 也都可以带 URL 参数,协议本身没有做限制。只是多数浏览器和后端框架为了保持一致性,默认不会处理 GET 和 DELETE 的请求体,所以这两个方法的参数一般都会写在 URL 上;而 POST、PUT 这样的请求才会把数据放在请求体里传给服务器。

不管 GET 还是 POST,它们最终都是通过 同一个 TCP 连接 发出去的。一般来说,GET 会一次性把请求发送完;而 POST 有时候会拆成两步(先发 header,拿到服务器的 100 Continue 后再发 body),不过这只是浏览器的优化方式,不是协议规定。


3.4 常见的请求体格式

在发起和响应请求的时候,都会传递 MIME 类型,用来标识请求的消息体和响应的消息体的格式。在 HTTP 协议中,会在请求头和响应头中添加 Content-Type 来标识 MIME 类型。

也就是说在 HTTP 协议中,请求(Request)和响应(Response)都会使用 Content-Type

  • 在请求中,当浏览器或客户端发送数据给服务器时,需要通过 Content-Type 告诉服务器 请求体是什么格式,这样服务器才能正确解析。
  • 在响应中,服务器返回数据时,也必须通过 Content-Type 告诉浏览器 响应体是什么格式,浏览器会根据不同的 Content-Type 进行展示或处理响应体。

而 POST 和 PUT 请求的参数都是放在请求体中的。请求体的格式 是由请求头中的 Content-Type 指定的,下面来介绍一下常用的请求体。


1 application/x-www-form-urlencoded

这是 HTML <form> 表单的默认提交方式

举个栗子:

http
POST /login HTTP/1.1                                 ← ① 请求行
Content-Type: application/x-www-form-urlencoded      ← ② 请求头
                                                     ← ③ 空白行
username=foooor&password=123456											 ← ④ 请求体

特点:

  • 键值对形式,使用 & 连接。
  • 与 URL 查询参数(?username=kang&password=123456)几乎相同。
  • 在服务端(比如 Java Servlet、Spring、Express)中,框架能自动解析成参数对象。

2 multipart/form-data

可以用于 上传文件提交二进制数据 的表单。

举个栗子:

http
POST /upload HTTP/1.1																	← ① 请求行
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryabc123		← ② 请求头
																											← ③ 空白行
------WebKitFormBoundaryabc123												← ④ 分隔符,表示一个新的字段开始
Content-Disposition: form-data; name="username"				← ④ 这一个字段的信息,例如字段名称

foooor																								← ④ 字段的实际值
------WebKitFormBoundaryabc123												← ④ 分隔符,表示一个新的字段开始
Content-Disposition: form-data; name="file"; filename="avatar.png"		← ④ 字段信息
Content-Type: image/png																← ④ 字段信息
																											← ③ 空白行
(binary data)																					← ④ 文件的二进制内容
------WebKitFormBoundaryabc123--											← ④ 结束标志,--表示整个表单的结束

特点:

  • 请求体可以包含多个独立的字段,每个字段都有独立的边界(boundary),字段可以包含文本字段和文件。
  • 最后面的 两个连字符 -- 表示整个表单的结束,没有这两个 --,服务器会认为数据还没传完。

浏览器上传文件时通常使用这种格式,我们除了可以传递文件,同时还可以传递其他的信息。


3 application/json

用于提交 JSON 格式的数据,对于现在前后端分离的项目,一般采用这种格式提交和返回数据,我们可以封装 JSON 格式的数据,作为请求体,发送给服务器。

举个栗子:

http
POST /api/user HTTP/1.1													← ① 请求行
Content-Type: application/json									← ② 请求头
																								← ③ 空白行
{"username": "foooor", "password": "123456"}		← ④ 请求体,是JSON字符串

特点:

  • 常用于前后端分离的 Web 项目(前端用 fetch / axios 发起请求)。
  • 服务端解析 JSON 数据后再转换为对象。

4 其他比较少用的类型

Content-Type用途
text/plain纯文本数据
application/xmlXML 格式数据(SOAP、旧系统常用)
application/octet-stream二进制数据流(下载或上传文件时),整个请求体就是文件件的二进制内容,没有文件名、字段名等信息。

通过上面的介绍,可以让我们知道怎么在发起请求的时候传递数据。


3.5 常见的响应体格式

而服务器在响应时,常用的 Content-Type 类型如下:

1 text/html

用于返回 HTML 页面,浏览器会按照网页渲染。

举个栗子,服务器返回:

http
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8

<h1>Hello SpringMVC</h1>
  • 浏览器会把 <h1>Hello SpringMVC</h1> 当作网页渲染,而不是普通文本。
  • 常用于传统 Web 项目中返回 Thymeleaf、JSP 页面等,浏览器会渲染为网页。

2 application/json

用于返回 JSON 数据,前后端分离项目中一般都使用这个,application/json 可以用于请求和可以用于响应。

http
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"message": "success", "username": "foooor"}
  • 前端使用 fetchaxiosXMLHttpRequest 等发起 AJAX 请求时,通常使用 JSON 作为响应体。
  • 服务器在返回数据是,需要用 JSON 序列化框架(如 Spring 的 Jackson)将对象转换成 JSON,然后返回。

3 text/plain

表示返回 纯文本

http
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

OK
  • 只返回字符串,不带格式。
  • 在调试接口、返回简单文本消息时常用。

4 application/octet-stream

表示返回 二进制数据流,比如下载文件。

举个栗子,告诉浏览器这是一个二进制文件:

http
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="report.pdf"
  • 浏览器不会解析内容,只会弹出下载。
  • Content-Disposition 决定是否下载以及文件名。

5 image/png等

如果返回图片,会使用图片对应的 Content-Type,例如:

http
HTTP/1.1 200 OK
Content-Type: image/png
  • 浏览器会自动显示图片,
  • 常用于验证码、头像图像接口等。

3.6 通过Apifox发起HTTP请求

除了通过浏览器发起请求,我们还可以使用工具,常用的有 Postman 和 Apifox。

以下以 Apifox 为例,发起请求。

首先新建一个项目:


然后就可以在项目下创建访问接口,可以输入请求地址,选择请求方法,还可以添加请求头、请求参数、和请求体等信息:

点击发送按钮,就可以发起请求,并在下面得到响应结果。