一、HTTP 协议学习
1. 常用的请求方法
- GET:用于请求获取指定资源的表示。客户端通过向服务器发送GET请求,服务器会返回请求的资源。这个请求方法通常用于获取数据,比如获取网页内容、图片、视频等。
- POST:用于向服务器提交数据,这些数据通常用于创建新的资源。通过POST请求,客户端将数据发送给服务器,服务器处理并存储这些数据。POST常用于提交表单数据,例如用户注册或提交评论。
- PUT:用于向服务器上传数据,从而更新指定的资源。客户端通过PUT请求,将数据发送到服务器上的指定资源位置,从而对该资源进行更新。
- DELETE:用于请求服务器删除指定的资源。客户端通过DELETE请求,告诉服务器删除指定的资源。
- PATCH:用于对资源进行局部更新。与PUT请求不同,PATCH请求仅更新资源的部分内容,而不是整个资源。
- HEAD:类似于GET方法,但服务器只返回响应头部信息,不返回实际的资源内容。这个方法常用于检查资源的元数据,例如验证资源是否存在或最后修改时间。
- OPTIONS:用于获取目标资源所支持的通信选项。客户端可以通过发送OPTIONS请求来了解服务器支持哪些HTTP方法、允许的头部信息等。
- TRACE:用于将客户端发出的请求返回回来,用于测试和诊断。服务器会将收到的请求转发回给客户端,以便客户端查看服务器收到的原始请求信息。
2. 请求头
HTTP协议的请求头是在HTTP请求中包含的一组信息,用于向服务器传递附加的数据和元数据。请求头通常是由客户端(例如Web浏览器或应用程序)添加到HTTP请求中,以提供有关请求的更多信息。
- Host:
指定目标服务器的主机名和端口号,用于告诉服务器请求的目标地址。例如:Host: www.example.com
协商
-
Accept:
指定客户端接受的响应数据类型(MIME类型)。客户端可以通过这个头部告诉服务器它能够处理哪些数据类型。例如:Accept: text/html, application/xhtml+xml, application/xml;q=0.9, /;q=0.8 -
Accept-Language:
指定客户端接受的自然语言类型,用于告诉服务器客户端希望接收什么语言的响应。例如:Accept-Language: en-US, en;q=0.9, zh-CN;q=0.8 -
Accept-Encoding:
指定客户端接受的内容编码类型,用于告诉服务器客户端能够解码的内容压缩格式。例如:Accept-Encoding: gzip, deflate -
Authorization:
用于在需要进行身份验证的请求中,包含用户凭证的信息。例如:Authorization: Basic base64encoded(username:password)
指定请求体
-
Content-Type:
指定请求体的数据类型(MIME类型),用于告诉服务器请求体中的数据是什么类型。例如:Content-Type: application/json -
Content-Length:
指定请求体的大小,用于告诉服务器请求体中的数据有多大(字节数)。例如:Content-Length: 1024 -
Referer:
指定当前请求的来源页面,即前一个页面的URL。通常用于告诉服务器请求是从哪个页面链接过来的。例如:Referer: https://www.example.com/previous-page -
Cookie:
包含之前由服务器设置的Cookie信息,用于保持状态和身份验证。例如:Cookie: sessionid=abcdef1234567890
3. 响应头
HTTP协议的响应头是服务器在响应客户端的HTTP请求时,包含在响应消息头部的一组信息。这些响应头提供了有关响应的各种信息,例如响应状态码、内容类型、服务器信息等。以下是一些常见的HTTP响应头:
-
Content-Type:
指定响应体的数据类型(MIME类型),告诉客户端服务器返回的内容是什么类型。例如:Content-Type: text/html; charset=utf-8 -
Content-Length:
指定响应体的大小,告诉客户端响应体的数据有多大(字节数)。例如:Content-Length: 1024 -
Date:
指定响应的日期和时间,告诉客户端响应生成的时间。例如:Date: Sun, 25 Jul 2023 12:34:56 GMT -
Server:
指定服务器的信息,告诉客户端响应是由哪个服务器生成的。例如:Server: Apache/2.4.41 (Unix) -
Set-Cookie:
用于在响应中设置Cookie信息,用于保持状态和身份验证。例如:Set-Cookie: sessionid=abcdef1234567890; Path=/; HttpOnly -
Cache-Control:
指定请求和响应的缓存行为。 -
Location:
用于重定向响应,告诉客户端资源的新位置。 -
Content-Encoding:
指定响应体的内容编码类型,告诉客户端服务器对响应体进行了何种压缩。
4. 响应状态码
- 2XX Success(成功状态码)
200 表示从客户端发来的请求在服务器端被正常处理
204 该状态码表示服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分
206 该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求 - 3XX Redirection(重定向状态码)
301 永久性重定向
302 临时性重定向 - 4XX Client Error(客户端错误状态码)
400 该状态码表示请求报文中存在语法错误
401 该状态码表示发送的请求需要有通过HTTP认证的认证信息
403 该状态码表明对请求资源的访问被服务器拒绝了。
404 该状态码表明服务器上无法找到请求的资源
405错误表示"Method Not Allowed",即方法不被允许,意思是对于请求所标识的资源,不允许使用请求行中所指定的方法。 - 5XX Server Error(服务器错误状态码)
500 该状态码表明服务器端在执行请求时发生了错误。
503 该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
5. Cookie & Session 的关系
- Cookie:
Cookie是在客户端(通常是浏览器)存储少量数据的一种机制。
服务器通过在HTTP响应头中添加Set-Cookie头部,将Cookie信息发送给客户端。
客户端会将Cookie保存在本地,每次向同一服务器发起请求时,都会自动将相关的Cookie信息包含在HTTP请求头中,发送给服务器。
Cookie通常用于跟踪用户的状态和存储用户偏好设置。例如,登录状态、语言偏好、购物车内容等都可以通过Cookie保存在客户端。 - Session:
Session是服务器端的一种机制,用于跟踪用户在同一网站的活动状态。
当用户第一次访问服务器时,服务器会为该用户创建一个唯一的Session标识,并将该标识保存在Cookie中(通常名为sessionid)。
之后,客户端每次向服务器发起请求时,都会自动带上这个sessionid标识,用于告诉服务器请求来自于哪个用户。
服务器根据收到的sessionid来查找相应的Session数据,从而判断用户的状态,存储购物车信息、用户认证状态等。 - 关系:
Cookie和Session通常一起使用,配合实现用户状态管理和会话跟踪。
用户第一次访问网站时,服务器为其创建一个Session,并将Session的标识(sessionid)保存在Cookie中,发送给客户端。
客户端在以后的每次请求中都会自动带上这个Cookie,服务器通过其中的sessionid找到对应的Session数据,从而恢复用户的状态。
通过Cookie和Session的配合使用,服务器可以有效地跟踪用户的会话信息,保持用户状态的连续性,并提供个性化的服务。例如,用户登录后,在整个会话期间保持登录状态,同时可以根据用户Session中的数据展示相应的个性化内容。
二、从头搭建 Spring Boot 工程
在Spring官网(https://start.spring.io/)自定义选项搭建。
三、练习 Spring MVC 常用注解
常见命令:
POST请求
curl -i -X POST \
-H 'Content-Type: application/json' \
-d '{"account": "admin", "password": "xxt123@XXT"}' \
http://zentao.xxt.cn/zentao/api.php/v1/tokens
GET 请求
curl -i \
-H 'Content-Type: application/json' \
http://localhost:8080/failure/test100101?timeoutMills=1
1. 简单练习一
package com.xxt.SpringPractice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/demo")
public class GetController {
// 处理GET请求,映射到路径 /demo/hello
@GetMapping("/hello")
public String helloGet() {
return "Hello, GET request";
}
/*
xxt@mawenbo ~ % curl -i http://localhost:8080/demo/hello
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 18
Date: Tue, 25 Jul 2023 08:21:19 GMT
Hello, GET request%
*/
// 处理POST请求,映射到路径 /demo/hello
@PostMapping("/hello")
public String helloPost() {
return "Hello, POST request";
}
/*
xxt@mawenbo ~ % curl -i -X POST http://localhost:8080/demo/hello
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 19
Date: Tue, 25 Jul 2023 08:23:40 GMT
Hello, POST request%
*/
}
2.GetController
package com.xxt.SpringPractice;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@RestController
@RequestMapping(value = "/test02", produces = MediaType.APPLICATION_JSON_VALUE)
@Slf4j
public class GetController01 {
@PostMapping("test0201")
public String test0101(@RequestBody Student student) {
log.info("test0201 called. student: {}", student);
return student != null ? student.toString() : null;
}
/*
xxt@mawenbo ~ % curl -i -X POST -H "Content-Type: application/json" -d '{"name": "mwb", "age": 3}' http://localhost:8080/test02/test0201
HTTP/1.1 200
Content-Type: application/json
Content-Length: 24
Date: Tue, 25 Jul 2023 09:20:09 GMT
Student(name=mwb, age=3)%
*/
@GetMapping("test0202")
public String test0202() {
log.info("test0202 called and return chinese word");
return "中文";
}
//curl -i -X GET -H "Accept-Charset: UTF-8" http://localhost:8080/test0202
/*
xxt@mawenbo ~ % curl -i -X GET -H "Accept-Charset: UTF-8" http://localhost:8080/test02/test0202
HTTP/1.1 200
Content-Type: application/json
Content-Length: 6
Date: Tue, 25 Jul 2023 09:28:08 GMT
中文%
*/
@GetMapping("test0203")
public List<Date> test0203() {
log.info("test0203 called and return date list");
List<Date> result = new ArrayList<>();
result.add(new Date());
result.add(new Date());
result.add(new Date());
result.add(null);
return result;
}
/*
xxt@mawenbo ~ % curl -i -X GET -H "Accept-Charset: UTF-8" http://localhost:8080/test02/test0203
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 25 Jul 2023 09:28:26 GMT
["2023-07-25T09:28:26.308+00:00","2023-07-25T09:28:26.308+00:00","2023-07-25T09:28:26.308+00:00",null]%
*/
@GetMapping("test0204")
public void test0204(@RequestParam(required = false) String name) {
log.info("test0204 called with params:name={}", name);
}
/*
xxt@mawenbo ~ % curl -i -X GET -H "Accept-Charset: UTF-8" http://localhost:8080/test02/test0204
HTTP/1.1 200
Content-Length: 0
Date: Tue, 25 Jul 2023 09:28:54 GMT
控制台:test100101 called with params:name=null
*/
}
3. PostController
package com.xxt.SpringPractice;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping(value = "/test01", produces = MediaType.APPLICATION_JSON_VALUE)
@Slf4j
public class PostController {
@PostMapping("test0101")
public String test0101(@RequestBody Student student) {
log.info("test01 called. student: {}", student);
return student != null ? student.toString() : null;
}
// 传入一个对象
/*
xxt@mawenbo ~ % curl -i -X POST -H "Content-Type: application/json" -d '{"name":"wenbo", "age": 20}' http://localhost:8080/test01/test0101
HTTP/1.1 200
Content-Type: application/json
Content-Length: 27
Date: Tue, 25 Jul 2023 08:53:41 GMT
Student(name=wenbo, age=20)%
*/
@PostMapping("test0102")
public String test0102(@RequestBody List<Student> students) {
log.info("test0102 called. students: {}", students);
return students != null ? students.toString() : null;
}
// 一次传入多个对象
/*
xxt@mawenbo ~ % curl -i -X POST -H "Content-Type: application/json" -d '[{"name":"mawenbo", "age": 20}, {"name":"maxiaobo", "age": 18}, {"name":"mayibo", "age": 19}]' http://localhost:8080/test01/test0102
HTTP/1.1 200
Content-Type: application/json
Content-Length: 93
Date: Tue, 25 Jul 2023 09:08:54 GMT
[Student(name=mawenbo, age=20), Student(name=maxiaobo, age=18), Student(name=mayibo, age=19)]%
*/
}
@Data
class Student {
private String name;
private int age;
}