问题描述
Java服务用GET请求调用第三方接口参数中用带有特殊符号的字段会导致返回的数据报404或者500:
如下面代码所示:
private static HttpEntity<String> createCommonHttpEntity(String token) {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setBearerAuth(token);
HttpEntity<String> entity = new HttpEntity<>(headers);
return entity;
}
public String Project(String token, String appid, String userId) {
String url = ymlInsConfig.getSystemHost() + "Project/{appId}/{userId}";
URI uri = new UriTemplate(url).expand(appid, userId);
HttpEntity<String> entity = createCommonHttpEntity(token);
return restTemplate.exchange(uri,
HttpMethod.GET, entity, String.class).getBody();
}
原因分析:
分析原因
开始是以为没有URLEncoder.encode导致特殊符号没有正确编码,但是测试后依然报错,于是检查了http请求地址和参数没有问题后,用另一个不带特殊字符的账号测试接口,结果返回数据正常,故想到可能是转移符导致在请求过程中被转义导致接口无法识别.
解决方案:
具体解决方案:
通过排查,是因为特殊符号在请求过程中二次转义导致无法识别,可以通过UriTemplate方法直得到一个URL,通过查看源码可以看到输入的结果时被encode过的。代码如下:
public URI expand(Object... uriVariableValues) {
UriComponents expandedComponents = this.uriComponents.expand(uriVariableValues);
UriComponents encodedComponents = expandedComponents.encode();
return encodedComponents.toUri();
}
public String Project(String token, String appid, String userId) {
String url = ymlInsConfig.getSystemHost() + "Project/{appId}/{userId}";
URI uri = new UriTemplate(url).expand(appid, userId);
HttpEntity<String> entity = createCommonHttpEntity(token);
return restTemplate.exchange(uri,
HttpMethod.GET, entity, String.class).getBody();
}
好记性不如烂笔头儿,记录遇到的问题,也是方便下次再遇到同样的问题可以直接查看。