RESTEasy中查询参数含未编码大括号返回400错误的排查
问题原因及解决方案
原因分析
未编码的大括号{}属于HTTP规范定义的保留字符,这类字符在URL查询参数中必须经过百分号编码({对应%7B,}对应%7D)才能合法传递。
当你直接传递未编码的{foo}时,请求会先被底层Web容器(如Tomcat、Jetty)拦截——容器在解析URL阶段就会判定这是非法请求,直接返回HTTP 400错误。此时请求根本没有到达JAX-RS框架层面,所以你配置的ExceptionMapper无法捕获这个异常(它只能处理JAX-RS运行时抛出的异常)。
解决办法
方法1:调整Web容器的URL解析规则
修改容器配置,允许未编码的大括号通过URL解析:
- Tomcat:在
conf/server.xml的<Connector>标签中添加relaxedQueryChars属性,包含{和}:<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" relaxedQueryChars="{}"/> - Jetty:可以通过代码或配置文件允许未转义字符:
- 代码方式:设置系统属性
System.setProperty("org.eclipse.jetty.server.Request.ALLOW_UNESCAPED_CHARACTERS_IN_QUERY", "true"); - 配置文件方式:在
jetty.xml的HttpConfiguration中添加允许的字符<Call name="addCustomizer"> <Arg> <New class="org.eclipse.jetty.server.HttpConfiguration.Customizer"> <Call name="setAllowedQueryCharacters"> <Arg><Array type="char"> <Item>{</Item> <Item>}</Item> </Array></Arg> </Call> </New> </Arg> </Call>
- 代码方式:设置系统属性
方法2:规范客户端请求(推荐)
严格遵循HTTP规范,要求客户端在传递包含保留字符的参数时先进行百分号编码。这是最标准的做法,能避免跨容器的兼容性问题。
方法3:通过UriInfo获取原始参数(需容器放行)
如果容器已经允许未编码字符通过,可使用@Context UriInfo直接获取查询参数,绕过JAX-RS的参数解析:
@GET @Path("/hello") @Produces(MediaType.TEXT_PLAIN) public String greeting(@Context UriInfo uriInfo) { String name = uriInfo.getQueryParameters().getFirst("name"); return "Hello " + (name != null ? name : ""); }
内容的提问来源于stack exchange,提问作者luca.vercelli
相关产品推荐
相关产品推荐

