前面说到如何使用 Spring 的 RestTemplate 进行数据请求,如何避免乱码问题,在项目开发中还遇到了文件上传和下载,所以也写了使用 RestTemplate 包装文件下载的组件。同样,项目越大遇到的问题就会越多,当使用 GET 请求时,如果URL中的参数有特殊字符,比如 '#' ,就会导致查询错误。
1、RestTemplate 下载组件
http://my.oschina.net/heweipo/blog/683233
2、RestTemplate 乱码解决
http://my.oschina.net/heweipo/blog/611514
重现步骤,如下代码
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
String url = "http://localhost:8180/workbench/questionBank/paper?search=#&query=123";
HttpEntity<?> entity = new HttpEntity<>(headers);
HttpEntity<String> response = restTemplate.exchange(url,HttpMethod.GET,entity,String.class);
System.out.println(response.getBody());
}
本来请求中是有参数 search 和 query ,就因为 search 中使用了特殊字符 # , 然而在服务端获取参数时得到的参数只有 search = ;
调试结果:
问题出现的原因,查看 RestTemplate 的如下代码
@Override
public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, Object... urlVariables) throws RestClientException {
// 这里进行网络转码,因为我们传递的URL是字符串,最后都要统一转为URL,而且对于字符都应该进行网络编码,
// 问题就出现在这里,我们如果自己手动把参数进行网络编码,那么问题就不会出现
URI expanded = getUriTemplateHandler().expand(url, urlVariables);
return doExecute(expanded, method, requestCallback, responseExtractor);
}
修改后的代码
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
String url = "http://localhost:8180/workbench/questionBank/paper?search=#&query=123";
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
URI uri = builder.build().encode().toUri();
HttpEntity<?> entity = new HttpEntity<>(headers);
HttpEntity<String> response = restTemplate.exchange( uri, HttpMethod.GET, entity, String.class);
System.out.println(response.getBody());
}
调试结果
总结:
网络传输需要进行网络编码,网络编码可以使用如下API
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("msisdn", msisdn)
.queryParam("email", email)
.queryParam("clientVersion", clientVersion)
.queryParam("clientType", clientType)
.queryParam("issuerName", issuerName)
.queryParam("applicationName", applicationName);
HttpEntity<?> entity = new HttpEntity<>(headers);
HttpEntity<String> response = restTemplate.exchange(
builder.build().encode().toUri(),
HttpMethod.GET,
entity,
String.class);