第6章 构建 RESTful 服务
6.1 RESTful 简介
6.2 构建 RESTful 应用接口
6.3 使用 Swagger 生成 Web API 文档
6.4 实战:实现 Web API 版本控制
6.5 拓展:如何实现 Web API 版本控制,同时兼容无版本控制的原始接口?
6.5 拓展:如何实现 Web API 版本控制,同时兼容无版本控制的原始接口?
〇、背景
在上一节 6.4 实战:实现 Web API 版本控制 中,我们实现了 Web API 版本控制,但是有一个问题:我们在原始版本上增加了版本控制之后(假设原始版本没有版本号,现在做版本控制之后,V1对应了原始版本),可以正常访问有版本号的接口,但是却无法访问没有版本号的原始接口。如下:
原始版本(无版本控制)删除订单接口:http://localhost:8080/api/order/delete/20011(无法返回数据)
原始版本(无版本控制)获取订单详情接口:http://localhost:8080/api/order/detail/20011(无法返回数据)
一、需求
假设原始 Web API 接口没有实现版本控制,那么,如何升级接口才能在实现版本控制的同时,无版本控制的原始接口不受影响。
1、背景
假设 原始接口(无版本控制) 和 升级后的接口(有版本控制) 如下所示。
原始接口(无版本控制):
api/order/接口名称
升级后的接口(有版本控制):
api/v1/order/接口名称
api/v2/order/接口名称
2、核心需求:
(1)升级接口,进行 Web API 版本控制。
(2)原始接口可以正常访问,不受接口升级影响。
(3)原始接口和升级后的V1接口等价(即api/order/接口名称
和api/v1/order/接口名称
等价)。
二、解决方案
Spring Boot 对 RESTful 的支持非常全面,因而实现 RESTful API 非常简单,同样对于 API 版本控制也有相应的实现方案,实现步骤如下:
1、API版本控制配置
(1)创建自定义的 @ApiVersion 注解。
(2)创建自定义 URL 匹配规则 ApiVersionCondition 类(实现 RequestCondition 接口)。
(3)创建自定义的映射处理程序 ApiRequestMappingHandlerMapping 类(继承 RequestMappingHandlerMapping 类)。
(4)创建 WebMvcRegistrationsConfig 配置类(实现 WebMvcRegistrations 接口),将自定义的映射处理程序 ApiRequestMappingHandlerMapping 注册到系统中。
2、配置实现接口
编写测试的控制器,实现相关接口的测试。
假设升级后的接口为V1(版本1)、V2(版本2)。
实现方法:
- 原始接口:原始接口不需要做任何操作。(保证原始接口不受任何影响)
- V1接口:V1接口不需要实现任何接口,直接继承原始接口,然后添加版本注解@ApiVersion 和 URL中添加版本标志{version} 实现版本控制即可。(保证原始接口和升级后的V1接口等价)
- V2接口:V2接口根据业务需求的变化实现相关接口,然后添加版本注解@ApiVersion 和 URL中添加版本标志{version} 实现版本控制。
三、具体实现
1、API版本控制配置
关于 API版本控制配置,可以直接参考上一节 6.4 实战:实现 Web API 版本控制 。
2、配置实现接口
配置完成之后,接下来编写测试的控制器(Controller),实现相关接口的测试。在 Controller 目录下分别创建 OrderV1Controller 和 OrderV2Controller,原始接口控制器 OrderController 不做任何改动。示例代码如下:
OrderController.java
package com.example.restfulproject.controller;
import com.example.restfulproject.comm.utils.JSONResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 原始版本的接口定义
*/
@RestController
@RequestMapping("/api/order")
public class OrderController {
@GetMapping("/delete/{orderId}")
public JSONResult deleteOrderById(@PathVariable String orderId) {
System.out.println("V1 删除订单成功:" + orderId);
return JSONResult.ok("V1 删除订单成功");
}
@GetMapping("/detail/{orderId}")
public JSONResult queryOrderById(@PathVariable String orderId) {
System.out.println("V1 获取订单详情成功:" + orderId);
return JSONResult.ok("V1 获取订单详情成功");
}
}
OrderV1Controller.java
package com.example.restfulproject.controller;
import com.example.restfulproject.comm.annotation.ApiVersion;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* V1 版本的接口定义
*/
@ApiVersion(value = 1)
@RestController
@RequestMapping("/api/{version}/order")
public class OrderV1Controller extends OrderController {
}
OrderV2Controller.java
package com.example.restfulproject.controller;
import com.example.restfulproject.comm.annotation.ApiVersion;
import com.example.restfulproject.comm.utils.JSONResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* V2 版本的接口定义
*/
@ApiVersion(value = 2)
@RestController
@RequestMapping("/api/{version}/order")
public class OrderV2Controller {
@GetMapping("/detail/{orderId}")
public JSONResult queryOrderById(@PathVariable String orderId) {
System.out.println("V2 获取订单详情成功:" + orderId);
return JSONResult.ok("V2 获取订单详情成功");
}
@GetMapping("/list")
public JSONResult list() {
System.out.println("V2 新增list订单列表接口");
return JSONResult.ok(200, "V2 新增list订单列表接口");
}
}
3、验证测试
启动项目,查看版本控制是否生效。同时检查无版本控制的原始接口是否不受影响。
(1)删除订单接口:
原始接口(无版本控制):http://localhost:8080/api/order/delete/20011
V1接口(有版本控制):http://localhost:8080/api/v1/order/delete/20011
V2接口(有版本控制):http://localhost:8080/api/v2/order/delete/20011
(2)获取订单详情接口:
原始接口(无版本控制):http://localhost:8080/api/order/detail/20011
V1接口(有版本控制):http://localhost:8080/api/v1/order/detail/20011
V2接口(有版本控制):http://localhost:8080/api/v2/order/detail/20011
(3)新增订单列表接口:
原始接口(无版本控制):http://localhost:8080/api/order/list
V1接口(有版本控制):http://localhost:8080/api/v1/order/list
V2接口(有版本控制):http://localhost:8080/api/v2/order/list
来源:《Spring Boot 从入门到实战》学习笔记