为了处理内容类型的不同版本,我试图使用"Accept*"标头的接受参数(RFC 2616).
Accept: application/vnd.mycompany.mytype;version=2 , application/vnd.mycompany.mytype;version=1;q=0.1
Run Code Online (Sandbox Code Playgroud)
问题是Jax-RS注释不支持Accept-parameters ...
@GET
@Produces("application/vnd.test;version=1")
public Response test1() {
return Response.ok("Version 1", "application/vnd.test").build();
}
@GET
@Produces("application/vnd.test;version=2")
public Response test2() {
return Response.ok("Version 2", "application/vnd.test").build();
}
Run Code Online (Sandbox Code Playgroud)
导致媒体类型冲突异常:
Producing media type conflict. The resource methods public javax.ws.rs.core.Response test.resources.TestResource.test2() and public javax.ws.rs.core.Response test.resources.TestResource.test1() can produce the same media type
Run Code Online (Sandbox Code Playgroud)
也许,这个例外只与我的JAX-RS框架(Jersey)有关,但我担心这是由于JSR311没有明确的接受参数.
到目前为止,我正在使用内容类型,其中包含其名称中的版本,但我发现这个解决方案非常流畅.
@GET
@Produces("application/vnd.test-v1")
public Response test() {
return Response.ok("Version 1", "application/vnd.test-v1").build();
}
Run Code Online (Sandbox Code Playgroud)
您对如何处理接受参数有任何想法吗?
编辑
我想我还不够清楚.我想自动将请求路由到特定方法.这些方法是版本化的,并且对应于返回的内容类型的特定版本.JAX-RS当前实现阻止我使用accept-parameters来路由请求(到相应的方法).
greenkode建议我version在调度方法(使用@HeaderParam("Accept"))中管理accept-parameter .该解决方案最终将重写内容解析逻辑,该逻辑嵌入框架中(并在JSR 311中描述).
如何使用JAX-RS的accept-parameter和content-negociation逻辑呢?
也许解决方案是使用另一个框架(我只使用Jersey by Now).但我不知道哪一个.
Per*_*ion 16
JAX-RS规范没有明确声明忽略Accept头参数的任何内容.但唯一明确定义处理的参数是质量(q).这是一个可能的改进领域,因为它似乎导致泽西岛实施中的歧义(或彻底的愚蠢).在将传入请求与资源方法匹配时,当前版本的Jersey(1.17)不会考虑Accept头参数,这就是您收到错误的原因:
严重:产生媒体类型冲突.资源方法......
对于资源:
@GET
@Produces("application/vnd.test;version=1")
public Response test1() {
return Response.ok("Version 1", "application/vnd.test").build();
}
@GET
@Produces("application/vnd.test;version=2")
public Response test2() {
return Response.ok("Version 2", "application/vnd.test").build();
}
Run Code Online (Sandbox Code Playgroud)
看来泽西岛根据Accept标头'type/subtype'执行'唯一性'检查,完全省略任何参数.这可以通过在"匹配"资源方法上使用各种标头对进行测试来确认:
Resource 1 Resource 2 ---------------------------------------- text/html;q=0.4 text/html;q=0.8 text/html text/html;q=0.2 text/html text/html;qs=1.4 text/html;qs=1.4 text/html;qs=1.8 text/html;level=1 text/html;level=2 text/html;foo=bleh text/html;bar=23
所有失败都有同样的错误.如果假设只发送了质量参数,那么仅匹配'type/subtype'是有意义的,因为这种请求是荒谬的:
接受:text/html; q = 0.8,text/html; q = 0.4,text/html
Aka,质量参数只有在处理各种可能的内容类型时才有意义.但是,当发送非质量参数或其他参数时,这种有限匹配会失败:
接受:text/html; version = 4.0; q = 0.8,text/html; version = 3.2; q = 0.4
那么可能的解决方案是什么?
使用RESTEasy和资源:
@Path("/content/version")
public class ContentVersionResource {
@GET
@Produces("application/vnd.test;version=1")
public Response test1() {
return Response.ok("Version 1", "application/vnd.test").build();
}
@GET
@Produces("application/vnd.test;version=2")
public Response test2() {
return Response.ok("Version 2", "application/vnd.test").build();
}
}
Run Code Online (Sandbox Code Playgroud)
使用以下Accept标头成功匹配:
接受:application/vnd.test; version = 1; q = 0.3,application/vnd.test; version = 2; q = 0.5
响应:版本2
还有这个:
接受:application/vnd.test; version = 1; q = 0.5,application/vnd.test; version = 2; q = 0.3
响应:版本1
您可以使用此示例项目下载和测试.需要Git,Maven和JBoss 7.x.
| 归档时间: |
|
| 查看次数: |
7578 次 |
| 最近记录: |