• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

SpringBoot实现API接口的完整代码

springboot 搞代码 4年前 (2022-01-05) 21次浏览 已收录 0个评论

这篇文章主要给大家介绍了关于SpringBoot实现API接口的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、简介

产品迭代过程中,同一个接口可能同时存在多个版本,不同版本的接口URL、参数相同,可能就是内部逻辑不同。尤其是在同一接口需要同时支持旧版本和新版本的情况下,比如APP发布新版本了,有的用户可能不选择升级,这是后接口的版本管理就十分必要了,根据APP的版本就可以提供不同版本的接口。

二、代码实现

本文的代码实现基于SpringBoot 2.3.4-release

1.定义注解

ApiVersion

 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ApiVersion { /** * 版本。x.y.z格式 * * @return */ String value() default "1.0.0"; } 

value值默认为1.0.0

EnableApiVersion

 /** * 是否开启API版本控制 */ @Target(ElementType.TYPE) @Documented @Retention(RetentionPolicy.RUNTIME) @Import(ApiAutoConfiguration.class) public @interface EnableApiVersion { } 

在启动类上添加这个注解后就可以开启接口的多版本支持。使用Import引入配置ApiAutoConfiguration。

2.将版本号抽象为ApiItem类

ApiItem

 @Data public class ApiItem implements Comparable { private int high = 1; private int mid = 0; private int low = 0; public static final ApiItem API_ITEM_DEFAULT = ApiConverter.convert(ApiVersionConstant.DEFAULT_VERSION); public ApiItem() { } @Override public int compareTo(ApiItem right) { if (this.getHigh() > right.getHigh()) { return 1; } else if (this.getHigh()  right.getMid()) { return 1; } else if (this.getMid()  right.getLow()) { return 1; } else if (this.getLow() <right.getLow()) { return -1; } return 0; } } 

为了比较版本号的大小,实现Comparable接口并重写compareTo(),从高位到低位依次比较。

ApiConverter

 public class ApiConverter { public static ApiItem convert(String api) { ApiItem apiItem = new ApiItem(); if (StringUtils.isBlank(api)) { return apiItem; } String[] cells = StringUtils.split(api, "."); apiItem.setHigh(Integer.parseInt(cells[0])); if (cells.length > 1) { apiItem.setMid(Integer.parseInt(cells[1])); } if (cells.length > 2) { apiItem.setLow(Integer.parseInt(cells[2])); } return apiItem; } } 

ApiConverter提供静态方法将字符创转为ApiItem。

常量类,定义请求头及默认版本号

 public class ApiVersionConstant { /** * header 指定版本号请求头 */ public static final String API_VERSION = "x-api-version"; /** * 默认版本号 */ public static final String DEFAULT_VERSION = "1.0.0"; } 

3.核心ApiCondition

新建ApiCondition类,实现RequestCondition,重写combine、getMatchingCondition、compareTo方法。

RequestCondition

 public interface RequestCondition { /** * 方法和类上都存在相同的条件时的处理方法 */ T combine(T other); /** * 判断是否符合当前请求,返回null表示不符合 */ @Nullable T getMatchingCondition(HttpServletRequest request); /** *如果存在多个符合条件的接口,则会根据这个来排序,然后用集合的第一个元素来处理 */ int compareTo(T other, HttpServletRequest request); 

以上对RequestCondition简要说明,后续详细源码分析各个方法的作用。

ApiCondition

 @Slf4j public class ApiCondition implements RequestCondition { public static ApiCondition empty = new ApiCondition(ApiConverter.convert(ApiVersionConstant.DEFAULT_VERSION)); private ApiItem version; private boolean NULL; public ApiCondition(ApiItem item) { this.version = item; } public ApiCondition(ApiItem item, boolean NULL) { this.version = item; this.NULL = NULL; } /** * <pre class="prettyprint linenums"> *   Spring先扫描方法再扫描类,然后调用{@link #combine} *   按照方法上的注解优先级大于类上注解的原则处理,但是要注意如果方法上不定义注解的情况。 *   如果方法或者类上不定义注解,我们会给一个默认的值{@code empty},{@link ApiHandlerMapping} * 

* @param other 方法扫描封装结果 * @return */ @Override public ApiCondition combine(ApiCondition other) { // 选择版本最大的接口 if (other.NULL) { return this; } return other; } @Override public ApiCondition getMatchingCondition(HttpServletRequest request) { if (CorsUtils.isPreFlightRequest(request)) { return empty; } String version = request.getHeader(ApiVersionC来源gao@daima#com搞(%代@#码网onstant.API_VERSION); // 获取所有小于等于版本的接口;如果前端不指定版本号,则默认请求1.0.0版本的接口 if (StringUtils.isBlank(version)) { log.warn(“未指定版本,使用默认1.0.0版本。”); version = ApiVersionConstant.DEFAULT_VERSION; } ApiItem item = ApiConverter.convert(version); if (item.compareTo(ApiItem.API_ITEM_DEFAULT) = 0) { return this; } return null; } @Override public int compareTo(ApiCondition other, HttpServletRequest request) { // 获取到多个符合条件的接口后,会按照这个排序,然后get(0)获取最大版本对应的接口.自定义条件会最后比较 int compare = other.version.compareTo(this.version); if (compare == 0) { log.warn(“RequestMappingInfo相同,请检查!version:{}”, other.version); } return compare; } }

3.配置类注入容器

ApiHandlerMapping

 public class ApiHandlerMapping extends RequestMappingHandlerMapping { @Override protected RequestCondition getCustomTypeCondition(Class handlerType) { return buildFrom(AnnotationUtils.findAnnotation(handlerType, ApiVersion.class)); } @Override protected RequestCondition getCustomMethodCondition(Method method) { return buildFrom(AnnotationUtils.findAnnotation(method, ApiVersion.class)); } private ApiCondition buildFrom(ApiVersion platform) { return platform == null ? getDefaultCondition() : new ApiCondition(ApiConverter.convert(platform.value())); } private ApiCondition getDefaultCondition(){ return new ApiCondition(ApiConverter.convert(ApiVersionConstant.DEFAULT_VERSION),true); } } 

ApiAutoConfiguration

 public class ApiAutoConfiguration implements WebMvcRegistrations { @Override public RequestMappingHandlerMapping getRequestMappingHandlerMapping() { return new ApiHandlerMapping(); } } 

ApiAutoConfiguration没有使用Configuration自动注入,而是使用Import带入,目的是可以在程序中选择性启用或者不启用版本控制。

三、原理解析

四、总结

以上就是SpringBoot实现API接口的完整代码的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:SpringBoot实现API接口的完整代码

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址