SpringBoot调用Google Maps附近搜索API返回INVALID_REQUEST问题排查
核心嫌疑点:重复编码导致参数解析失败
你的代码中手动使用UriUtils.encode处理location参数,但UriComponentsBuilder本身会自动对查询参数进行URL编码,这会导致参数被二次编码。比如原location值是48.1317547,11.5694659,手动编码后变成48.1317547%2C11.5694659,UriComponentsBuilder会再次将%编码为%25,最终发送的location参数变为48.1317547%252C11.5694659——Google Places API无法解析这种格式的坐标,直接返回INVALID_REQUEST。
虽然日志打印的URL看起来正常,但这是UriComponentsBuilder.build().toUriString()的结果,实际通过RestTemplate发送时可能存在二次编码的问题(取决于RestTemplate的配置)。
排查与修复步骤
移除手动编码逻辑
修改location参数的构建代码,去掉UriUtils.encode,直接传入原始字符串:.queryParam("location", request.getLocation().toString())UriComponentsBuilder会自动处理合法的URL编码,确保参数格式符合Google API要求。验证实际发送的请求URL
日志打印的是构建后的URL,但RestTemplate可能会对URL进行额外处理。可以通过以下方式确认实际请求:- 开启RestTemplate的DEBUG日志,查看完整请求详情;
- 使用抓包工具(如Fiddler、Wireshark)捕获发送到
maps.googleapis.com的请求,对比URL参数是否与日志一致。
检查
language参数合法性
日志中的URL包含language=US,但Google Places API的language参数要求是语言代码(如en代表英语),而非国家代码(US)。如果你的实际代码中添加了这个参数,错误的值会导致API请求无效,建议改为合法的语言代码(比如en-US)。模拟浏览器/Postman的请求头
Postman和浏览器会自动添加User-Agent等请求头,而RestTemplate默认请求头较为简单。可以尝试添加请求头模拟浏览器请求,排除头信息导致的问题:HttpHeaders headers = new HttpHeaders(); headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"); HttpEntity<Void> entity = new HttpEntity<>(headers); ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);检查RestTemplate的编码配置
如果自定义了RestTemplate的UriTemplateHandler(比如替换为DefaultUriBuilderFactory),需确认其编码逻辑是否正常。默认配置下UriComponentsBuilder的编码是符合规范的,但自定义配置可能导致异常。
内容的提问来源于stack exchange,提问作者Felicity Wang

