使用Spring RestTemplate调用REST GET接口时出现400 Bad Request错误的问题求助
我帮你分析下这个问题的根源,你遇到的核心问题是URL编码重复处理导致的IdDistrict参数无效。
问题原因
你直接写在getForEntity里的URL末尾参数是CG7drXn9fvA%253D,这里的%25其实是%的URL编码结果,而%3D是=的编码。但Spring的RestTemplate默认会自动对URL中的特殊字符(包括%)进行编码,所以当它处理这个URL时,会把原本的%再次编码成%25,最终后台收到的参数变成了CG7drXn9fvA%25253D——这显然不是服务器期望的有效ID,所以返回了400错误。
而你用cURL或Postman能正常调用,是因为这两个工具不会对已经编码过的URL再次编码,服务器收到的是正确的参数值。
解决方案
这里有两种可靠的解决方式,推荐第一种更规范的写法:
1. 使用URL占位符传递参数(推荐)
让RestTemplate自动处理参数编码,避免手动编码出错。只需要把URL中的参数部分用{id}占位,然后在方法参数里传入原始的未编码(或正确编码一次的)ID值:
// 方式一:传入原始ID(比如你的ID实际是CG7drXn9fvA=) String url = "https://MAYPI.SERVICE.it/ws-application/service/distretti/{id}"; ResponseEntity<NotaryDistrict> response = restTemplate.getForEntity(url, NotaryDistrict.class, "CG7drXn9fvA="); // 方式二:如果ID本身就是已经编码过的CG7drXn9fvA%3D,也可以直接传 ResponseEntity<NotaryDistrict> response = restTemplate.getForEntity(url, NotaryDistrict.class, "CG7drXn9fvA%3D");
这种方式下,RestTemplate会自动帮你处理好正确的URL编码,不会出现重复编码的问题。
2. 手动构建已编码的URI,禁止RestTemplate再次编码
如果你必须手动构造完整的URL,可以使用UriComponentsBuilder来构建,并明确告诉它URL已经编码完成,不需要再处理:
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("https://MAYPI.SERVICE.it/ws-application/service/distretti/CG7drXn9fvA%3D") .build(true); // true表示该URI已经完成编码,RestTemplate不会再修改 ResponseEntity<NotaryDistrict> response = restTemplate.getForEntity(uriComponents.toUri(), NotaryDistrict.class);
注意这里的URL要写正确编码一次的版本(CG7drXn9fvA%3D),而不是你之前写的CG7drXn9fvA%253D。
验证建议
你可以先在Postman里测试一下:如果输入CG7drXn9fvA%253D作为ID,应该也会返回同样的400错误,这就能验证重复编码的问题。
内容的提问来源于stack exchange,提问作者AndreaNobili

