RestTemplate请求url中包含特殊字符被转义问题,RestTemplate发送请求带有特殊字符,RestTemplate发送请求的坑

问题一:请求url中包含%被转义为%25

resteTemplate中url如果带%,被被转义成%25,无法正确的访问资源

例如: http://localhost:8080/aa?param=sdlfjdl&name=%123
会被转为:http://localhost:8080/aa?param=sdlfjdl&name=%25123

问题代码

String url = "http://localhost:8080/aa?param=sdlfjdl&name=%123";
try{
    restTemplate.getForEntity(url, String.class);
}catch (Exception e){

}

问题原因
restTemplate的exchange方法,若参数url是String类型在发送请求之前会先将String类型的url转为URI类型的url,在这个过程中会对url进行转义,如下面的restTemplate的源码中的方法:

@Nullable
public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor, Map<String, ?> uriVariables) throws RestClientException {
    URI expanded = this.getUriTemplateHandler().expand(url, uriVariables);
    return this.doExecute(expanded, method, requestCallback, responseExtractor);
}

因此这里直接采用restTemplate传参为URI的方法,将url的字符串编码转成URI就可以了:

@Nullable
public <T> T execute(URI url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
   return this.doExecute(url, method, requestCallback, responseExtractor);
}

问题解决
注意:若get请求参数中包含特殊字符&,则下面的这个解决方法还是有问题的,要想解决请求参数包含&可以参考下面问题二中的解决方法

String url = "http://localhost:8080/aa?param=sdlfjdl&name=%123";
try{
	URI uri = URI.create(url);
    restTemplate.getForEntity(uri, String.class);
}catch (Exception e){

}

问题二:RestTemplate发送get请求,请求参数中包含特殊字符&

解决方法

所有发送get请求,请求中包含特殊字符,如% & + = 空格 等都可以使用以下解决方法,目前没发现异常

public String get(String url, List<NameValuePair> params, List<NameValuePair> headerParams){
	String response = "";
	log.info("请求地址:{},请求头参数:{},请求参数:{}",url,headerParams,params);
	try {
		HttpHeaders headers = new HttpHeaders();
		if(!CollectionUtils.isEmpty(headerParams)){
			headerParams.forEach(p ->
					headers.add(p.getName(),p.getValue())
			);
		}
		HttpEntity<String> httpEntity = new HttpEntity<>(null,headers);
		URI uri = URI.create(url);
		if(!CollectionUtils.isEmpty(params)){
			String param = URLEncodedUtils.format(params, StandardCharsets.UTF_8);
			uri = URI.create(url+"?"+param);
		}
		//url中若带了参数,不要使用String url的方式传入,里面的+ = % &等符号会被转义或替换掉,所以传入URI对象
		response = restTemplate.exchange(uri, HttpMethod.GET, httpEntity , String.class).getBody();
	}catch (Exception e){
		log.error("请求:"+url+"时发生未知异常"+e.getMessage(),e);
	}
	return response;
}

调用:

List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("name", "tom"));
params.add(new BasicNameValuePair("age", "&%24"));

String response = get("http://localhost/8080/aa",params,null);

URL中的特殊字符

有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了。编码的格式为:%加字符的ASCII码,即一个百分号%,后面跟对应字符的ASCII(16进制)码值。对于ASCII码不了解的同学,可以参考ASCII码 http://c.biancheng.net/c/ascii/,例如 空格的编码值是"%20"。

下表中列出了一些URL特殊符号及编码

符号含义转义后
+URL 中+号表示空格%2B
空格URL中的空格可以用+号或者编码%20
/分隔目录和子目录%2F
?分隔实际的URL和参数%3F
%指定特殊字符%25
#表示书签%23
&URL 中指定的参数间的分隔符%26
=URL 中指定参数的值%3D
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值