使用RestTemplate和UriComponentsBuilder调用带JSON参数API报错如何解决
问题原因
- UriComponentsBuilder默认会将URI中的
{}识别为URI模板占位符,尝试匹配对应变量值进行替换。你传入的filter参数是JSON格式,包含{"code":"xxx"}结构,框架会把"code"识别为待填充的模板变量名,没有传入对应变量值就会抛出该异常。 - 你的代码还存在额外错误:
RestTemplate.getForObject()方法直接返回响应体对象,不会返回ResponseEntity,此处类型不匹配会触发编译/运行时错误。
解决方案
以下两种修复方式可二选一:
方案1:构造URI时禁用模板解析,直接传递URI对象给RestTemplate
不要将构造好的URI转成String字符串,直接生成URI对象传入RestTemplate,同时构建时禁用模板变量解析:
public Person getPerson(String filter, Optional<Integer> size, Optional<Integer> page, Optional<String> sort){ String endpoint = "http://localhost:8081/person"; UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(endpoint) .queryParam("filter", filter); page.ifPresent(p -> builder.queryParam("page", p)); size.ifPresent(s -> builder.queryParam("size", s)); sort.ifPresent(s -> builder.queryParam("sort", s)); // 关键:第二个参数false表示不解析模板占位符,直接生成URI对象 URI uri = builder.build(false).toUri(); // 修正方法调用,使用getForEntity获取ResponseEntity ResponseEntity<Person> response = restTemplate.getForEntity(uri, Person.class); return response.getBody(); }
方案2:提前对JSON参数做URL编码后再传入
先将JSON格式的filter参数做URL编码,再传入queryParam,编码后的JSON不会包含{}字符,就不会触发模板解析逻辑:
import java.net.URLEncoder; import java.nio.charset.StandardCharsets; public Person getPerson(String filter, Optional<Integer> size, Optional<Integer> page, Optional<String> sort){ String endpoint = "http://localhost:8081/person"; // 对JSON参数做URL编码 String encodedFilter = URLEncoder.encode(filter, StandardCharsets.UTF_8); UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(endpoint) .queryParam("filter", encodedFilter); page.ifPresent(p -> builder.queryParam("page", p)); size.ifPresent(s -> builder.queryParam("size", s)); sort.ifPresent(s -> builder.queryParam("sort", s)); String url = builder.build().toUriString(); ResponseEntity<Person> response = restTemplate.getForEntity(url, Person.class); return response.getBody(); }
内容的提问来源于stack exchange,提问作者user14500188
相关产品推荐
相关产品推荐

