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开发更便捷
示例:
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) { System.out.println("请求方式:" + request.getMethod());
System.out.println("请求地址:" + request.getRequestURL());
System.out.println("请求协议:" + request.getProtocol());
System.out.println("请求参数:" + request.getParameter("name"));
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,示例:
1 2 3 4 5 6 7 8 9 10 11 12
| @GetMapping("/response") public void response(HttpServletResponse response) throws IOException { response.setStatus(2000); response.setHeader("Content-Type","text/html;charset=UTF-8"); response.setContentLength(1000); response.getWriter().write("你好你好你好,HelloHelloHello"); }
|
演示图:

通过枚举获取状态码:

- 基于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>"); }
|
演示图:

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