时间:2021-05-20
一、简介
产品迭代过程中,同一个接口可能同时存在多个版本,不同版本的接口URL、参数相同,可能就是内部逻辑不同。尤其是在同一接口需要同时支持旧版本和新版本的情况下,比如APP发布新版本了,有的用户可能不选择升级,这是后接口的版本管理就十分必要了,根据APP的版本就可以提供不同版本的接口。
二、代码实现
本文的代码实现基于SpringBoot 2.3.4-release
1.定义注解
ApiVersion
value值默认为1.0.0
EnableApiVersion
/** * 是否开启API版本控制 */@Target(ElementType.TYPE)@Documented@Retention(RetentionPolicy.RUNTIME)@Import(ApiAutoConfiguration.class)public @interface EnableApiVersion {}在启动类上添加这个注解后就可以开启接口的多版本支持。使用Import引入配置ApiAutoConfiguration。
2.将版本号抽象为ApiItem类
ApiItem
为了比较版本号的大小,实现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
以上对RequestCondition简要说明,后续详细源码分析各个方法的作用。
ApiCondition
@Slf4jpublic class ApiCondition implements RequestCondition<ApiCondition> { 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> * Spring先扫描方法再扫描类,然后调用{@link #combine} * 按照方法上的注解优先级大于类上注解的原则处理,但是要注意如果方法上不定义注解的情况。 * 如果方法或者类上不定义注解,我们会给一个默认的值{@code empty},{@link ApiHandlerMapping} * </pre> * @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(ApiVersionConstant.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) { throw new IllegalArgumentException(String.format("API版本[%s]错误,最低版本[%s]", version, ApiVersionConstant.DEFAULT_VERSION)); } if (item.compareTo(this.version) >= 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); }}ApiAutoConfigurationpublic class ApiAutoConfiguration implements WebMvcRegistrations { @Override public RequestMappingHandlerMapping getRequestMappingHandlerMapping() { return new ApiHandlerMapping(); }}ApiAutoConfiguration没有使用Configuration自动注入,而是使用Import带入,目的是可以在程序中选择性启用或者不启用版本控制。
总结
到此这篇关于SpringBoot实现API接口多版本支持的示例代码的文章就介绍到这了,更多相关SpringBoot API多版本支持内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
这篇文章主要介绍了SpringBoot如何使用feign实现远程接口调用和错误熔断,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
1.首先用springboot构建一个简单的dubbo测试程序,并引入相关依赖编写公共接口api编写provider实现UserSvice的方法,并暴露服务编写
1,支持群发(如果需要群发多号用英文逗号(,)分隔(159..,159..))2,支持POST或GET方式提交数据本站接口:http://api.heqee.c
问题springboot集成springcloud时常常由于版本问题而报错,如下:com.sun.jersey.api.client.ClientHandler
本文介绍了Maven工程搭建springboot+springmvc+JPA的示例,分享给大家,具体如下:添加Springboot支持,引入相关包:1、mave