我们将 REST Web 服务视为一种“面向未来”我们的业务的方式,等等。我正在考虑对 REST Web 服务进行版本控制的各种方法的权衡,我想了解其他人在对 REST Web 服务进行版本控制时学到了什么。
关于 SO 和其他地方有很多关于版本控制 Web 服务的很好的讨论,但大多数都集中在是否将版本号放在 URL 或请求标头中。
版本控制 Web 服务有多个方面。在 Web 服务调用本身(URL 或标头)中指定了版本。在源代码中管理多个版本的业务逻辑。正在构建版本化的 Web 服务。存在版本控制问题。还有如何弃用和删除过时版本的问题。
我们正在编写移动客户端的合作伙伴希望将版本放在 URL 中,这就是我的方法(目前)。此外,这些网络服务的新版本可能与旧版本不兼容。例如,不同版本中可能有不同的安全实现。
当涉及到版本化 URL 时,通常建议使用两种方法 - 将版本号放在 URL 中或将其作为参数
context-root/service/rest/v0.1/restMethod/param1
context-root/service/rest/restMethod/param1?version=v0.1
第二种方法需要一些控制器逻辑来将请求路由到正确的实现,但这并不难。两者之间的选择并不难。
第三种选择是将版本号放在上下文根本身中,这意味着将其放在 .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 服务的各个方面的经验学到了什么。
这是一种合理的方法,还是会导致我在这里没有提到的问题?