千家信息网

如何解决RestTemplate请求url中包含百分号会被转义成25的问题

发表于:2025-01-17 作者:千家信息网编辑
千家信息网最后更新 2025年01月17日,小编给大家分享一下如何解决RestTemplate请求url中包含百分号会被转义成25的问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一
千家信息网最后更新 2025年01月17日如何解决RestTemplate请求url中包含百分号会被转义成25的问题

小编给大家分享一下如何解决RestTemplate请求url中包含百分号会被转义成25的问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

RestTemplate 请求url中包含百分号 会被转义成25

最初使用RestTemplate 进行远程调用方法如下:

private String getRemoteData(String url) {  logger.info("Request URL :" + url + "|");   String resp = rest.getForObject(url, String.class);   logger.info("Response result : " + resp.toString());  return resp; }

但发现请求结果一直为空。

最后发现由于我们的业务场景中,请求参数包含中文要求按指定规则转码,导致请求url中包含% ,而RestTemplate会自动调用encode方法进行转义,将%转义成了%25 。

解决方法

自建URI 传入:

private String getRemoteData(String url) {  logger.info("Request URL :" + url + "|");  String resp = null;  try {   URI uri = new URI(url);   resp = rest.getForObject(uri, String.class);  } catch (URISyntaxException e) {   logger.error("Create URI Exception !");  }   logger.info("Response result : " + resp.toString());  return resp; }

RestTemplate转码bug

发现一个关于HTTP的Get请求的罕见bug。

转码问题的背景

需要向tigergraph服务端发送一个复杂的get请求,参数只有一个,但是参数的值是一个复杂json

服务端收到的值始终是不正常的值。观察发现,不正常地方在于服务端本应解析为空格的地方都变成了加号(+)。

以为是代码写得有问题,然后使用HTTPclient的原生的方式发起请求:

public static String doGet(String url) throws Exception{        HttpGet get = new HttpGet(url);        return doMethod(get);    }    private static String doMethod(HttpRequestBase method)throws Exception{        CloseableHttpResponse response = null;        CloseableHttpClient client;        HttpClientBuilder hcb = HttpClientBuilder.create();        HttpRequestRetryHandler hrrh = new DefaultHttpRequestRetryHandler();        HttpClientBuilder httpClientBuilder = hcb.setRetryHandler(hrrh);        client = httpClientBuilder.build();        method.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");        method.addHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);        RequestConfig.Builder confBuilder = RequestConfig.custom();        confBuilder.setConnectTimeout(CONNECT_TIMEOUT);        confBuilder.setConnectionRequestTimeout(REQUEST_TIMEOUT);        confBuilder.setSocketTimeout(SOCKET_TIMEOUT);        RequestConfig config = confBuilder.build();        method.setConfig(config);        response = client.execute(method);        int code = response.getStatusLine().getStatusCode();        String result = EntityUtils.toString(response.getEntity());        response.close();        client.close();        return result;    }

得到结果还是这个问题,使用Assured测试工具构建http请求也有这问题。

结论

后来仔细检查了URLEncode.encode方法和RestTemplate源码实现后,发现是客户端的转码协议和服务端的解码协议不匹配导致。

经反复测试和严重,这个问题只有参数中带有空格时才会有,其他字符都不有,比如: / * & 这类特殊字符都没这问题。

最后的解决方案是替换URL串的转码后的字符串中的空格为%20,然后使用http client原生的请求方式。

第二个解决方案是使用RestTemplate的UriComponentsBuilder类,使用(builder.build(false).toUri()获得URL,参数必须是false才会把空格转成%20

/** * urlencode转码不能随便用,因为她会把空格转换成+号,而不是标准的%20字符。 * 对于spring构建的服务端不会有这个问题。但我在tiger服务器上遇到这种问题。 * 所以urlencode只适用于服务端支持的协议是RFC1738 * 如果服务端只支持RFC 2396标准,那么服务端解码时,会把加号+当成保留字符,而不转码 * */  @Override    @SuppressWarnings("all")    public  Resp doGet(String url, Req request, Class responseType) throws Exception {        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);        Map parameters = (Map)request;        for (Map.Entry entry : parameters.entrySet()) {            builder.queryParam(entry.getKey(), Objects.toString(entry.getValue(), ""));        }        return restTemplate.getForObject(builder.build(false).toUri(), responseType);    }

为什么会有这个问题?

根源在于Java语言的URLEncode类只能适用于早期的RFC协议,通常spring开发的服务端是兼容这种模式的。

新版的RFC协议会把+号当成关键字不再反转成空格,这通常体现在新技术上,比如目前用的tigergraph图数据库就有这情形。

以上是"如何解决RestTemplate请求url中包含百分号会被转义成25的问题"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

问题 服务 空格 转义 参数 字符 中包 方法 百分 百分号 篇文章 复杂 内容 加号 只有 地方 方式 方案 标准 端的 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 全面建设互联网金融科技创新 中国网络安全谷选址 怎么计算服务器带宽要多大 甘肃联想服务器虚拟化多少钱 长宁区一站式软件开发不二之选 苏州渔客网络技术 怀旧服精英服务器怎么买装备 局域网服务器怎么管理局域网 苏州戴尔服务器特惠价格 大学生会遇到的网络安全问题 switch一键迁移数据库 专业网络技术分类服务标准 移动硬盘作小型服务器 临沂网络安全教育周 河北通用软件开发参考价格 软件开发技术的介绍 每个实例只能有一个数据库 软件开发测试缺陷的露出 网络安全日主题班会ppt 雅马哈AOI元件数据库对照表 戴尔服务器虚拟机控制网站 数据库建表中的说明怎么写 神奇宝贝服务器游戏视频 广州合纵网络技术有限公司 数据库什么实验室 软件开发公司市场 网络安全总结小学 java怎样将图片存进数据库 数据库查询当前时间字符串 服务器白名单域名免备案
0