使用Spring实现REST Api实现

时间:2013-05-22 13:32:50

标签: java spring spring-mvc

编写RESTFul api应用程序的最佳实践之一是添加版本控制。例如:

http://my-server/api/v1/getData
http://my-server/api/v2/getData

我们的应用程序使用Spring框架公开REST api。我们将类标记为Controller,使用RequestMapping注释将URL映射到函数,并添加一些转换为json对象的对象。

例如:

@RequestMapping(method = RequestMethod.POST, value = "/api/v1/getData")
public @ResponseBody ResponseDataDTO getData(@RequestBody OperationsDetailsTDO details) {...}

现在,我们要提供API的第二个版本。大约2/3的功能保持不变,并且1/3正在改变。这些更改都在逻辑和JSON对象中。

我想知道如何设计代码。我认为这种代码难以管理:

@RequestMapping(method = RequestMethod.POST, value = "/api/{version-var}/getData")
public @ResponseBody ResponseDataDTO createReleaseFromTemplate(@PathVariable("version-var") Integer version, @RequestBody OperationsDetailsTDO details) {
if (version == 1)
{
   doForVersion1();
}
else if (version == 2)
{
   doForVersion2();
}

}

管理起来很困难,因为在每个功能中都会有不同的分支。为了证明这个问题,如果我有一个生成文档的自动工具 - 它将无法理解什么是API。

其次,我想知道如何处理绑定到JSON对象的类。我是否需要复制所有这些类,以进行微小的更改?

THX。

2 个答案:

答案 0 :(得分:1)

我同意你将版本作为参数传递,就像

一样
@RequestMapping(method = RequestMethod.POST, value = "/api/{version-var}/getData")

但我不认为添加大量分支是个好主意, 我们应该将资源类中的所有方法提取到业务接口,例如

private IDataRetrieve dataRetriever;
@RequestMapping(method = RequestMethod.POST, value = "/api/{version-var}/getData")
public @ResponseBody ResponseDataDTO createReleaseFromTemplate(@PathVariable("version-var") Integer version, @RequestBody OperationsDetailsTDO details) {
    dataRetiever = DataRetrieverFactory.getDataTrieverByVersion(version);  //TODO, create a factory to get DataRetriever
    return dataRetiever.getData();
}

然后你需要两个分类来实现IDataRetriver,(一个用于V1,另一个用于v2);为了避免重复代码,您可以为V1和V2添加一个抽象类,并使用Template Patern删除重复的代码。

答案 1 :(得分:0)

如果对版本(see here for example)使用路径变量,则可以在RequestMapping中使用正则表达式。或者,您可以创建一个新方法,只需调用旧方法,但具有较新的RequestMapping for v2。或者,创建一个抓取版本的通用方法,并调用实际处理该版本请求的正确方法。最后一种方法的奖励:如果他们发送的版本不受支持,您可以获取版本并将用户发送到特定错误,例如,如果他们发送/ app / v10 /等等。