《Spring Boot 趣味实战课》读书笔记(四)
你有 REST Style 吗
你应该懂一点 HTTP
- HTTP 就是 HyperText Transfer Protocol(超文本传输协议)的缩写。
- 它是一种关于“传输”的协议,既然是传输,那么至少要在两个对象之间进行,在 HTTP 中对应的就是客户端和服务端。
- 客户端和服务端对应两个动作——请求和响应。
- 客户端向服务端发送请求,而服务端则根据客户端的请求做出相应的响应。
报文
- HTTP 的报文有两种——请求报文和响应报文。
- 请求报文
- 开头的 GET 表示请求的类型,称为 HTTP 的方法(Method)。
- 之后的 /v3/api-docs 表示请求的路径。
- HTTP/1.1 表示本次请求使用的 HTTP 协议的版本。
- 接下来的 Host 和 Accept 都属于首部(Header)字段,属于可选字段。
- 空行下面的…代表实体的主体(Entity Body)部分,同样是可选内容。
- 这段请求内容的意思是:以 GET 方式基于 HTTP 协议的 1.1 版本请求访问 localhost:8080 服务器上的/v3/api-docs 资源。
- 响应报文
- 开头的 HTTP/1.1 与请求报文的意义相同。
- 之后的 200 OK 表示响应的状态码(Status Code)和原因短语(Reason-Phrase)。
- 接下来的 Date、Content-Type 等都属于首部字段。
- 接着以空行分隔,最后的…与请求报文一样是资源实体的主体。
- 请求报文
报文结构
- 报文由 3 部分组成:
- 起始行(请求行、响应行)
- 报文的第一行,请求行(请求报文中的起始行)用来说明要做什么,响应行(响应报文中的起始行)用来说明结果如何。
- 首部
- 起始行后面有零到多个首部字段,首部字段由 key:value 的方式构成。
- 首部以一个空行结束。
- 主体(部分请求方法没有主体)
- 空行之后是报文主体,请求主体包含了客户端发送给服务端的数据;
- 响应主体则是服务端要返回给客户端的内容。
- 起始行和首部都是文本格式,且其结构都是相对固定的。而主体则不一样,主体中可以包含任何格式的数据(如文本、图片、音频、视频、其他文件)。
- 起始行(请求行、响应行)
状态码
- 状态码与原因短语用来描述请求的处理结果。
安全性与幂等性
- 安全性与幂等性指的都是 HTTP 方法的特性。
- 安全性指的是不会对服务端造成影响,无论如何请求,服务端都不会因为这个请求而发生变化,简而言之就是只读。
- 幂等性指的是多次请求对服务器造成的影响与第一次请求完全一样。
- 安全性与幂等性依赖于服务端实现,这种方式是一种契约。
- 并不是说将一个删除操作的接口设置为 GET 请求(它依然具备安全性);
- 而是说对应类型的请求在实现的时候要符合它们的安全性、幂等性约定。
接口代言人 Swagger
- Swagger 是一款用于生成、描述、调用和可视化 RESTful 风格的 Web 服务接口文档的框架。
- 其最大的特点在于可以使接口文档与代码实时同步。
- 通常的做法是将接口文档写在公司内部的 Wiki 上(Confluence)。
- 但这种做法的致命缺点就是接口文档几乎永远都会落后于实际代码实现,让我们的开发工作无法顺畅地进行下去。
- 为了解决这些问题,Swagger 应运而生。
- Swagger 不仅可以实时展示接口信息,还可以对接口进行调试。
整合
- 要使用 Swagger,首先需要添加 Swagger 对应的依赖:
<dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version> </dependency>
- 然后需要添加 Swagger 的基础配置:
@EnableOpenApi @Configuration public class SwaggerConfig {/*** 返回 restful api* @return*/@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.OAS_30).apiInfo(apiInfo()).select()/** apis 用于告诉 Swagger 扫描带有 @Api 注解的类*/.apis(RequestHandlerSelectors.withClassAnnotation(Api.class)).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("Spring Boot 趣味实战课").description("Spring Boot 趣味实战课的 RESTFul 接口文档说明").version("1.0").build();} }
- 最后需要在接口上添加一些 Swagger 的注解:
@RestController @RequestMapping("/rest") @Api(tags = "RestFul 接口") public class RestFulController {@GetMapping("/swagger")@ApiOperation(value = "Swagger 接口")public String swagger() {return "Swagger Method";} }
常用注解
- Swagger 常用的 5 个注解:
- 增强版 User 类:
@Data public class User {@ApiModelProperty("用户ID")private int id;@ApiModelProperty("名字")@NotBlank(message = "名字不能为空")private String name;@ApiModelProperty("年龄")@Min( value = 1,message = "年龄要不能小于 1")@Max( value = 120,message = "年龄要不能大于 120")private int age;@ApiModelProperty("邮箱")@Email(message = "Email格式不正确")private String email;@ApiModelProperty("生日")@Past(message = "生日必须为过去的时间")private LocalDate birthDay; }
增强版
- 有一款增强版的工具 knife4j 能够弥补原生 Swagger 在使用体验和调试接口方面的不足。
-
要使用 knife4j 也非常简单,只需要将依赖替换成如下内容即可:
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</version> </dependency>
-
使用 knife4j 时,记得删除之前的 Swagger 依赖,因为 knife4j 依赖已经包含了 Swagger 依赖。
-
- 启动工程并访问 knife4j 的默认地址(http://localhost:8080/doc.html):
- 除了 Swagger 的基础功能,knife4j 还有很多增强功能,如全局参数、请求参数缓存、接口排序、导出离线文档等非常实用的功能。
解密 REST
REST 定义
- REST 是 Representational State Transfer 的缩写,翻译为中文就是“表现层状态转换”。
- 简单来说,就是资源以什么样的形式来展现自己。
- 例如,文本可以是 JSON 或 XML 格式的,图片可以是 JPEG 或其他格式的。
- 状态转换说的是资源发生了变化。
- “资源”的状态转换正是由 HTTP 的各种动作(方法)所引起的。
- REST 的核心不仅仅是对数据的操作,还包括如何操作,以什么样的规范操作。
REST-Ful
- 前/后端分离,移动互联网的爆发,导致后端服务不仅要为 Web 端提供支持,还要为移动端(如 Android、iOS 等)提供支持,那么对 API 的设计就显得格外重要了。
- API 需要多端共享、多端统一,否则就会给后期的维护和扩展带来重大的灾难。
- 这个时候,RESTful 凭借它结构清晰、易于理解、方便扩展的特性成了设计良好 API 的不二之选。
- RESTful 风格的 API 要满足以下要求:
- 用 URI 定位资源;
- URI 由名词组成;
- 使用 HTTP 方法操作资源。
URL 与 URI
- URI
- Uniform Resource Identifier;
- 统一资源标识符。
- URL
- Uniform Resource Locator;
- 统一资源定位符。
- URN
- Uniform Resource Name;
- 统一资源名称。