Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java RESTWeb服务版本控制在实践中的应用_Java_Spring_Rest_Jakarta Ee_Spring Mvc - Fatal编程技术网

Java RESTWeb服务版本控制在实践中的应用

Java RESTWeb服务版本控制在实践中的应用,java,spring,rest,jakarta-ee,spring-mvc,Java,Spring,Rest,Jakarta Ee,Spring Mvc,我正在创建一个新的web服务,我已经阅读了APIgee的一些电子书,其中推荐对web服务进行版本控制。我知道在URL和标题中保留版本控制信息之间存在一些“战斗”。根据我的阅读和理解,我希望在标题中使用版本控制 我的问题是,;这在实践中是什么样子?我使用的是SpringMVC3.2。您是否只是在同一个控制器中创建这样的方法,以响应不同的版本 第1版: @RequestMapping(method = RequestMethod.GET, produces = "application/vnd.ex

我正在创建一个新的web服务,我已经阅读了APIgee的一些电子书,其中推荐对web服务进行版本控制。我知道在URL和标题中保留版本控制信息之间存在一些“战斗”。根据我的阅读和理解,我希望在标题中使用版本控制

我的问题是,;这在实践中是什么样子?我使用的是SpringMVC3.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引入了少量中断的模式更改。在这种情况下,在其上创建新包可能没有意义。控制器中可能只有简单的条件逻辑来处理/服务版本的正确表示

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

应用这些想法 方法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方法的方法级注释(只定义了
方法
,而不是
生成
)。然后使用扩展基础的特定于版本的扩展,扩展控制器在类级别具有
@RequestMapping(value=“/orders”,products=“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);
    }
}

这是有道理的。谢谢:)