Spring中如何对含对象参数的请求URL进行正确编码?
解决RestTemplate传递JSON作为GET请求参数的URL编码问题
你遇到的核心问题是URL中的JSON字符串没有正确编码,导致UriBuilder解析失败。Postman会自动帮你处理URL编码,所以能正常工作,但RestTemplate不会自动处理这种内嵌的JSON参数,得用正确的方式做编码。
为什么直接写JSON会报错?
URL里的{"level":"BIG"}包含双引号"、大括号{}这些URL保留字符,直接放在URL中会破坏URI的语法结构,new URI(...)解析时自然会抛出错误。而你之前尝试URLEncoder时出错,大概率是错误地编码了整个URL,导致URI变成非绝对路径,才出现IllegalArgumentException: URI is not absolute。
正确的解决方案有两种:
方案1:手动编码JSON参数,再通过占位符传递
先把Filter对象序列化成JSON字符串,单独编码这个字符串,再用RestTemplate的参数占位符传入,避免直接拼接URL:
// 1. 构建Filter对象并转成JSON字符串 Filter filter = new Filter(); filter.add("level", "BIG"); ObjectMapper objectMapper = new ObjectMapper(); String filterJson = objectMapper.writeValueAsString(filter); // 2. 对JSON字符串进行URL编码(指定UTF-8字符集) String encodedFilter = URLEncoder.encode(filterJson, StandardCharsets.UTF_8); // 3. 用占位符传递编码后的参数,RestTemplate会自动拼接正确的URL RestTemplate restTemplate = new RestTemplate(); Item item = restTemplate.getForObject( "http://127.0.0.1:8080/items?filter={filter}", Item.class, encodedFilter );
方案2:用UriComponentsBuilder自动编码(更推荐)
Spring提供的UriComponentsBuilder会自动帮你处理参数的URL编码,比手动编码更安全,不容易出错:
// 1. 构建Filter对象并转成JSON字符串 Filter filter = new Filter(); filter.add("level", "BIG"); ObjectMapper objectMapper = new ObjectMapper(); String filterJson = objectMapper.writeValueAsString(filter); // 2. 用UriComponentsBuilder构建带编码参数的URI UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("http://127.0.0.1:8080/items") .queryParam("filter", filterJson) .build(true); // 参数true表示自动对查询参数进行URL编码 // 3. 发送请求 RestTemplate restTemplate = new RestTemplate(); Item item = restTemplate.getForObject(uriComponents.toUri(), Item.class);
额外说明
你的Filter类用@JsonAnySetter来接收动态的criteria是正确的,远程服务那边能正常把URL中编码后的JSON字符串反序列化成Filter对象,进而执行MongoDB的参数化查询。
内容的提问来源于stack exchange,提问作者Valeriy K.
相关产品推荐
相关产品推荐

