gpt4 book ai didi

java - REST Web 服务版本控制实践

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:08:39 24 4
gpt4 key购买 nike

我正在创建一个新的网络服务,我已经阅读了一些来自 APIgee 的电子书,其中建议对网络服务进行版本控制。我知道在 URL 和 header 中保留版本控制信息之间存在一些“斗争”。根据我所阅读和理解的内容,我想在 header 中使用版本控制。

我的问题是;这在实践中看起来如何?我正在使用 Spring MVC 3.2。您是否只是在响应不同版本的同一 Controller 中创建这样的方法?

版本 1:

@RequestMapping(method = RequestMethod.GET, produces = "application/vnd.example-v1+json")

版本 2:

@RequestMapping(method = RequestMethod.GET, produces = "application/vnd.example-v2+json")

或者这是错误的?或者更常见的是创建包含不同版本 Controller 的不同包?还是有其他方法?

最佳答案

这里的问题不在于版本信息所在的位置(URI 与 header ),而在于如何为不同版本组织代码。

我怀疑是否存在单一的标准方法。这仅取决于版本的不同程度。

简单的格式更改。例如,假设唯一的区别是您从 V1 中的 XML 移动到 V2 中的 JSON。在那种情况下,您可以使用完全相同的代码,但只需将应用配置为全局输出 JSON。不需要不同的包或 Controller 。 (例如,您可以使用 JAXB 注释来驱动 XML 和 Jackson 生成的 JSON 输出。)

适度的架构更改。假设 V2 引入了少量破坏性架构更改。在这种情况下,在它上面创建新包可能没有意义。您的 Controller 中可能只有简单的条件逻辑来处理/提供版本的正确表示。

主要架构更改。如果您的架构更改很深且范围很广,您可能需要的不仅仅是单独的 Controller 。您甚至可能需要不同的域模型(实体/服务)。在这种情况下,为 Controller 一直到实体、存储库甚至数据库表提供一组并行的包可能很有意义。

应用这些想法

方法 1. 将这些想法应用到您的 @RequestMapping 示例中,您可以按照您在那里所说的去做,但是如果版本之间的响应完全相同,那么它们应该只需委托(delegate)给一个共享方法:

@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 方法的方法级注释的 Controller (仅定义了 valuemethod,但没有定义 produces)。然后使用扩展基础的特定于版本的扩展,其中扩展 Controller 在类级别具有 @RequestMapping(value = "/orders", produces = "application/vnd.example-v1") .然后仅覆盖版本和基线之间的增量。 我不确定这是否可行,但如果可行,这将是组织 Controller 的一种非常干净的方式。这就是我的意思:

// 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);
}
}

关于java - REST Web 服务版本控制实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18936264/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com