缘博客
发布日期

HTTP协议

作者
  • 姓名
    社交账号

HTTP协议

HTTP 全称为 Hyper Text Transfer Protocol,即超文本传输协议。

它规定了浏览器和服务器之间进行数据传输时需要遵守的规则。

浏览器                         服务器
   ─────── HTTP 请求 ────────>
   <────── HTTP 响应 ─────────

浏览器发送给服务器的数据称为请求数据,服务器返回给浏览器的数据称为响应数据


HTTP协议的特点

1. 基于 TCP 协议

HTTP 基于 TCP 协议进行数据传输。TCP 是面向连接的协议,浏览器和服务器建立连接后再传输数据。

2. 基于请求—响应模型

一次请求对应一次响应,并且请求必须由客户端主动发起。

浏览器发送请求
服务器接收并处理请求
服务器返回响应

3. HTTP 是无状态协议

HTTP 对之前发生过的请求没有记忆能力,每一次请求和响应都是独立的。

例如,浏览器第一次请求服务器完成登录,第二次再请求个人信息时,仅靠 HTTP 协议本身,服务器并不知道这两个请求来自同一个已经登录的用户。

无状态的特点:

  • 优点:每次请求都可以独立处理,速度快。
  • 缺点:多次请求之间不能直接共享数据。

HTTP请求协议

HTTP 请求是浏览器发送给服务器的数据。

一份完整的 HTTP 请求由三部分组成:

  1. 请求行
  2. 请求头
  3. 请求体

例如:

POST /user/login HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

username=Tom&password=123

其中:

POST /user/login HTTP/1.1        请求行
Host: localhost:8080             请求头
User-Agent: Mozilla/5.0          请求头
Content-Type: ...                请求头
Content-Length: 27               请求头

username=Tom&password=123        请求体

请求头和请求体之间存在一个空行,用来表示请求头已经结束。


请求行

请求行位于请求数据的第一行,格式为:

请求方式 资源路径 协议版本

例如:

GET /hello?name=Tom HTTP/1.1

这三个部分分别表示:

内容说明
GET本次请求使用的请求方式
/hello?name=Tom请求的资源路径以及查询参数
HTTP/1.1使用的 HTTP 协议版本

请求头

请求头从请求数据的第二行开始,每一行都是一组键值对:

key: value

常见请求头如下:

请求头说明
Host请求的主机名和端口
User-Agent浏览器和操作系统等客户端信息
Accept浏览器能够接收的资源类型
Accept-Language浏览器偏好的语言
Accept-Encoding浏览器支持的压缩类型,例如 gzipdeflate
Content-Type请求体中数据的类型
Content-Length请求体的大小,单位为字节

例如:

Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/json
Accept-Language: zh-CN,zh
Accept-Encoding: gzip, deflate

请求体

请求体用于存放提交给服务器的数据。

它与请求头之间隔着一个空行,主要出现在带有请求数据的请求中,例如 POST 请求。

POST /user/login HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded

username=Tom&password=123

最后一行就是请求体:

username=Tom&password=123

GET与POST请求

GET请求

GET 请求通常将请求参数放在请求行的资源路径后面:

GET /brand/findAll?name=OPPO&status=1 HTTP/1.1

其中:

?name=OPPO&status=1

是查询字符串。

GET 请求的特点:

  • 请求参数位于 URL 中。
  • 通常没有请求体。
  • 浏览器会对 URL 长度进行限制,因此能够携带的数据量有限。

POST请求

POST 请求通常将请求参数放在请求体中:

POST /brand HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded

name=OPPO&status=1

POST 请求的特点:

  • 请求参数位于请求体中。
  • 参数不会直接显示在浏览器地址栏中。
  • 不受浏览器 URL 长度的限制,更适合提交较多数据。

请求数据的完整结构

GET /request?name=Tomcat&age=10 HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0
Accept: text/html
Accept-Language: zh-CN

这是一份 GET 请求:

  • 请求行:GET /request?name=Tomcat&age=10 HTTP/1.1
  • 请求头:从 Host 开始的所有键值对
  • 请求体:没有请求体

POST 请求示例:

POST /request HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Content-Length: 22

name=Tomcat&age=10

这份请求包含请求行、请求头和请求体三个部分。


获取HTTP请求数据

HTTP 请求数据不需要程序员自己按照字符串逐行解析。

Web 服务器 Tomcat 接收到请求后,会按照 HTTP 协议解析请求数据,并将解析结果封装到 HttpServletRequest 对象中。

HTTP 请求数据
Tomcat 解析请求
HttpServletRequest
Controller 方法读取请求信息

Controller 可以直接通过 HttpServletRequest 获取请求数据。

@RequestMapping("/request")
public String request(HttpServletRequest request) {
    // 获取请求参数
    String name = request.getParameter("name");

    // 获取请求路径
    String uri = request.getRequestURI();

    // 获取完整请求地址
    String url = request.getRequestURL().toString();

    // 获取请求头
    String userAgent = request.getHeader("User-Agent");

    // 获取请求方式
    String method = request.getMethod();

    // 获取查询字符串
    String queryString = request.getQueryString();

    return "request success";
}

假设浏览器访问:

http://localhost:8080/request?name=Tomcat&age=10

各方法可能得到:

方法结果
getParameter("name")Tomcat
getRequestURI()/request
getRequestURL()http://localhost:8080/request
getHeader("User-Agent")浏览器的 User-Agent 信息
getMethod()GET
getQueryString()name=Tomcat&age=10

因此,在 Java Web 开发中可以先记住:

Tomcat 负责解析 HTTP 请求,HttpServletRequest 负责封装解析后的请求信息。


HTTP响应协议

HTTP 响应是服务器处理完请求后,返回给浏览器的数据。

一份完整的 HTTP 响应由三部分组成:

  1. 响应行
  2. 响应头
  3. 响应体

例如:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 24

{"name":"Tom","age":18}

其中:

HTTP/1.1 200 OK                 响应行
Content-Type: application/json 响应头
Content-Length: 24             响应头

{"name":"Tom","age":18}        响应体

响应行

响应行是响应数据的第一行,格式为:

协议版本 状态码 状态描述

例如:

HTTP/1.1 200 OK

表示服务器使用 HTTP/1.1 协议返回响应,本次请求处理成功。


HTTP状态码

状态码用于表示服务器处理请求的结果。

分类说明
1xx响应中,表示请求已经接收,客户端可以继续后续操作
2xx成功,表示请求已经成功接收并处理完成
3xx重定向,需要客户端再次发起请求
4xx客户端错误,例如请求不存在的资源或没有访问权限
5xx服务器错误,例如服务端程序运行时抛出异常

常见状态码:

状态码说明
200 OK请求成功
404 Not Found请求的资源不存在
500 Internal Server Error服务器程序发生错误

重定向

重定向表示服务器没有直接返回最终资源,而是告诉浏览器到另一个地址重新发送请求。

浏览器请求资源 A
服务器返回 3xx,并在 Location 中指定资源 B
浏览器再次请求资源 B
服务器返回资源 B

响应示例:

HTTP/1.1 302 Found
Location: /login

浏览器收到响应后,会再次向 /login 发起请求。


响应头

响应头从响应数据的第二行开始,同样使用键值对格式:

key: value

常见响应头如下:

响应头说明
Content-Type响应体中数据的类型,例如 text/htmlapplication/json
Content-Length响应体的长度,单位为字节
Content-Encoding响应数据使用的压缩算法,例如 gzip
Cache-Control告诉浏览器如何缓存响应数据
Set-Cookie告诉浏览器设置 Cookie
Location重定向时指定新的请求地址

例如:

Content-Type: application/json
Content-Encoding: gzip
Cache-Control: max-age=300

响应体

响应体用于存放服务器真正返回的数据。

返回 HTML:

<h1>Hello Response</h1>

返回 JSON:

{
  "id": 1,
  "username": "Tom"
}

浏览器最终展示或处理的主要内容,就位于响应体中。


设置HTTP响应数据

Tomcat 会将 HTTP 响应相关操作封装到 HttpServletResponse 对象中。

程序可以通过它设置响应状态码、响应头和响应体。

使用HttpServletResponse

@RequestMapping("/response")
public void response(HttpServletResponse response) throws IOException {
    // 设置响应状态码
    response.setStatus(401);

    // 设置响应头
    response.setHeader("itheima", "itheima");

    // 设置响应体
    response.getWriter().write("<h1>Hello Response</h1>");
}

对应关系:

Java代码HTTP响应部分
response.setStatus(401)响应行中的状态码
response.setHeader(...)响应头
response.getWriter().write(...)响应体

使用ResponseEntity

Spring 还可以使用 ResponseEntity 封装完整响应:

@RequestMapping("/response")
public ResponseEntity<String> response() {
    return ResponseEntity
            .status(401)
            .header("group", "itcast")
            .body("<h1>Hello Response</h1>");
}

其中:

status(...)  设置响应状态码
header(...)  设置响应头
body(...)    设置响应体

通常情况下,程序员不需要手动设置所有响应信息。

Controller 返回普通字符串、对象或集合时,Spring Boot 和 Tomcat 会根据请求处理结果自动生成合适的响应状态码、响应头和响应体。只有存在特殊响应要求时,才需要直接使用 HttpServletResponseResponseEntity


请求与响应的整体过程

1. 浏览器按照 HTTP 格式生成请求数据
2. 浏览器将请求发送给服务器
3. Tomcat 解析请求并封装为 HttpServletRequest
4. Controller 获取请求信息并处理业务
5. 程序生成响应数据
6. Tomcat 按照 HTTP 格式将响应发送给浏览器
7. 浏览器解析响应并展示结果

核心关系:

HTTP请求  → HttpServletRequest
HTTP响应  → HttpServletResponse

HTTP 协议规定数据传输格式,Tomcat 负责解析和封装,程序员通过 Java 对象获取请求数据、设置响应数据。