本文介绍了在开发jax-rs应用程序时如何处理accept-parameters的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了处理内容类型的不同版本,我试图使用Accept *标题的accept-parameters(。

In order to deal with different versions of a content-type i am trying to use the accept-parameters of the "Accept*" headers (RFC 2616).

Accept: application/vnd.mycompany.mytype;version=2 , application/vnd.mycompany.mytype;version=1;q=0.1

问题在于Jax-RS注释不支持Accept-parameters ...

The problem is that Jax-RS annotations do not support 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();
}

导致媒体类型冲突异常:

Results in a media type conflict exception:

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

也许,这个例外只与我的JAX-RS框架(Jersey)有关,但我担心这是由于对于accept-parameters没有明确规定。

Maybe, this exception only related to my JAX-RS framework (Jersey), but i'm afraid this is due to the JSR311 which is not explicit about accept-parameters.

到目前为止,我正在使用内容类型,其中包含其名称中的版本,但我发现这个解决方案非常糟糕。

By now, i'm using content-types which holds the version within their names, but i found this solution pretty uggly.

@GET
@Produces("application/vnd.test-v1")
public Response test() {
    return Response.ok("Version 1", "application/vnd.test-v1").build();
}

您对如何处理接受参数有任何想法吗?

Do you have any ideas about how to deal with accept-parameters ?

编辑

我认为我不够清楚。
我想自动将请求路由到特定方法。
这些方法是版本化的,并且对应于返回的内容类型的特定版本。
JAX-RS当前实现阻止我使用accept-parameters路由请求(到相应的方法)。

I think i wasn't clear enough.I want to automatically route the request to specific methods.These methods are versioned and correspond to a specific version of the returned content-type.JAX-RS current implementation prevents me to use accept-parameters to route the request (to the corresponding method).

greenkode建议我管理 version 调度方法中的accept-parameter(使用 @HeaderParam(Accept))。
这个解决方案最终会重新编写嵌入框架中的内容解析逻辑(并在JSR 311中描述)。

greenkode suggest that i manage the version accept-parameter within a dispatching method (using @HeaderParam("Accept")).This solution would end-up in re-writing the content negociation logic which is embeded in the framework (and described in JSR 311).

我能做什么?从JAX-RS使用accept-parameter和content-negociation逻辑?

What can i do to use both accept-parameter and content-negociation logic from JAX-RS ?

也许解决方案是使用另一个框架(我现在只使用Jersey)。但我不知道是哪一个。

Maybe a solution is to use another framework (I only worked with Jersey by Now). But i don't know which one.

推荐答案

JAX-RS规范没有显式状态关于忽略Accept标头参数的任何事情。但处理绝对定义的唯一参数是 quality (q)。这是一个可能的改进领域,因为它似乎导致泽西岛实施中的歧义(或彻头彻尾的愚蠢)。在将传入请求与资源方法匹配时,当前版本的Jersey(1.17)不会考虑Accept标头参数,这就是您收到错误的原因:

The JAX-RS specification does not explicitly state anything about ignoring Accept header parameters. But the only parameter for which handling is definitely defined is quality (q). This is a possible area for improvement as it seems to have lead to ambiguity (or outright bugginess) in the Jersey implementation. The current version of Jersey (1.17) does not take Accept header parameters into consideration when matching incoming requests to resource methods, which is why you are getting the error:

对于资源:

@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();
}

看来Jersey会根据Accept标头执行唯一性检查'type / subtype',完全省略任何参数。这可以通过在匹配资源方法上使用各种标题对进行测试来确认:

It would appear that Jersey performs a 'uniqueness' check based on the Accept header 'type/subtype', totally omitting any parameters. This can be confirmed by testing with various pairs of headers on the 'matching' resource methods:


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'是有意义的,因为这种请求是荒谬的:

All fail with the same error. If the assumption were made that only the quality parameter is ever sent, then it would make sense to only match on 'type/subtype', because this kind of request is nonsensical:

接受:text / html; q = 0.8,text / html; q = 0.4,text / html

Aka, quality 参数仅在处理可能的内容类型的 mix 时才有意义。但是,当发送非质量参数或其他参数时,这种有限匹配会失败:

Aka, quality parameters only make sense when you are dealing with a mix of possible content types. However, this sort of limited matching fails when non-quality parameters or additional parameters are being sent:

那么可能的解决方案是什么?

So what are the possible solutions?


  • 根据'type / subtype'截取高级请求,然后路由到更合适的方法(你已表明你不想要要做这个)

  • 修改预期的标题。例如'application / vnd.mycompany.mytype + v2'和'application / vnd.mycompany.mytype + v1'。不需要进行任何其他更改,您可以继续使用Jersey

  • Switch框架。 可以轻松处理您的方案。

  • Intercept the high level request based off 'type/subtype', then route to more appropriate method (you've indicated you do not want to do this)
  • Modify your expected headers. For example 'application/vnd.mycompany.mytype+v2' and 'application/vnd.mycompany.mytype+v1'. No other changes would be required and you could keep on using Jersey
  • Switch frameworks. RESTEasy happens to handle your scenario with ease.

使用RESTEasy和资源:

With RESTEasy, and resource:

@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();
    }
}

使用以下Accept标头成功匹配:

A successful match is made with the following Accept header:

这个:

您可以下载并测试。需要Git,Maven和JBoss 7.x

You can download and test with this sample project. Git, Maven and JBoss 7.x required

这篇关于在开发jax-rs应用程序时如何处理accept-parameters的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 20:30