Luc*_*uke 9 java rest spring spring-mvc java-ee
我正在创建一个新的Web服务,我已经阅读了一些来自APIgee的电子书,其中建议对Web服务进行版本控制.我知道在URL和标题之间保持版本信息之间存在一些"争执".根据我的阅读和理解,我想在标题中使用版本控制.
我的问题是; 这在实践中看起来如何?我正在使用Spring MVC 3.2.你是否只是在同一个控制器中创建这样的方法来响应不同的版本?
版本1:
@RequestMapping(method = RequestMethod.GET, produces = "application/vnd.example-v1+json")
Run Code Online (Sandbox Code Playgroud)
版本2:
@RequestMapping(method = RequestMethod.GET, produces = "application/vnd.example-v2+json")
Run Code Online (Sandbox Code Playgroud)
或者这是错的?或者更常见的是创建包含不同版本控制器的不同包?或者还有其他方法吗?
Wil*_*ler 19
这里的问题不是版本信息所在的位置(URI与标题),而是关于如何为不同版本组织代码的更多信息.
我怀疑有一种标准方法.它只取决于版本的不同.
简单的格式更改.例如,假设您唯一的区别是您从V1中的XML移动到V2中的JSON.在这种情况下,您可以使用完全相同的代码,但只需将应用程序配置为全局输出JSON.不需要不同的包或控制器.(例如,您可以使用JAXB注释来驱动XML和Jackson生成的JSON输出.)
适度的架构更改.假设V2引入了少量重大架构更改.在这种情况下,在它上面创建新包可能没有意义.您可能只需要在控制器中使用简单的条件逻辑来处理/提供版本的正确表示.
主要架构更改.如果您的架构更改很深且范围很广,那么您可能需要的不仅仅是单独的控制器.您甚至可能需要不同的域模型(实体/服务).在这种情况下,为控制器提供一组并行的包可能是有意义的,直到实体,repos甚至数据库表.
方法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);
}
Run Code Online (Sandbox Code Playgroud)
这样的东西会起作用.如果版本之间的订单不同,那么您可以在方法中实现差异.
方法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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8457 次 |
| 最近记录: |