一、问题

  软件开发过程中,常常会需要变更以前的接口,添加或删除接口请求字段,接口字段校验、甚至是变更请求/返回字段名称,如果强制要求所有客户端跟着一起升级代价太大。如果接口从一开始就考虑到了版本的设计,那么做到平滑升级就很容易了。

二、版本控制方式

1、利用url传入版本

以@RequestMapping("/api")controller为例:

在路径里传入版本号:

优点:可以做到大版本切换,路由下的所有接口同时更新

缺点:实际中往往不会涉及很多接口同时升级,并且往往难以控制不同接口的版本(版本管理容易混乱)

    /**
* http://localhost:8090/api/v1/getUser/111
* {"userId":111,"userName":"小明"}
*
* @param userId
* @return
*/
@RequestMapping(value = "/v1/getUser/{userId}")
public GetUserV1Response getUserInfoV1(@PathVariable("userId") Integer userId) {
return new GetUserV1Response(userId, "小明");
}

通过参数传入(POST 或 GET)

可以单独控制,注意version不存在和乱传值的处理

    /**
* http://localhost:8090/api/getUser/111?version=v1
* {"userId":111,"userName":"小明"}
* <p>
* http://localhost:8090/api/getUser/111?version=v2
* {"userId":111,"userName":"小明","notes":"version 2"}
*
* @param userId
* @return
*/
@RequestMapping(value = "/getUser/{userId}")
public Object getUserInfo(@PathVariable("userId") Integer userId, @RequestParam("version") String version) {
if ("v1".equals(version)) {
return new GetUserV1Response(userId, "小明");
}
return new GetUserV2Response(userId, "小明", "version 2");
}

2、利用request header

以@RequestMapping("/api2")controller为例:

header设置在Controller或Action上都可以,设置在Controller上,控制所有Action的版本,设置在Action上,单独控制一个Action的版本

@RestController
@RequestMapping(value = "/api2")
public class ApiVersionHeaderDemoController {
@Autowired
private HttpServletRequest request; //request header
@RequestMapping(value = "/getUserById/{userId}", headers = "version=v2")
public Object getUserInfo(@PathVariable("userId") Integer userId) {return new GetUserV2Response(userId, "小明", "version 2");
}
}

对应版本:

不支持的版本:

3、利用content type

利用自定义请求的Content-Type来控制版本:

    /**
* 请求的是 application/vnd.apiversioncontrol.v1+json
* 返回的是 application/json;charset=UTF-8
* v1 是api版本
*
* @param userId
* @return
*/
@RequestMapping(value = "/getUserById/{userId}", consumes = "application/vnd.apiversioncontrol.v1+json")
public Object getUserInfoV11(@PathVariable("userId") Integer userId) {
return new GetUserV2Response(userId, "小明", "version 2");
}

返回的是Content-Type:application/json;charset=UTF-8(不指定produces,默认是application/json;charset=UTF-8)

同时指定request和response的Content-Type为:application/vnd.apiversioncontrol.v2+json

    /**
* 请求、返回Content-Type都是 application/vnd.apiversioncontrol.v1+json
* v1 :为api版本
*
* @param userId
* @return
*/
@RequestMapping(value = "/getUserById/{userId}", consumes = "application/vnd.apiversioncontrol.v2+json", produces = "application/vnd.apiversioncontrol.v2+json")
public Object getUserInfoV12(@PathVariable("userId") Integer userId) {
return new GetUserV2Response(userId, "小明", "version 2");
}

同时指定request和response的Content-Type为:application/vnd.apiversioncontrol+json;version=v2

    /**
* 请求、返回Content-Type都是 application/vnd.apiversioncontrol+json;version=v2
* v2 :为api版本
*
* @param userId
* @return
*/
@RequestMapping(value = "/getUserById/{userId}", consumes = "application/vnd.apiversioncontrol+json;version=v2", produces = "application/vnd.apiversioncontrol+json;version=v2")
public Object getUserInfoV2(@PathVariable("userId") Integer userId) {
return new GetUserV2Response(userId, "小明", "version 2");
}

三、注解实现

注解来实现:SpingMVC框架实现restfull接口的版本控制

参考:webapi-version-control

最新文章

  1. notepad++ 配置Python 调试环境 实用版
  2. OPRNGL总结(一)OPENGL的理论原理
  3. linux 常用的酷炫命令
  4. 解决tableViewCell分割线不到左边界的问题
  5. 记录linux系统下所有用户的操作信息
  6. sed 替换
  7. POJ 2516 Minimum Cost 最小费用流
  8. [转] “error LNK2019: 无法解析的外部符号”之分析
  9. ModelState.IsValid一直为false的原因
  10. 前端学PHP之Session
  11. PHP 错误 系列:编码格式错误解决
  12. Windows 与 Linux下关于端口不能访问的问题
  13. GIt如何安装使用
  14. poj-1195(二维树状数组)
  15. 从商业角度探讨API设计
  16. 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)
  17. redis升级注意事项
  18. 《AngularJS即学即用》读书笔记(一)
  19. 计算方法 -- 解线性方程组直接法(LU分解、列主元高斯消元、追赶法)
  20. 前端(一):html标签

热门文章

  1. JSP小例子——实现用户登录小例子(不涉及DB操作)
  2. Java中分页功能源码实例
  3. echart使用总结
  4. 第十一课——codis-server的高可用,对比codis和redis cluster的优缺点
  5. Cookies, Security, and Privacy Client Identification
  6. PHP_OS常量使用方法
  7. python基础-第三篇-函数编程
  8. NFS服务基础
  9. Flowers---hdu4325(区间处理 离散化)
  10. 在linux上配置Django项目