Jersey同一URL接口在Accept: */*时调用方法不一致原因排查
问题描述
在Jersey 2.33中配置了两个URL、HTTP方法完全相同的POST接口,分别返回JSON和CSV格式的数据:
- 当请求头为
Accept: application/json时,调用getDataJson方法 - 当请求头为
Accept: text/csv时,调用getDataCsv方法
但当请求头为Accept: */*时,不同服务器上的行为不一致:有的服务器始终调用getDataCsv,有的则始终调用getDataJson。已通过sha256sum校验确认应用jar包完全一致,查阅Jersey 2.33官方文档也未找到相关说明。
对应的代码如下:
@POST @Path("customer/{custId}/search/stuff") @Consumes(MediaType.APPLICATION_JSON) @Produces({MediaType.APPLICATION_JSON}) MyDataResponse getDataJson(@PathParam("custId") UUID custId, SearchParams params); @POST @Path("customer/{custId}/search/stuff") @Consumes(MediaType.APPLICATION_JSON) @Produces("text/csv") Response getDataCsv(@PathParam("custId") UUID custId, SearchParams params);
问题原因
这种不一致的核心原因是Jersey在匹配多个兼容的资源方法时,若没有明确的权重优先级,会依赖方法的扫描顺序,而扫描顺序受类加载器或服务器文件系统的遍历顺序影响。
具体细节:
- 当
Accept: */*时,两个接口的@Produces声明都能匹配该请求头(*/*匹配任何媒体类型),Jersey需要从候选方法中选择一个执行。 - Jersey内部处理这类模糊匹配时,会按资源方法被扫描发现的顺序,选择第一个符合条件的方法。
- 而方法的扫描顺序并非固定:不同服务器的类加载器实现差异、不同操作系统文件系统遍历Jar包内类的排序逻辑不同,都会导致资源方法被发现的顺序变化,最终出现有的服务器调用JSON接口、有的调用CSV接口的情况。
Jersey 2.x的官方文档未明确提及这种扫描顺序的不确定性,因为这属于底层实现细节,而非公开约定的标准行为。
内容的提问来源于stack exchange,提问作者DWilches
相关产品推荐
相关产品推荐

