HTTP协议基础知识
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 | 请求主体的大小(单位:字节) |
请求体:
- 请求方式-GET:请求参数在请求行中,没有请求体,GET请求大小是有限制的
- 请求方式-POST:请求参数在请求体中,POST请求大小是没有限制的
获取请求协议
- Web服务器(Tomcat)对HTTP协议的请求数据进行了解析,并将解析结果封装为HttpServeletRequest。在调用Controller方法的时候传递给了该方法。这样,程序就不需要再直接对协议进行操作,让Web开发更便捷
示例:
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 "响应成功";
}
}
演示图:

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开发更便捷
- 使用HttpServletResponse,示例:
@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");
}
演示图:

通过枚举获取状态码:

- 基于ResponseEntity,示例:
@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>");// 响应体
}
演示图:

响应状态码和响应头如果没有特殊要求的话,通常不手动设定。服务器会根据请求处理的逻辑,自动设置响应状态码和响应头
案例
将如下文本:
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:
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")该注释可以快速的将日期格式化
后端实现代码:
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部分):
<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
案例总结
@CrossOrigin(origins = "*")可以解决除了协议以外的跨域问题@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")该注释可以为对象的日期属性快速格式化- 如果将html文件放到SpringBoot的
resource/static下,启动项目后可以通过IP地址访问