文章目录
接口设计中的统一语言原则
在接口设计时,确保系统之间的对话语言统一非常重要,尤其是在接口的命名、参数列表、包装结构体、版本策略、幂等性实现及同步异步处理方式等方面。
关键点
-
接口响应的明确性:
- 接口应明确表示处理结果,以避免混乱。例如,响应体中
success
、code
、info
和message
的含义需清晰定义。 - 例子中,收单服务的接口由于没有明确的文档和逻辑,导致开发和调用者之间产生理解偏差。
- 接口应明确表示处理结果,以避免混乱。例如,响应体中
-
对外隐藏内部实现:
- 应避免将内部服务的状态码和错误信息直接暴露给客户端。可以通过设计更清晰的响应结构体来实现,例如去掉外层的
info
字段。
- 应避免将内部服务的状态码和错误信息直接暴露给客户端。可以通过设计更清晰的响应结构体来实现,例如去掉外层的
-
接口结构的设计逻辑:
- 设计逻辑应清楚地定义每个字段的含义,并规范客户端如何处理这些响应。
- 例如,只有在
success
为true
时才解析data
字段。
-
版本控制策略:
- 版本策略应在一开始就确定,确保统一性,可以通过 URL Path、QueryString 或 HTTP 头等方式实现。
- 不同接口实现时,应遵循相同的版本控制规则,以避免混淆。
-
同步与异步处理:
- 接口应明确其处理方式。如果内部实现为异步,但接口命名为同步,可能会导致用户误解和不必要的等待。
-
最佳实践与优化:
- 使用自定义异常和响应包装来简化代码,提高可读性和可维护性。
- 通过框架自动处理响应体包装和错误处理,简化业务逻辑。
小技巧
- 可以通过自定义注解和框架扩展实现统一的 API 版本控制,简化开发过程。
- 确保设计文档与接口实现保持一致,方便后续的维护与扩展。
Pre
Spring Boot - 在Spring Boot中实现灵活的API版本控制(上)
Spring Boot - 在Spring Boot中实现灵活的API版本控制(下)_ 封装场景启动器Starter
版本控制策略
接口不可能一成不变,需要根据业务需求不断增加内部逻辑。如果做大的功能调整或重构,涉及参数定义的变化或是参数废弃,导致接口无法向前兼容,这时接口就需要有版本的念。
在考虑接口版本策略设计时,我们需要注意的是,最好一开始就明确版本策略,并考虑在整个服务端统一版本策略.
版本策略一开始就考虑
既然接口总是要变迁的,那么最好一开始就确定版本策略。比如,确定是通过 URL Path 实现,是通过 QueryString 实现,还是通过 HTTP 头实现
接口版本控制策略
在设计 API 时,版本控制是一个重要的考虑因素。确定版本策略的方式有多种,常见的三种实现方式包括:
- 通过 URL Path 实现版本控制 :
-
这种方式最直观,易于理解和使用。
-
示例代码:
java@GetMapping("/v1/api/user") public int right1() { return 1; }
-
优点:清晰明了,客户端在访问接口时能一目了然地了解所用的版本。
-
- 通过 QueryString 中的 version 参数实现版本控制 :
-
这种方式将版本号作为查询参数传递。
-
示例代码:
java@GetMapping(value = "/api/user", params = "version=2") public int right2(@RequestParam("version") int version) { return 2; }
-
缺点:不太推荐作为公开 API 的版本策略,因为 QueryString 不易携带,可能在某些情况下造成混淆。
-
- 通过请求头中的 X-API-VERSION 参数实现版本控制 :
-
这种方式较为灵活,不会对 URL 产生影响。
-
示例代码:
java@GetMapping(value = "/api/user", headers = "X-API-VERSION=3") public int right3(@RequestHeader("X-API-VERSION") int version) { return 3; }
-
优点:不侵入 URL 结构,适合需要部分接口版本控制的场景。
-
小结
- URL Path 的版本控制方式直观且不易出错,适合大多数场景。
- QueryString 版本控制不太推荐用于公开 API,因为其携带性较差。
- HTTP 头 方式适合需要灵活版本控制的场景,能够保持接口的干净和可维护性。
根据具体的业务需求,可以选择适合的版本控制策略,以实现版本的动态切换和更好的 API 管理。
统一的 API 版本实现方式
在实现 REST 接口时,保持版本控制的一致性至关重要。以下是对如何统一 API 版本控制的策略和实现:
问题示例
团队约定使用 URL Path 方式进行版本控制,但实际实现却不一致,导致出现以下不同的 URL 格式:
java
@GetMapping("/api/item/v1")
public void wrong1() {}
@GetMapping("/api/v1/shop")
public void wrong2() {}
@GetMapping("/v1/api/merchant")
public void wrong3() {}
这种不统一可能导致接口混淆,例如 /api/v1/user
和 /api/user/v1
是否是同一个接口?因此,确保在框架层面实现统一非常重要。
解决方案
-
自定义注解 :创建一个
@APIVersion
注解,用于在方法或 Controller 类上定义版本信息。java@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface APIVersion { String[] value(); }
-
自定义 HandlerMapping :继承
RequestMappingHandlerMapping
,重写registerHandlerMethod
方法,以便从@APIVersion
注解读取版本信息并生成新的 URL Pattern。javapublic class APIVersionHandlerMapping extends RequestMappingHandlerMapping { @Override protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) { // 读取 APIVersion 注解 APIVersion apiVersion = // ... 获取注解信息 String[] urlPatterns = apiVersion == null ? new String[0] : apiVersion.value(); // 更新 RequestMappingInfo // ... super.registerHandlerMethod(handler, method, mapping); } }
-
注册自定义 HandlerMapping :通过实现
WebMvcRegistrations
接口来激活自定义的APIVersionHandlerMapping
。java@SpringBootApplication public class CommonMistakesApplication implements WebMvcRegistrations { @Override public RequestMappingHandlerMapping getRequestMappingHandlerMapping() { return new APIVersionHandlerMapping(); } }
使用示例
使用 @APIVersion
注解指定版本:
java
@GetMapping(value = "/api/user")
@APIVersion("v4")
public int right4() {
return 4;
}
小结
通过在框架层面实施统一的版本控制策略,能够有效避免接口版本混淆,实现标准化和强制的 API 版本管理。这样不仅提高了代码的可维护性,还增强了团队协作的效率。