我一直在寻找如何使用 Spring 3.2.x 来管理 REST API 版本,但是我没有找到任何易于维护的东西。我会先解释我的问题,然后是解决方案... 但我不知道我是不是在重新发明轮子。
我希望基于 Accept 头来管理这个版本,例如,如果一个请求有 Accept 头 application/vnd.company.app-1.1+json
,我希望 Spring MVC 将其转发到处理这个版本的方法。由于 API 中的所有方法并非都在同一个版本中发生变化,因此我不希望转到每个控制器,为一个在不同版本之间没有变化的处理程序更改任何内容。我也不想用逻辑来确定在控制器中使用哪个版本(使用服务定位器) ,因为 Spring 已经发现了要调用哪个方法。
因此,使用版本1.0的 API 到版本1.8,其中在版本1.0中引入了一个处理程序,并在版本1.7中进行了修改,我希望用以下方式处理这个问题。假设代码在一个控制器中,并且有一些代码能够从头部提取版本。(以下内容在 Spring 中无效)
@RequestMapping(...)
@VersionRange(1.0,1.6)
@ResponseBody
public Object method1() {
// so something
return object;
}
@RequestMapping(...) //same Request mapping annotation
@VersionRange(1.7)
@ResponseBody
public Object method2() {
// so something
return object;
}
这在春季是不可能的,因为这两个方法有相同的 RequestMapping
注释,而 Spring 无法加载。其思想是 VersionRange
注释可以定义一个打开或关闭的版本范围。第一种方法适用于1.0到1.6版本,而第二种方法适用于1.7以后的版本(包括最新的1.8版本)。我知道,如果有人决定通过99.99版本,这种方法就会失效,但我可以接受。
现在,如果没有对 Spring 的工作原理进行认真的修改,上面的内容是不可能实现的,我正在考虑修改处理程序与请求匹配的方式,特别是编写我自己的 ProducesRequestCondition
,并在其中设置版本范围。比如说
密码:
@RequestMapping(..., produces = "application/vnd.company.app-[1.0-1.6]+json)
@ResponseBody
public Object method1() {
// so something
return object;
}
@RequestMapping(..., produces = "application/vnd.company.app-[1.7-]+json)
@ResponseBody
public Object method2() {
// so something
return object;
}
通过这种方式,我可以在注释的生成部分中定义关闭或打开的版本范围。我现在正在研究这个解决方案,问题是我仍然需要替换一些核心的 Spring MVC 类(RequestMappingInfoHandlerMapping
、 RequestMappingHandlerMapping
和 RequestMappingInfo
) ,这是我不喜欢的,因为当我决定升级到一个新版本的 Spring 时,这意味着额外的工作。
我会很感激任何想法... 特别是,任何建议这样做,在一个更简单,更容易维护的方式。
增加赏金。要获得奖金,请回答上面的问题,而不要建议在控制器本身有这种逻辑。Spring 已经有很多逻辑来选择调用哪个控制器方法,我想借鉴一下。
我已经在 github: https://github.com/augusto/restVersioning中分享了原始的 POC (做了一些改进)