HTTP协议

概念:超文本传输协议(Hyper Text Transfer Protocol),规定了浏览器和服务器之间数据传输的规则

特点:

  • 基于TCP协议:面向连接,安全
  • 基于请求-响应模型的:一次请求对应一次响应
  • HTTP协议是无状态的协议:对于事物处理没有记忆能力。每次请求-响应都是独立的
    • 缺点:多次请求间不能共享数据
    • 优点:速度快

请求协议

GET请求有两部分:请求行和请求头,POST请求有三部分:请求行、请求头和请求体

请求行:请求数据第一行(请求方式、资源路径、协议)

请求头:第二行开始,格式:key : value

Key 说明
Host 请求的主机名
User-Agent 浏览器版本
Accept 表示浏览器能够接收的资源类型,如test/*,image/或者/*表示所有
Accept-Language 表示浏览器偏好的语言,服务器可以据此返回不同语言的网页
Accept-Encoding 表示浏览器可以支持的压缩类型
Content-Type 请求主体的数据类型
Content-Length 请求主体的大小(单位:字节)

请求体:

  1. 请求方式-GET:请求参数在请求行中没有请求体,GET请求大小是有限制的

  2. 请求方式-POST:请求参数在请求体中,POST请求大小是没有限制的

获取请求协议

  • Web服务器(Tomcat)对HTTP协议的请求数据进行了解析,并将解析结果封装为HttpServeletRequest。在调用Controller方法的时候传递给了该方法。这样,程序就不需要再直接对协议进行操作,让Web开发更便捷

示例:

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
package com.norlcyan.controller;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RequestController {
@GetMapping("/request")
public String request(HttpServletRequest request) {
// 1. 获取请求方式
System.out.println("请求方式:" + request.getMethod());

// 2. 获取请求URL地址
System.out.println("请求地址:" + request.getRequestURL());

// 3. 获取请求协议
System.out.println("请求协议:" + request.getProtocol());

// 4. 获取请求参数 - name
System.out.println("请求参数:" + request.getParameter("name"));

// 5. 获取请求头 - Accept
System.out.println("请求头:" + request.getHeader("Accept"));

return "响应成功";
}
}

演示图:

Snipaste_2025-08-05_16-08-20

HTTP请求数据不需要程序员自己解析,因为web服务器负责对HTTP请求进行解析,并封装为了对象

想要获取请求数据,可以通过HttpServletRequest对象,里面封装了所有的请求信息

响应协议

响应行:响应数据第一行(协议、状态码、描述)

状态码 说明
1xx 响应中-临时状态码,表示请求已经接收,告诉客户端应该继续请求或者如果它已经完成则忽略它
2xx 成功-表示请求已经被成功接收,处理已完成
3xx 重定向-重定向到其他地方;让客户端再发起一次请求以完成整个处理
4xx 客户端错误-处理发生错误,责任在客户端。如:请求了不存在的资源、客户端未被授权、禁止访问等
5xx 服务器错误-处理发生错误,责任在服务端。如:程序抛出异常等

响应头:第二行开始,格式:key : value

Key 说明
Content-Type 表示该响应内容的类型,例如:text/html,application/json
Content-Length 表示该响应内容的长度(字节数)
Content-Encoding 表示该响应压缩算法,如:gzip
Cache-Control 指示客户端应如何缓存,例如:max-age=300表示可以最多缓存300秒
Set-Cookie 告诉浏览器为当前页面所在的域设置cookie

响应体:最后一部分,存放响应数据

响应数据设置

Web服务器对HTTP协议的响应数据进行了封装(HttpServletResponse),在调用Controller方法的时候传递给了该方法。这样,程序就不需要再直接对协议进行操作,让Web开发更便捷

  1. 使用HttpServletResponse,示例:
1
2
3
4
5
6
7
8
9
10
11
12
@GetMapping("/response")
public void response(HttpServletResponse response) throws IOException {
// 1. 响应状态码
response.setStatus(2000);

// 2. 响应头
response.setHeader("Content-Type","text/html;charset=UTF-8"); // 字体最好设置为UTF-8,否则可能中文会显示???
response.setContentLength(1000);

// 3. 响应体
response.getWriter().write("你好你好你好,HelloHelloHello");
}

演示图:

Snipaste_2025-08-05_16-34-23

通过枚举获取状态码:

Snipaste_2025-08-05_16-36-39

  1. 基于ResponseEntity,示例:
1
2
3
4
5
6
7
8
@GetMapping("/entity")
public ResponseEntity<String> entity() {
return ResponseEntity.
status(401). // 状态码
header("Cache-Control","500"). // 响应头
header("Content-Type","text/html;charset=UTF-8"). // 响应头
body("<h1>Hello Response Entity</h1>"); // 响应体
}

演示图:

Snipaste_2025-08-05_16-45-58

响应状态码和响应头如果没有特殊要求的话,通常不手动设定。服务器会根据请求处理的逻辑,自动设置响应状态码和响应头

案例

将如下文本:

1
2
3
4
5
6
7
8
1,daqiao,1234567890,大乔,22,2024-07-15 15:05:45
2,xiaoqiao,1234567890,小乔,18,2024-07-15 15:12:09
3,diaochan,1234567890,貂蝉,21,2024-07-15 15:07:16
4,lvbu,1234567890,吕布,28,2024-07-16 10:05:15
5,zhaoyun,1234567890,赵云,27,2024-07-16 11:03:28
6,zhangfei,1234567890,张飞,31,2024-07-16 11:03:28
7,guanyu,1234567890,关羽,34,2024-07-16 12:05:12
8,liubei,1234567890,刘备,37,2024-07-16 15:03:28

响应给前端使用

实体类User:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.norlcyan.pojo;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;

import java.time.LocalDateTime;

@NoArgsConstructor
@Data
public class User {
private Integer id;
private String username;
private String password;
private String name;
private Integer age;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
}

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")该注释可以快速的将日期格式化

后端实现代码:

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
package com.norlcyan.controller;

import cn.hutool.core.io.FileUtil;
import com.norlcyan.pojo.User;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@RestController
@CrossOrigin(origins = "*")
public class UserListController {
@GetMapping("/users")
public List<User> getUsers() { // User为自定义的实体类,成员属性对应文本中的内容
List<User> users = new ArrayList<>();
addUser2UserList(users);
return users;
}

private void addUser2UserList(List<User> users) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
File file = new File("src/main/resources/static/user.txt");
List<String> lines = FileUtil.readUtf8Lines(file);
for (String line : lines) {
String[] info = line.split(",");
User user = new User();
user.setId(Integer.parseInt(info[0]));
user.setUsername(info[1]);
user.setPassword(info[2]);
user.setName(info[3]);
user.setAge(Integer.parseInt(info[4]));
user.setUpdateTime(LocalDateTime.parse(info[5],formatter));
users.add(user);
}
}
}

@CrossOrigin(origins = "*")用于解决跨域问题(这个注释不能解决协议跨域问题

当请求的 协议、域名、端口 任意一个不同时,就构成了跨域

如果后端地址为127.0.0.1:8080,而前端是127.0.0.1:5050,这时候就会存在跨域,导致无法获取服务端响应的数据

前端代码(只提供JS部分):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script src="js/axios.min.js"></script>
<script type="module">
import { createApp } from './js/vue.esm-browser.js'
createApp({
data() {
return {
userList: []
}
},
created() {
axios.get("http://localhost:8080/users").then((res) => {
this.userList = res.data
console.log(userList);
})
},
}).mount('#app')
</script>

前端代码可以放在SpringBoot项目的resource/static目录下,并且文件名为index.html,启动后直接访问http://localhost:8080/即可

如果文件名为user.html或其他,需要在路径后加上对应的文件名,比如http://localhost:8080/user.html

案例总结

  1. @CrossOrigin(origins = "*")可以解决除了协议以外的跨域问题
  2. @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")该注释可以为对象的日期属性快速格式化
  3. 如果将html文件放到SpringBoot的resource/static下,启动项目后可以通过IP地址访问