我们将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服务的各个方面的经验,听听其他人学到的东西。
这是一个合理的方法,还是会导致我在这里没有提到的问题?
答案 0 :(得分:0)
这个主题是在JavaOne上提出的,没有正确的答案。
发表上述文章的人说,他的偏好是将版本保留在标题中,并避免将其放在URL中或作为查询参数。
就个人而言,我们自己对文件进行版本控制。无论如何,我们必须部署单独的版本化版本,所以它没有太多额外的麻烦。我们只从Manifest中提取#版本并将?{version}附加到文件中。