面向未来的RESTful Web服务的各个方面

时间:2012-10-05 05:24:04

标签: api rest versioning jax-rs resteasy

我们将REST Web服务视为一种“面向未来”的业务方式。我正在考虑各种版本化REST Web服务的方法的权衡,我想了解其他人在REST Web服务版本化方面学到了什么。

在SO和其他地方有很多关于版本化Web服务的讨论,但大多数讨论的重点是是将版本号放在URL还是请求标题中。

版本控制Web服务有多个方面。在Web服务调用本身(URL或标头)中指定了版本。在源代码中管理多个版本的业务逻辑。有建筑版本的Web服务。有版本控制问题。还有一个问题是如何弃用和删除过时的版本。

我们编写移动客户端的合作伙伴希望将版本放在URL中,这是我的方法(目前)。此外,这些Web服务的新版本可能与旧版本不兼容。例如,不同版本中可能存在不同的安全实现。

当涉及版本化URL时,通常会建议两种方法 - 将版本号放在URL中或使其成为参数

context-root/service/rest/v0.1/restMethod/param1

context-root/service/rest/restMethod/param1?version=v0.1

第二种方法需要一些控制器逻辑将请求路由到正确的实现,但这并不困难。两者之间的选择并不困难。

第三个选项是将版本号放在context-root本身,这意味着将它放在.war文件名前缀或部署描述符中:

restarchive-v0.1/service/rest/restMethod/param1

这意味着为当前支持的所有版本部署多个存档。

我喜欢文件名中的版本号。它可以很容易地看到部署的内容。这种方法的缺点是它需要为每个版本化的存档单独构建,可能需要maven配置文件。

这是第一种方法的代码可能是什么样子。每个Web方法都为该方法的所有受支持版本执行自己的控制器逻辑。每个版本的业务逻辑都可以以合理的方式处理(即将版本号放在包中)。

    @ApplicationPath("/service/rest")
    @Path("/{version}/")
    public class RestService extends Application {

    @GET
    @Path("/user/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public User getUser(@PathParam("version") String version, @PathParam("id") int id) {

        User user;
        if (version.equals("v0.1")) {
            //  call v0.1 code to get the User
         }
         else if (version.equals("v0.2")) {
            //  call v0.2 code to get the User
         }
         else {

             throw new WebApplicationException(Response.Status.NOT_FOUND);
         }

         return user;
    }

}

我的第一次实现使用了包含版本号的不同包中的javax.ws.rs.core.Application的多个子类。这应该有效,但JBoss RESTeasy实现不允许在一个.war中使用Application的多个子类。这显然违反了JAX-RS 1.1规范,但如果您使用JBoss或RESTeasy,那么它将是您必须忍受的限制。

我倾向于使用第一种方法,其实现类似于上面的方法。由于我试图在将来最小化问题,我希望通过对版本Web服务的各个方面的经验,听听其他人学到的东西。

这是一个合理的方法,还是会导致我在这里没有提到的问题?

1 个答案:

答案 0 :(得分:0)

这个主题是在JavaOne上提出的,没有正确的答案。

发表上述文章的人说,他的偏好是将版本保留在标题中,并避免将其放在URL中或作为查询参数。

就个人而言,我们自己对文件进行版本控制。无论如何,我们必须部署单独的版本化版本,所以它没有太多额外的麻烦。我们只从Manifest中提取#版本并将?{version}附加到文件中。