使用@PathParam与@QueryParam时QueryParam被解析为PathParam的问题
出现这种情况,核心是Jersey没有正确区分URL的路径部分和查询参数部分,把?及后续内容都当作@PathParam("id")的取值,常见原因和对应解决办法如下:
常见原因
Servlet映射或Jersey路径配置错误
若Jersey的ServletContainer在web.xml中的映射路径设置不当,或是@ApplicationPath的配置有问题,会导致容器把整个URL(含查询参数)都当作路径的一部分传递给资源方法。请求中的
?被编码
如果客户端实际发送的请求里,?被编码成了%3F,服务器会将其视为路径的普通字符,不会识别为查询参数的分隔符,进而把后面的内容并入id参数。自定义过滤器/拦截器干扰
项目中若存在自定义的Servlet Filter或Jersey Interceptor,处理请求时错误地将查询参数拼接到路径中再转发,会导致Jersey解析异常。旧版本Jersey存在解析Bug
部分早期版本的Jersey存在URL解析缺陷,无法正确拆分路径与查询参数。
解决办法
检查配置文件
确认Jersey的Servlet映射(web.xml)或@ApplicationPath设置正确。例如web.xml中的标准配置:<servlet> <servlet-name>Jersey Servlet</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>你的资源类包路径</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Jersey Servlet</servlet-name> <url-pattern>/api/*</url-pattern> </servlet-mapping>若使用
@ApplicationPath,比如@ApplicationPath("/api"),要确保资源方法的@Path基于该前缀设置,避免路径覆盖。验证请求格式
用curl或浏览器开发者工具查看实际请求的URL,确认?未被编码。正确的请求示例:curl http://localhost:8080/api/user/id11302908?asOf=2024-05-21若URL中出现
%3F,说明客户端编码错误,需修正请求发送逻辑。排查自定义组件
检查项目中的自定义Filter/Interceptor,确认是否存在修改请求URI的代码。比如做请求转发时,要正确保留查询参数,而非将其拼接到路径中。升级Jersey版本
若使用旧版本(如Jersey 2.x早期版本),建议升级到Jakarta EE兼容的Jersey 3.x稳定版本,修复可能存在的解析Bug。显式限制PathParam匹配规则
在@Path注解中给id参数添加正则表达式,强制其仅匹配?之前的内容:@GET @Path("/user/{id:[^?]+}") public Response getUser(@PathParam("id") final String id, @QueryParam("asOf") final String asOf) { // 业务逻辑 }正则
[^?]+表示匹配任意非?的字符,即使出现异常情况,也能保证id不会包含查询参数部分。
内容的提问来源于stack exchange,提问作者Eugene S

