Java-019-HTTP

HTTP协议

HTTP协议是互联网的基础协议

  • 本质上是Web前端程序和Web后端程序的通信的协议
  • 定义了前端给后端发送请求的格式
  • 同时也定义了后端解析前端发来的请求(HTTP请求)的方式
  • 使用程序语言来描述, HTTP协议给后端程序定义了一个接口

HTTP协议格式

HTTP请求格式

基本元素
  • 请求路径 — URL, 例如: https://xiedaimala.com/lives/723a04ed
  • 请求操作命令(动词): GET, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT, PATCH
  • 客户端标记 User-Agent, 值的例子: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
  • 传输的内容格式: Content-Type: application/json
  • 接收类型 Accept, 值的例子: text/plain, text/html, image/jpeg
  • Cookie: 用于传送和状态相关的信息的键值对

示例

1
2
3
4
5
6
7
8
9
10
GET /favicon.ico HTTP/1.1
Host: www.xiedaimala.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8,ja;q=0.7,zh-TW;q=0.6
Cookie: _ga=GA1.2.963880079.1538204516; _gid=GA1.2.932523408.1538204516; _gat=1; Hm_lvt_f89e0235da0841927341497d774e7b15=1538204517,1538205893; Hm_lpvt_f89e0235da0841927341497d774e7b15=1538205893

HTTP响应格式

基本元素
  • HTTP协议版本: HTTP/1.1
  • 返回状态 Status: 200, 201, 404 (详细示例看后文)
  • 时间, 例如: Sat, 29 Sep 2018 07:24:53 GMT
  • 返回内容类型: text/plain, text/html, image/jpeg

示例

1
2
3
4
5
6
7
8
9
10
11
12
HTTP/1.1 200 OK
Date: Sat, 29 Sep 2018 07:24:53 GMT
Content-Type: image/vnd.microsoft.icon
Content-Length: 3638
Connection: keep-alive
Server: nginx/1.6.2
Last-Modified: Thu, 24 May 2018 05:56:53 GMT
ETag: "e36-56ced517f0753"
Cache-Control: max-age=2592000, public
X-ORCA-Accelerator: HIT from 006.mul.lax01.us.krill.zenlogic.net
X-Cache: HIT from 006.mul.lax01.us.krill.zenlogic.net
Accept-Ranges: bytes
总结
  • 一个HTTP请求在语义上表达对一个互联网资源(URL)的操作(GET, POST, PUT)
  • 然后Web后端返回资源操作的结果和相关信息

常见的Content-Type字段值

  • text/plain
  • text/html
  • text/css
  • image/jpeg
  • image/png
  • image/svg+xml
  • audio/mp4
  • video/mp4
  • application/javascript
  • application/pdf
  • application/zip
  • application/atom+xml

HTTP状态码 Status

HTTP状态码

  • 1xx消息——请求已被服务器接收,继续处理
  • 2xx成功——请求已成功被服务器接收、理解、并接受
  • 3xx重定向——需要后续操作才能完成这一请求
  • 4xx请求错误——请求含有词法错误或者无法被执行(客户端的责任)
  • 5xx服务器错误——服务器在处理某个正确请求时发生错误(服务端的责任)

*如何理解HTTP协议是无状态

HTTP请求的实现应该是无状态的

  • 每个请求都是独立的
  • 每个请求都需要显示的附带状态信息. 比如告诉后端, 我是谁 (认证), 我现在在什么状态

如何使用浏览器查看HTTP请求和返回结果

  • Chrome调试工具 –> 浏览器打开页面发送HTTP请求和返回结果
    -Wireshark –> 抓包工具, 用来查看其他客户端的请求

Spring实现响应GET, POST, PUT, DELETE操作请求

使用Postman发送GET, POST, PUT, DELETE操作请求

  • 操作相关注解 @PostMapping, @GetMapping, @PutMapping, Deletemapping
  • 参数相关注解 @RequestBody, @PathVariable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package user;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.*;
/*
操作相关注解 @PostMapping, @GetMapping, @PutMapping, Deletemapping
参数相关注解 @RequestBody, @PathVariable
*/
@RestController
public class UserController {
private final Map<String,User> map = new HashMap<String,User>();

UserController(){
map.put("aaa",new User("aaa",11));
map.put("bbb",new User("bbb",22));
map.put("ccc",new User("ccc",33));
}

@GetMapping("/users")
public List<User> getUsers() {
Set<String> keys = map.keySet();
List<User> res = new ArrayList<>();
for (String name:keys) {
res.add(map.get(name));
}
return res;
}

@GetMapping("/users/{name}")
public User getUserByName(@PathVariable("name") String name) {
if(map.containsKey(name)){
return map.get(name);
}else{
return null;
}
}

@PostMapping("/users")
public User AddUser(@RequestBody User user) {
String name = user.getName();
map.put(name,user);
return user;
}

@PutMapping("/users/{name}")
public User UpdateUser(@PathVariable("name") String name ,@RequestBody User user) {
map.get(name).setAge(user.getAge());
return user;
}
@DeleteMapping("/users/{name}")
public User DelUserByName(@PathVariable("name") String name){
if(map.containsKey(name)){
return map.remove(name);
}else{
return null;
}
}
}

Spring实现自定义返回状态码

ResponseEntity类的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package user;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.*;
/*
操作相关注解 @PostMapping, @GetMapping, @PutMapping, Deletemapping
参数相关注解 @RequestBody, @PathVariable
*/
@RestController
public class UserController {
private final Map<String,User> map = new HashMap<>();

UserController(){
map.put("aaa",new User("aaa",11));
map.put("bbb",new User("bbb",22));
map.put("ccc",new User("ccc",33));
}

@GetMapping("/users")
ResponseEntity<List<User>> getUsers(){
Set<String> keys = map.keySet();
List<User> res = new ArrayList<>();
for (String name:keys) {
res.add(map.get(name));
}
return new ResponseEntity<>(res, HttpStatus.OK);
}

@GetMapping("/users/{name}")
public ResponseEntity<User> getUserByName(@PathVariable("name") String name) {
if(map.containsKey(name)){
return new ResponseEntity<>(map.get(name),HttpStatus.OK);
}else{
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}

@PostMapping("/users")
public ResponseEntity<User> AddUser(@RequestBody User user) {
String name = user.getName();
if(map.containsKey(name)){
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}else{
map.put(name,user);
return new ResponseEntity<>(map.get(name),HttpStatus.CREATED);
}
}



@PutMapping("/users/{name}")
public ResponseEntity<User> UpdateUser(@PathVariable("name") String name ,@RequestBody User user) {
if(map.containsKey(name)){
User updateUser = map.get(name);
updateUser.setAge(user.getAge());
return new ResponseEntity<>(map.get(name),HttpStatus.OK);
}else{
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}

@DeleteMapping("/users/{name}")
public ResponseEntity<User> DelUserByName(@PathVariable("name") String name){
if(map.containsKey(name)){
return new ResponseEntity<>(map.remove(name),HttpStatus.OK);
}else{
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
}

参考资料