Quarkus使用resteasy-reactive时MessageBodyWriter收到MediaType恒为application/json问题
问题解答
这个是Quarkus 2.x版本中resteasy-reactive组件的预期设计行为,不属于异常问题。
行为差异原因
传统JAX-RS实现(如Jersey、旧版RESTEasy)的内容协商逻辑默认优先遵循客户端Accept请求头的优先级:只要客户端请求的媒体类型落在服务端@Produces声明的范围内,就会按客户端Accept头的顺序匹配最优类型。
而resteasy-reactive为了优化内容协商的性能,调整了默认匹配规则:当客户端Accept头没有明确设置质量参数(q值)时,框架会优先以资源方法@Produces注解中声明的类型顺序作为匹配优先级,所以当application/json排在application/vnd.ms-excel前面时,框架会优先选中JSON作为响应媒体类型,传入MessageBodyWriter的mediaType自然就是JSON类型。
可选解决方式
你已经验证过的调整@Produces声明顺序是最直接的适配方案,除此之外还有两种可选方案:
- 客户端请求时给
Accept头添加q值声明优先级,例如:Accept: application/vnd.ms-excel;q=1.0, application/json;q=0.9,框架会优先匹配q值更高的媒体类型,不受服务端@Produces顺序影响 - 在资源方法中主动判断
Accept头,返回Response时手动指定响应媒体类型:
@Override public Response getData(@PathParam("id") Long id) { List<MediaType> accepts = httpHeaders.getAcceptableMediaTypes(); // 自行判断是否需要返回Excel if (accepts.stream().anyMatch(m -> m.isCompatible(MediaType.valueOf("application/vnd.ms-excel")))) { return Response.ok(new MyData(), "application/vnd.ms-excel").build(); } return Response.ok(new MyData()).build(); }
额外说明:Quarkus 3.x版本新增了配置项quarkus.rest.content-negotiation.strategy,可手动切换内容协商的优先级策略,支持选择优先遵循客户端Accept头或者优先遵循服务端@Produces顺序。
内容的提问来源于stack exchange,提问作者Carl-Evert Kangas
相关产品推荐
相关产品推荐

