我一直在寻找如何使用Spring3.2.x管理REST API版本,但我没有找到任何易于维护的东西。我将首先解释我所遇到的问题,然后提出一个解决方案...但我真的想知道我是不是在重新发明轮子。
我希望根据Accept标头管理版本,例如,如果请求具有Accept标头application/vnd.company.app-1.1+json
,我希望spring MVC将其转发到处理此版本的方法。由于并非API中的所有方法在同一版本中都会发生变化,因此我不想去每个控制器那里,为一个在不同版本之间没有变化的处理程序更改任何东西。我也不想让逻辑去找出在控制器中使用哪个版本(使用服务定位器),因为Spring已经发现了要调用的方法。
因此,以1.0到1.8版本的API为例,在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;
}
这在spring中是不可能的,因为这两个方法具有相同的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;
}
通过这种方式,我可以在注释的produces部分定义封闭或开放的版本范围。我现在正在致力于这个解决方案,问题是我仍然必须替换一些核心的spring MVC类(RequestMappingInfoHandlerMapping
、RequestMappingHandlerMapping
和RequestMappingInfo
),这是我不喜欢的,因为每当我决定升级到更新版本的Spring时,这意味着额外的工作。
如果你有任何想法我将不胜感激。特别是,任何以更简单、更容易维护的方式完成此操作的建议。
编辑
添加赏金。要获得赏金,请回答上面的问题,而不是建议在控制器中包含此逻辑。Spring已经有了很多逻辑来选择要调用的控制器方法,我想利用这一点。
编辑2
我已经在github中分享了原始的POC (有一些改进):https://github.com/augusto/restVersioning
https://stackoverflow.com/questions/20198275
复制相似问题