SpringBoot API增加version版本号
SpringBoot 增加 API Version
基于restful风格上,增加version版本号
例如: get /api/v1/users/
一、增加ApiVersion自定义注解
作用于Controller上,指定API版本号
这里版本号使用了double ,考虑到小版本的情况,例如1.1
import java.lang.annotation.*;/*** API Version type*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiVersion {/*** api version begin 1*/double version() default 1;
}
二、新增RequestCondition自定义匹配条件
Spring提供RequestCondition接口,用于定义API匹配条件
这里通过自定义匹配条件,识别ApiVersion,进行版本匹配
getMatchingCondition 用于检查URL中,是否符合/v{版本号},用于过滤无版本号接口;
compareTo 用于决定多个相同API时,使用哪个接口进行处理;
import org.springframework.web.servlet.mvc.condition.RequestCondition;import javax.servlet.http.HttpServletRequest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** API version condition* @author w* @date 2020-11-16*/
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {/*** 接口路径中的版本号前缀,如: api/v[1-n]/test*/private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("/v([0-9]+\\.{0,1}[0-9]{0,2})/");/** API VERSION interface **/private ApiVersion apiVersion;ApiVersionCondition(ApiVersion apiVersion){this.apiVersion = apiVersion;}/*** [当class 和 method 请求url相同时,触发此方法用于合并url]* 官方解释:* - 某个接口有多个规则时,进行合并* - 比如类上指定了@RequestMapping的 url 为 root* - 而方法上指定的@RequestMapping的 url 为 method* - 那么在获取这个接口的 url 匹配规则时,类上扫描一次,方法上扫描一次,这个时候就需要把这两个合并成一个,表示这个接口匹配root/method* @param other 相同api version condition* @return ApiVersionCondition*/@Overridepublic ApiVersionCondition combine(ApiVersionCondition other) {// 此处按优先级,method大于classreturn new ApiVersionCondition(other.getApiVersion());}/*** 判断是否成功,失败返回 null;否则,则返回匹配成功的条件* @param httpServletRequest http request* @return 匹配成功条件*/@Overridepublic ApiVersionCondition getMatchingCondition(HttpServletRequest httpServletRequest) {// 通过uri匹配版本号System.out.println(httpServletRequest.getRequestURI());Matcher m = VERSION_PREFIX_PATTERN.matcher(httpServletRequest.getRequestURI());if (m.find()) {// 获得符合匹配条件的ApiVersionConditionSystem.out.println("groupCount:"+m.groupCount());double version = Double.valueOf(m.group(1));if (version >= getApiVersion().version()) {return this;}}return null;}/*** 多个都满足条件时,用来指定具体选择哪一个* @param other 多个时* @param httpServletRequest http request* @return 取版本号最大的*/@Overridepublic int compareTo(ApiVersionCondition other, HttpServletRequest httpServletRequest) {// 当出现多个符合匹配条件的ApiVersionCondition,优先匹配版本号较大的return other.getApiVersion().version() >= getApiVersion().version() ? 1 : -1;}public ApiVersion getApiVersion() {return apiVersion;}
}
三、重写RequestMappingHandlerMapping处理
通过重写 RequestMappingHandlerMapping 类,对RequestMappering进行识别@ApiVersion注解,针对性处理;
这里考虑到有些接口不存在版本号,则使用Spring原来的ApiVersionRequestMappingHandlerMapping继续处理;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import java.lang.reflect.Method;/*** API version setting* @author w* @date 2020-11-15*/
public class ApiVersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {/*** class condition* - 在class上加@ApiVersion注解&url加{version}* @param handlerType class type* @return ApiVersionCondition*/@Overrideprotected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType,ApiVersion.class);return null == apiVersion ? super.getCustomTypeCondition(handlerType) : new ApiVersionCondition(apiVersion);}/*** method condition* - 在方法上加@ApiVersion注解&url加{version}* @param method method object* @return ApiVersionCondition*/@Overrideprotected RequestCondition<?> getCustomMethodCondition(Method method) {ApiVersion apiVersion = AnnotationUtils.findAnnotation(method,ApiVersion.class);return null == apiVersion ? super.getCustomMethodCondition(method) : new ApiVersionCondition(apiVersion);}
}
四、Controller接口增加@ApiVersion注解
通过@ApiVersion注解指定该接口版本号
import com.panda.common.web.controller.BasicController;
import com.panda.common.web.version.ApiVersion;
import com.panda.core.umc.service.UserInfoService;
import com.panda.core.umc.vo.QueryUsersConditionVo;
import com.panda.face.umc.dto.user.QueryUsersReq;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;/*** 用户信息服务* @author w* @date 2020-11-06*/
@RequestMapping("/api")
@RestController
public class UserInfoController extends BasicController{@Autowiredprivate UserInfoService userInfoService;/*** 查询所有用户信息* @param req 查询条件信息*/@ApiVersion@RequestMapping(value = "{version}/users", method = RequestMethod.GET)@ResponseBodypublic ResponseEntity getUsers(@PathVariable("version") String version, QueryUsersReq req){QueryUsersConditionVo condition = new QueryUsersConditionVo();BeanUtils.copyProperties(req,condition);condition.setOrderBy("CREATE_TIME");condition.setSort("DESC");return assemble("1111");}/*** 查询所有用户信息* @param req 查询条件信息*/@ApiVersion(version = 1.1)@RequestMapping(value = "{version}/users", method = RequestMethod.GET)@ResponseBodypublic ResponseEntity getUsersV2(@PathVariable("version") String version, QueryUsersReq req){QueryUsersConditionVo condition = new QueryUsersConditionVo();BeanUtils.copyProperties(req,condition);condition.setOrderBy("CREATE_TIME");condition.setSort("DESC");return assemble("222");}/*** 根据用户ID获取用户信息* @param userId 用户ID*/@RequestMapping(value = "/users/uid/{userId}", method = RequestMethod.GET)@ResponseBodypublic ResponseEntity getUserInfo(@PathVariable("userId") String userId){return assemble(userInfoService.selectByUserId(userId));}
}
五、测试调用
通过访问以下URL,测试返回结果
GET http://127.0.0.1/api/v1/users
GET http://127.0.0.1/api/v1.1/users
GET http://127.0.0.1/api/v1.2/users
GET http://127.0.0.1/api/users/uid/U0001
六、总结
1.通过@ApiVersion注解方式,可以灵活指定接口版本;
2.缺点很明显,需要在URL上加入{version},才能进行匹配成功,这种PathVariable识别过于模糊,后期排查问题增加困难;
3.建议通过包名增加v1/v2明显区分版本,且在controller的URL上直接写死v1版本号,这种更直观;
SpringBoot API增加version版本号相关推荐
- 自动给 Asp.Net Core Api 增加 ApiVersionNeutral
自动给 Asp.Net Core Api 增加 ApiVersionNeutral Intro 新增加一个 Controller 的时候,经常忘记在 Controller 上增加 ApiVersion ...
- 通过Swashbukle给DotNet Core Web API 增加自动文档功能
DotNet Core Web API给开发者提供了一个很好的框架来开发Restful的API.那么这些API接口该如何管理起来呢?Swagger是一个很好的选择,Swagger不需要开发者额外去维护 ...
- 全站课-阶段二(Java SpringBoot API打造高级电商业务后端)
项目目录 missyou ├─github │ └─wxpay │ └─sdk # 微信sdk └─lin└─missyou│ MissyouApplication.java # 启动类├─api│ ...
- itextpdf api帮助文档_我开源了一个小工具,可以帮你轻松生成 SpringBoot API 文档...
前言 大家好,我叫叶大侠,一名独立开发者.这个文档工具是我17年的一个想法,当时还是在公司里面上班,负责App客户端的开发工作,当时后端童鞋写文档的意愿比较低,总是要等他们开发完接口,然后才在微信上沟 ...
- springboot api文档_SpringCloud/SpringBoot - 自动生成API文档
SpringCloud/SpringBoot 的项目一定要前后分离,这就需要一个API文档生成的工具,后端一定要和前端或者是移动端对接接口,那么问题来了,接口是不是要自己写给他们看,一般的会采用Exc ...
- springboot api版本控制_SpringBoot入门练习
一.创建项目出现的问题 问题1.application.yml文件无法识别*解决方法:File->Settions->Plugins目录下选中YAML,重启IDEA 问题2.applica ...
- Kubernetes1.5新特性(一):Kubelet API增加认证和授权能力
2019独角兽企业重金招聘Python工程师标准>>> 背景介绍 在Kubernetes1.5中,对于kubelet新增加了几个同认证/授权相关的几个启动参数,分别是: 认证相关参数 ...
- delphi中的函数传参如何传枚举参数_我是这样使用SpringBoot(API传参)
spring boot 传参 spring boot 中的Controller或者RestController接收参数的方法是一样的.这章目标是对几种常用的传参都写个例子. 创建package: co ...
- springboot的api_【粉丝投稿】无需额外注解的 SpringBoot API文档生成工具
点击上方"蓝字"关注我们吧! JApiDocs是一个无需额外注解.开箱即用的SpringBoot接口文档生成工具. 编写和维护API文档这个事情,对于后端程序员来说,是一件恼人但又 ...
最新文章
- vim/vi的使用(Ubuntu12.04)
- dbvis 数据库连接工具-更新数据库驱动方法示例演示,驱动与数据库版本不匹配问题:Unknown system variable ‘query_cache_size‘解决方法
- C++ new delete(二)
- 微软宣布公开预览Dev Spaces for AKS
- linux查看关键词前后几行内容
- python中scrapy可以爬取多少数据_python中scrapy框架爬取携程景点数据
- [新思路]Online DVD Rental! 美国在线DVD租赁
- 【Nginx那些事】nginx配置实例(三)动静分离
- linux 下自动重启tomcat的脚本(支持shell杀进程)
- 在shop++二次开发中金额数据类型BigDecimal转换,注意细节。
- (12)自定义数据流(实战Docker事件推送的REST API)——响应式Spring的道法术器...
- Python编程手册系列 - 日历、日期、时间相关内建模块详解
- lgv30刷android10,记一次LG V30系列手机完美刷入MIUI12系统和Flyme刷机教程
- SpringBoot-refresh解析
- Java图形界面文字乱码
- android隐藏虚拟按键的几种方式
- java 男女 相邻交换 队形_调整队形+上机编程调整男孩女孩顺序
- day199-2019-01-05-英语流利阅读-待学习
- 盘点世界十大著名黑客攻击事件
- java time_java常用类Time
热门文章
- 详细讲解 —— 操作符(C语言初阶)(万字长文)
- vue数组刷新_Vue数组更新方法
- Vue数组更新相关方法和过滤与排序的使用
- 【vue前端】Echarts 3D地球 照片显示白球该如何处理+ 地球模型+ 简单前端登录页面 +数字时钟组件
- 软工实践第十次作业-项目评测
- 深度学习第一周 tensorflow实现mnist手写数字识别
- 转贴一篇:《不尽阑珊----阿休罗的眼泪》
- A Mobility Model Based on Improved Artificial Potential Fields for Swarms of UAVs(论文翻译)
- embed autopaly=false失效
- 美国97岁喜剧演员拥豪宅每天沿街乞讨