Vol*_*kur 11 java versioning rest jax-rs jersey
REST资源版本控制的最佳实践是将版本信息放入HTTP请求的Accept/Content-Type标头中,使URI保持不变.
以下是用于检索系统信息的REST API示例请求/响应:
==>
GET /api/system-info HTTP/1.1
Accept: application/vnd.COMPANY.systeminfo-v1+json
<==
HTTP/1.1 200 OK
Content-Type: application/vnd.COMPANY.systeminfo-v1+json
{
“session-count”: 19
}
Run Code Online (Sandbox Code Playgroud)
请注意,MIME类型中指定了版本.
这是版本2的另一个请求/响应:
==>
GET /api/system-info HTTP/1.1
Accept: application/vnd.COMPANY.systeminfo-v2+json
<==
HTTP/1.1 200 OK
Content-Type: application/vnd.COMPANY.systeminfo-v2+json
{
“uptime”: 234564300,
“session-count”: 19
}
Run Code Online (Sandbox Code Playgroud)
有关更多说明和示例,请参见http://barelyenough.org/blog/tag/rest-versioning/.
是否有可能在基于Java的JAX-RS实现中轻松实现此方法,例如Jersey或Apache CXF?
目标是让几个@Resource类具有相同的@Path值,但是根据MIME类型中指定的实际版本提供请求?
我一般都研究过JAX-RS,特别是Jersey,并没有发现它的支持.泽西岛没有机会以相同的路径注册两个资源.需要实现WebApplicationImpl类的替换以支持它.
你能提出什么建议吗?
注意:需要同时提供同一资源的多个版本.新版本可能会引入不兼容的更改.
JAX-RS通过Accept标头调度到使用@Produces注释的方法.因此,如果您希望JAX-RS进行调度,则需要利用此机制.如果没有任何额外的工作,您必须为您希望支持的每种媒体类型创建一个方法(和Provider).
没有什么可以阻止你使用基于媒体类型的几种方法,这些方法都是一种常用方法来完成这项工作,但是每次添加新媒体类型时都必须更新并添加代码.
一个想法是添加一个过滤器,专门为调度"规范化"您的Accept标头.那也许就是你的:
Accept: application/vnd.COMPANY.systeminfo-v1+json
Run Code Online (Sandbox Code Playgroud)
并将其转换为:
Accept: application/vnd.COMPANY.systeminfo+json
Run Code Online (Sandbox Code Playgroud)
同时,您提取版本信息供以后使用(可能在请求中,或其他一些临时机制).
然后,JAX-RS将调度到处理"application/vnd.COMPANY.systeminfo + json"的单个方法.
然后,该方法采用"带外"版本控制信息来处理处理中的细节(例如选择通过OSGi加载的适当类).
接下来,您将使用适当的MessageBodyWriter创建一个Provider.JAX-RS将为application/vnd.COMPANY.systeminfo + json媒体类型选择提供程序.由MBW决定实际的媒体类型(再次基于该版本信息)并创建正确的输出格式(再次,可能调度到正确的OSGi加载类).
我不知道MBW是否可以覆盖Content-Type标头.如果没有,那么您可以委派早期的过滤器在出路时为您重写该部分.
这有点令人费解,但是如果你想利用JAX-RS调度,而不是为你的媒体类型的每个版本创建方法,那么这是一条可行的途径.
编辑以回应评论:
是的,基本上,您希望JAX-RS根据Path和Accept类型分派到正确的类.JAX-RS不太可能开箱即用,因为它有点边缘.我没有看过任何JAX-RS实现,但是你可以通过在基础架构级别调整其中一个来做你想做的事.
可能另一个侵入性较小的选择是使用来自Apache世界的古老技巧,并简单地创建一个基于Accept标头重写路径的过滤器.
所以,当系统获得:
GET /resource
Accept: application/vnd.COMPANY.systeminfo-v1+json
Run Code Online (Sandbox Code Playgroud)
你重写它:
GET /resource-v1
Accept: application/vnd.COMPANY.systeminfo-v1+json
Run Code Online (Sandbox Code Playgroud)
然后,在您的JAX-RS类中:
@Path("resource-v1")
@Produces("application/vnd.COMPANY.systeminfo-v1+json")
public class ResourceV1 {
...
}
Run Code Online (Sandbox Code Playgroud)
因此,您的客户端可以获得正确的视图,但是您的类可以通过JAX-RS正确分派.唯一的另一个问题是你的类,如果他们看起来,将会看到修改后的路径,而不是原始路径(但是如果你愿意,你的过滤器可以将请求中的内容作为参考).
它并不理想,但它(大多数)是免费的.
这是一个现有的过滤器,可能会做你想做的事情,如果不是它也许可以作为你自己做的灵感.
归档时间: |
|
查看次数: |
9989 次 |
最近记录: |