我正在创建一个新的Web服务,并且已经阅读了APIgee的一些电子书,其中建议对Web服务进行版本控制。我知道将版本控制信息保留在URL与标头之间存在一些“争斗”。通过阅读和理解,我想在标题中使用版本控制。
我的问题是;实际情况如何?我正在使用Spring MVC 3.2。您是否只是在响应不同版本的同一控制器中创建了这样的方法?
版本1:
@RequestMapping(method = RequestMethod.GET, produces = "application/vnd.example-v1+json")
版本2:
@RequestMapping(method = RequestMethod.GET, produces = "application/vnd.example-v2+json")
还是这是错误的?还是创建包含不同版本控制器的不同软件包的更常见的做法?还是有其他方法?
这里的问题与版本信息的存放位置(URI与标头)无关,而与如何组织不同版本的代码有关。
我怀疑是否有单一的标准方法。这仅取决于版本的差异。
简单的格式更改。例如,假设唯一的区别是您从V1中的XML迁移到V2中的JSON。在这种情况下,您可以使用完全相同的代码,但只需将应用程序配置为全局输出JSON。无需使用其他程序包或控制器。(例如,您可以使用JAXB注释来驱动XML和Jackson生成的JSON输出。)
适度的架构更改。假设V2引入了少量重大的架构更改。在这种情况下,在上面创建新包可能没有意义。您的控制器中可能只具有简单的条件逻辑,即可处理/提供版本的正确表示。
主要模式更改。如果您的模式更改很深远,那么您可能需要的不只是单独的控制器。您甚至可能需要其他域模型(实体/服务)。在这种情况下,对于控制器一直到实体,存储库甚至数据库表,都有一组并行的软件包是很有意义的。
方法1.将这些想法应用到@RequestMapping
示例中,您可以按照此处所说的做,但是如果版本之间的响应完全相同,则它们应仅委托给一个共享方法:
@RequestMapping(
value = "/orders/{id}",
method = RequestMethod.GET,
produces = "application/vnd.example-v1")
@ResponseBody
public Order getOrderV1(@PathVariable("id") Long id) {
return getOrder(id);
}
@RequestMapping(
value = "/orders/{id}",
method = RequestMethod.GET,
produces = "application/vnd.example-v2")
@ResponseBody
public Order getOrderV2(@PathVariable("id") Long id) {
return getOrder(id);
}
private Order getOrder(Long id) {
return orderRepo.findOne(id);
}
这样的事情会起作用。如果版本之间的顺序不同,则可以直接在方法中实现差异。
方法2。您可能要尝试的另一件事-我自己也没有尝试过-每个资源类型(例如订单,产品,客户等)都有自己的基本控制器,并带有HTTP方法的方法级别注释(只是value
和method
定义,但没有produces
)。然后,使用特定于版本的扩展来扩展基础,其中扩展控制器@RequestMapping(value = "/orders", produces = "application/vnd.example-v1")
在类级别具有。然后仅覆盖版本和基准之间的增量。我不确定这是否行得通,但是如果这样的话,这将是组织控制器的一种非常干净的方法。这就是我的意思:
// The baseline
public abstract class BaseOrderController {
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@ResponseBody
public Order getOrder(@PathVariable("id") Long id) { ... }
}
// V1 controller
@RequestMapping(value = "/orders", produces = "application/vnd.example-v1")
public class OrderControllerV1 extends BaseOrderController {
... no difference from baseline, so nothing to implement ...
}
// V2 controller
@RequestMapping(value = "/orders", produces = "application/vnd.example-v2")
public class OrderControllerV2 extends BaseOrderController {
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@ResponseBody
@Override
public Order getOrder(@PathVariable("id") Long id) {
return orderRepoV2.findOne(id);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句