云计算百科
云计算领域专业知识百科平台

HTTP 请求协议详解

HTTP 请求协议详解

Spring MVC 处理的是 HTTP 请求,理解 HTTP 请求协议的结构,才能搞清楚 @RequestParam、@RequestBody、@RequestHeader 这些注解到底在取哪部分数据。

一、HTTP 请求报文的结构

一个 HTTP 请求由四部分组成:

请求行
请求头
空行
请求体

用文本表示:

POST /api/users HTTP/1.1 ← 请求行
Host: example.com ← 请求头开始
Content-Type: application/json
Content-Length: 45
User-Agent: Mozilla/5.0
← 空行
{"name":"张三","email":"z@example.com"} ← 请求体

空行是请求头和请求体的分隔符。没有请求体时,空行之后直接结束。

二、请求行

请求行包含三部分:

GET /api/users/1?status=active HTTP/1.1

部分示例说明
请求方法 GET HTTP 方法
请求目标 /api/users/1?status=active 路径 + 查询参数
协议版本 HTTP/1.1 HTTP 版本

请求目标中的路径和查询参数

/api/users/1?status=active&page=2

  • /api/users/1 是路径部分,Spring MVC 用 @PathVariable 获取路径变量。
  • ?status=active&page=2 是查询字符串,Spring MVC 用 @RequestParam 获取。

@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id,
@RequestParam String status,
@RequestParam(defaultValue = "1") int page) { }

三、请求头

请求头是键值对,描述请求的元信息。常见的请求头:

请求头作用示例
Host 目标主机 Host: example.com
Content-Type 请求体的媒体类型 Content-Type: application/json
Content-Length 请求体长度(字节) Content-Length: 45
Accept 客户端能接受的响应类型 Accept: application/json
User-Agent 客户端信息 User-Agent: Mozilla/5.0
Cookie 客户端携带的 Cookie Cookie: sessionId=abc123
Authorization 认证信息 Authorization: Bearer xxx
Referer 请求来源页面 Referer: http://example.com/list

Spring MVC 获取请求头:

@GetMapping("/info")
public String info(@RequestHeader("User-Agent") String userAgent,
@RequestHeader(value = "X-Token", required = false) String token) {
return userAgent;
}

获取 Cookie:

@GetMapping("/cookie")
public String cookie(@CookieValue("sessionId") String sessionId) {
return sessionId;
}

四、请求体

请求体携带客户端提交的数据。GET 请求通常没有请求体,POST、PUT、PATCH 通常有。

请求体的格式由 Content-Type 决定,常见三种:

1. application/x-www-form-urlencoded

HTML 表单默认提交方式。请求体是键值对,用 & 分隔:

Content-Type: application/x-www-form-urlencoded

name=张三&email=zhangsan@example.com

Spring MVC 获取:

@PostMapping("/form")
public String form(@RequestParam String name,
@RequestParam String email) { }

或者用对象接收:

@PostMapping("/form")
public String form(User user) { }

2. multipart/form-data

文件上传使用的格式。请求体被分成多个部分,每部分有自己的头部:

Content-Type: multipart/form-data; boundary=—-WebKitFormBoundary

——WebKitFormBoundary
Content-Disposition: form-data; name="name"

张三
——WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="a.txt"
Content-Type: text/plain

文件内容
——WebKitFormBoundary–

Spring MVC 获取:

@PostMapping("/upload")
public String upload(@RequestParam String name,
@RequestParam MultipartFile file) { }

3. application/json

前后端分离项目最常用的格式。请求体是 JSON 字符串:

Content-Type: application/json

{"name":"张三","email":"zhangsan@example.com"}

Spring MVC 获取:

@PostMapping("/json")
public User json(@RequestBody User user) { }

@RequestBody 会读取整个请求体,通过 HttpMessageConverter 反序列化成对象。

五、四种参数获取方式对应关系

数据位置示例Spring MVC 注解
URL 路径中的变量 /users/1 中的 1 @PathVariable
URL 查询参数 ?status=active @RequestParam
请求头 User-Agent: xxx @RequestHeader
Cookie Cookie: sessionId=abc @CookieValue
请求体(JSON) {"name":"张三"} @RequestBody
请求体(表单) name=张三&email=… @RequestParam 或对象接收

六、GET 和 POST 在协议层面的区别

对比GETPOST
参数位置 URL 查询字符串 请求体
是否有请求体 通常没有 通常有
Content-Length 通常为 0 有值
幂等 是 否
缓存 可缓存 默认不缓存

GET 请求也可以有请求体,但 HTTP 规范不推荐,很多服务器和客户端会忽略。Spring MVC 的 @RequestBody 在 GET 请求中通常拿不到数据。

七、完整请求示例

1. 查询请求

GET /api/users?status=active&page=1 HTTP/1.1
Host: example.com
Accept: application/json
User-Agent: Mozilla/5.0

没有请求体。

2. JSON 提交请求

POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 52
Accept: application/json

{"name":"张三","email":"zhangsan@example.com"}

3. 表单提交请求

POST /api/login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30

username=admin&password=123456

4. 文件上传请求

POST /api/upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=—-Boundary

——Boundary
Content-Disposition: form-data; name="file"; filename="a.txt"
Content-Type: text/plain

文件内容
——Boundary–

八、Spring MVC 中的完整接收示例

@RestController
@RequestMapping("/api/users")
public class UserController {

// 路径变量 + 查询参数
@GetMapping("/{id}")
public User getById(@PathVariable Long id,
@RequestParam(required = false) String fields) {
return userService.getById(id);
}

// JSON 请求体
@PostMapping
public User create(@RequestBody @Valid User user) {
return userService.save(user);
}

// 表单提交
@PostMapping("/form")
public User createByForm(User user) {
return userService.save(user);
}

// 请求头
@GetMapping("/header")
public String header(@RequestHeader("User-Agent") String ua) {
return ua;
}

// Cookie
@GetMapping("/cookie")
public String cookie(@CookieValue("sessionId") String sessionId) {
return sessionId;
}

// 文件上传
@PostMapping("/upload")
public String upload(@RequestParam MultipartFile file) {
return file.getOriginalFilename();
}
}

九、常见问题

1. 415 Unsupported Media Type

请求的 Content-Type 与接口的 consumes 不匹配。比如接口声明 consumes = "application/json",但客户端发了 text/plain。

2. 400 Bad Request

请求体 JSON 格式错误,或参数类型不匹配。检查 Content-Type 是否为 application/json,JSON 是否合法。

3. @RequestBody 拿不到数据

检查请求方法是否为 POST/PUT/PATCH,Content-Type 是否为 application/json。GET 请求通常没有请求体。

4. @RequestParam 拿不到表单数据

检查 Content-Type 是否为 application/x-www-form-urlencoded。如果是 application/json,表单参数拿不到,需要用 @RequestBody。

5. 中文乱码

检查请求头 Content-Type 是否带了 charset=UTF-8,服务端编码配置是否正确。

十、总结

请求组成部分内容Spring MVC 获取方式
请求行 方法、路径、查询参数 @PathVariable、@RequestParam
请求头 元信息、认证、Cookie @RequestHeader、@CookieValue
空行 分隔符 —
请求体 表单、JSON、文件 @RequestBody、@RequestParam、MultipartFile
Content-Type请求体格式获取方式
application/x-www-form-urlencoded 键值对 @RequestParam 或对象
multipart/form-data 分段数据 MultipartFile
application/json JSON 字符串 @RequestBody

HTTP 请求协议的核心是“请求行 + 请求头 + 空行 + 请求体”四部分。路径和查询参数在请求行,元信息在请求头,业务数据在请求体。Spring MVC 的注解就是按这四部分设计的:@PathVariable 取路径,@RequestParam 取查询参数和表单,@RequestHeader 取请求头,@RequestBody 取请求体。把请求结构和注解对应起来,参数绑定就不会搞混。

赞(0)
未经允许不得转载:网硕互联帮助中心 » HTTP 请求协议详解
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!