java 处理 JAX-RS REST API URI 版本控制的最佳方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14827222/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to handle JAX-RS REST API URI versioning
提问by Deepesh M
I did my search first in stackoverflow & I was not able to find out any answers related to my question. All I can find was questions related to REST uri design.
我首先在 stackoverflow 中进行了搜索,但找不到与我的问题相关的任何答案。我能找到的只是与 REST uri 设计相关的问题。
My question in on the backend side. Suppose we have two different version of REST uri's
我的问题在后端。假设我们有两个不同版本的 REST uri
http://api.abc.com/rest/v1/products
http://api.abc.com/rest/v1/products
http://api.abc.com/rest/v2/products
http://api.abc.com/rest/v2/products
What is the best approach to follow on the backend side (server side code) for proper routing, manageability & reuse of the existing classes across these two set of api's based on version?
在后端(服务器端代码)遵循基于版本的这两组 api 中现有类的正确路由、可管理性和重用的最佳方法是什么?
I have thought of approach to define resource classes with different @Path annotations for e.g. have a package for v1 & v2 separately & in ProductsResource class of that package, define
我想过定义具有不同@Path 注释的资源类的方法,例如分别为 v1 和 v2 提供一个包,并在该包的 ProductsResource 类中定义
package com.abc.api.rest.v1.products;
@Path("/rest/v1/products")
public class ProductsResource {...}
package com.abc.api.rest.v2.products;
@Path("/rest/v2/products")
public class ProductsResource {...}
& then have the implementation logic based on the versions. The problems with this approach is when we are only changing one particular resource api from the set of api's, we have to copy other classes to the v2 package also. Can we avoid it?
&然后有基于版本的实现逻辑。这种方法的问题在于,当我们只更改一组 api 中的一个特定资源 api 时,我们还必须将其他类复制到 v2 包中。我们能避免吗?
How about to write a custom annotation say @Version & have values of the versions it supports? Now whether it is v1 or v2, both request will go to same resource class.
写一个自定义注释怎么样 @Version 并拥有它支持的版本的值?现在无论是 v1 还是 v2,两个请求都将转到同一个资源类。
Say for e.g.
说例如
package com.abc.api.rest.products;
@Path("/rest/{version: [0-9]+}/products")
@Version(1,2)
public class ProductsResource {...}
UPDATE:
更新:
There was a API versioning suggestion by Jarrod to handle version in headers. That's also one way to do it however, I am looking forward for best practices to use when we are following URI based versioning
Jarrod 有一个 API 版本控制建议来处理标头中的版本。这也是一种方法,但是,当我们遵循基于 URI 的版本控制时,我期待使用最佳实践
回答by Deepesh M
The problem with putting it in the URL is that the URL is supposed to represent a resource by location. An API Version is not a location and it not part of the identifier of the resource.
将它放在 URL 中的问题在于 URL 应该按位置表示资源。API 版本不是位置,也不是资源标识符的一部分。
Sticking /v2/
in the URL breaks all existing links that came before.
粘贴/v2/
URL 会破坏之前出现的所有现有链接。
There is one correct way to specify API versioning:
有一种正确的方法来指定 API 版本控制:
Put it in the mime-type for the Accept:
header that you want. Something like Accept: application/myapp.2.0.1+json
把它放在Accept:
你想要的标题的 mime-type 中。就像是Accept: application/myapp.2.0.1+json
Chain of Responsiblitypattern goes well here especially if there will be significant number of API versions that are different enough to have to have their own handler, that way methods don't get out of hand.
责任链模式在这里运行得很好,特别是如果有大量不同的 API 版本必须有自己的处理程序,这样方法就不会失控。
回答by David Dossot
This blog post has an example of what is considered the by some to be the correct approach, i.e. not having the version in the URI: http://codebias.blogspot.ca/2014/03/versioning-rest-apis-with-custom-accept.html
这篇博客文章有一个例子,说明了一些人认为正确的方法,即 URI 中没有版本:http: //codebias.blogspot.ca/2014/03/versioning-rest-apis-with- custom-accept.html
In short, it leverages JAX-RS @Consume
annotation to associate the request for a particular version to a specific implementation, like:
简而言之,它利用 JAX-RS@Consume
注释将特定版本的请求与特定实现相关联,例如:
@Consumes({"application/vnd.blog.v1+xml", "application/vnd.blog.v1+json"})
回答by Chetya
I was just wondering why not have a subclass of ProductService called
我只是想知道为什么没有一个名为 ProductService 的子类
@Path(/v2/ProductService)
ProductServiceV2 extends ProductService {
}
@Path(/v1/ProductService)
class ProductService{
}
and only override whatever is changed in v2. Everything unchanged will work the same as in v1/ProductService.
并且只覆盖 v2 中更改的任何内容。未更改的所有内容将与 v1/ProductService 中的相同。
This defintely leads to more # of classes but is one easier way of coding for only whatever is changing in the new version of api and reverting to the old version without duplicating code.
这绝对会导致更多的类,但这是一种更简单的编码方式,仅针对新版本 api 中发生的变化进行编码,并在不复制代码的情况下恢复到旧版本。