小编典典

如何使用Spring管理REST API版本管理?

spring

我一直在搜索如何使用Spring 3.2.x管理REST API版本,但没有找到易于维护的东西。我将首先解释我所遇到的问题,然后是一个解决方案……但我确实想知道是否在这里重新发明轮子。

我想基于Accept标头管理版本,例如,如果请求具有Accept标头application/vnd.company.app-1.1+json,我希望spring MVC将其转发到处理此版本的方法。而且由于并非同一版本中的API中的所有方法都发生了变化,所以我不想转到每个控制器并为在版本之间未发生变化的处理程序进行任何更改。我也不想逻辑确定在控制器本身中使用哪个版本(使用服务定位器),因为Spring已经在发现要调用的方法。

因此,采用1.0版至1.8版的API,其中在1.0版中引入了处理程序,并在v1.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;
}

这样,我可以在注释的产生部分中定义封闭或开放的版本范围。我工作的这个解决方案现在,这个问题,我仍然不得不更换一些核心的Spring MVC类(RequestMappingInfoHandlerMapping,RequestMappingHandlerMapping和RequestMappingInfo),我不喜欢,因为这意味着额外的工作,每当我决定升级到较新版本弹簧。

我将不胜感激…尤其是任何以更简单,更易于维护的方式进行此操作的建议。


阅读 445

收藏
2020-04-12

共1个答案

小编典典

无论是否可以通过向后兼容的更改来避免版本控制(当你受到某些公司准则的约束或API客户端以错误的方式实现并且即使不这样做时也会中断),这可能总是不可能的,抽象的需求是一个有趣的一:

我该如何做一个自定义请求映射,以对请求中的标头值进行任意评估,而无需在方法主体中进行评估?

如该SO答案所述,你实际上可以具有相同的@RequestMapping注释,并使用不同的注释来区分运行时发生的实际路由。为此,你将必须:

  1. 创建一个新的注释VersionRange
  2. 实施RequestCondition<VersionRange>。由于你将拥有最佳匹配算法之类的东西,因此你必须检查用其他VersionRange值注释的方法是否可以为当前请求提供更好的匹配。
  3. VersionRangeRequestMappingHandlerMapping根据注释和请求条件实现一个(如如何实现@RequestMapping定制属性一文中所述 )。
  4. 配置spring以便VersionRangeRequestMappingHandlerMapping在使用默认值之前评估你的行为RequestMappingHandlerMapping(例如,将其顺序​​设置为0)。
    这不需要对Spring组件进行任何恶意的替换,而是使用Spring配置和扩展机制,因此即使你更新Spring版本(只要新版本支持这些机制),它也可以正常工作。
2020-04-12