Java 开发jax-rs应用程序时如何处理accept参数
为了处理不同版本的内容类型,我尝试使用“accept*”头()的accept参数 问题是Jax RS注释不支持接受参数Java 开发jax-rs应用程序时如何处理accept参数,java,rest,jax-rs,Java,Rest,Jax Rs,为了处理不同版本的内容类型,我尝试使用“accept*”头()的accept参数 问题是Jax RS注释不支持接受参数 @GET @产生(“应用程序/vnd.test;版本=1”) 公共响应测试1(){ 返回Response.ok(“版本1”,“应用程序/vnd.test”).build(); } @得到 @产生(“应用程序/vnd.test;版本=2”) 公众回应测试2(){ 返回Response.ok(“版本2”,“应用程序/vnd.test”).build(); } 导致媒体类型冲突异常
@GET
@产生(“应用程序/vnd.test;版本=1”)
公共响应测试1(){
返回Response.ok(“版本1”,“应用程序/vnd.test”).build();
}
@得到
@产生(“应用程序/vnd.test;版本=2”)
公众回应测试2(){
返回Response.ok(“版本2”,“应用程序/vnd.test”).build();
}
导致媒体类型冲突异常:
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参数没有明确的定义
到目前为止,我使用的内容类型将版本保存在它们的名称中,但我发现这个解决方案非常糟糕
@GET
@Produces("application/vnd.test-v1")
public Response test() {
return Response.ok("Version 1", "application/vnd.test-v1").build();
}
您对如何处理accept参数有什么想法吗
编辑
我想我还不够清楚。
我想自动将请求路由到特定的方法。
这些方法进行版本控制,并对应于返回内容类型的特定版本。
JAX-RS当前的实现阻止我使用accept参数来路由请求(到相应的方法)
greenkode建议我在分派方法中管理版本
接受参数(使用@HeaderParam(“接受”)
)。
该解决方案最终将重写嵌入框架中的内容协商逻辑(并在JSR311中描述)
如何使用JAX-RS中的accept参数和内容协商逻辑
也许一个解决方案是使用另一个框架(我现在只与Jersey合作)。但我不知道是哪一个。除非我遗漏了什么。JAX-RS确实支持接受参数。查看
@Consumes(“*/*”)
注释。此外,由于在同一url上有两个GET
方法,因此会出现媒体类型冲突的异常。用@Path(“test2”)
注释test2()方法,然后将GET
请求发送到url/test2。这应该可以消除这个错误
编辑
您可以使用@HeaderParams
注入Accept
头的值。这是我所做的一个例子
@Path("/conneg")
public class ConnNeg {
@GET
@Produces("application/vnd.test;version=1")
public Response test1(@HeaderParam("Accept") String header) {
System.out.println(header);
return Response.ok("Version 1", "application/vnd.test").build();
}
}
通过请求
接受:应用程序/vnd.test;版本=2,应用程序/vnd.test;版本=1;q=0.1
这会打印出来
应用/vnd.test;版本=2,应用程序/vnd.test;版本=1;q=0.1
然后您可以手动处理它。这就是您要寻找的吗?对于Jersey framework,HTTP请求的Accept头声明了最可接受的内容。如果资源类能够生成多个MIME媒体类型,则选择的资源方法将对应于客户端声明的最可接受的媒体类型。 在您的情况下,如果accept标头为
Accept: application/vnd.mycompany.mytype;version=2
然后将调用方法test1()
如果是
Accept: application/vnd.mycompany.mytype;q=0.9 version=2, application/vnd.mycompany.mytype;version=1
后者将被称为
在同一@products声明中可以声明多个媒体类型,例如:
@GET
@Produces({"application/vnd.mycompany.mytype; version=2", "application/vnd.mycompany.mytype; version=1"})
public Response test() {
return Response.ok("").build();
}
如果两种媒体类型中的任何一种都可以接受,则将调用test(9)方法。如果两种媒体类型都可以接受,则将调用第一种媒体类型
希望有帮助!JAX-RS规范没有明确说明忽略Accept头参数的任何内容。但唯一明确定义处理的参数是质量(q)。这是一个可能需要改进的领域,因为它似乎导致了歧义(或彻底的错误)在Jersey实现中。当前版本的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();
}
@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();
}
}
Jersey似乎根据Accept标头“type/subtype”执行“唯一性”检查,完全忽略任何参数。这可以通过在“matching”资源方法上使用不同的标头对进行测试来确认:
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
与以下Accept标头成功匹配:
接受:应用程序/vnd.test;版本=1;q=0.3,应用程序/vnd.test;版本=2;q=0.5答复:第2版 这是: 接受:应用程序/vnd.test;版本=1;q=0.5,应用程序/vnd.test;版本=2;q=0.3
答复:第1版
你可以下载并使用它进行测试。Git、Maven和JBoss 7.x必需我已经知道JAX-RS不支持accept参数。我想要的是关于如何正确处理这些参数的建议。哦,我明白了。我把
媒体范围
与accept参数
搞混了。实际上,这不是我想要的。有了这个解决方案在上,我仍然必须手动将所有请求路由到每个版本特定的方法。我还必须处理媒体类型冲突异常。现在这很有趣。阅读注释,我发现JAX-RS在表达这一点上没有问题。相反,这是Jersey实现的问题,至少还有一个实现可以解决n去做。(我希望知道我使用的框架CXF是否有问题,但我现在正在路上,无法测试…)关于您选择如何实现的任何更新。我也需要这样做,我很想知道所选答案是否对您有效。我不久前尝试过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();
}
}