1.1问题描述
运行上图的程序,两个方法专入同样的url,但执行结果则不相同
1、调用restTemplate.getForEntity(URI url, Class<T> responseType)则返回正常;
2、调用restTemplate.getForEntity(String url, Class<T> responseType)返回异常(404 Not_FOUND)如下图所示:
1.2 原因分析
通过请求地址和日志分确认是因为请求的地址path(/csh/d20/a149/e14506/p4731//9e76224c85f8454f8b65992ee3caa038.jpg?imageInfo)中存在//的情况,通过restTemplate.getForEntity(String url, Class<T> responseType)调用时,底层会将“//”替换成“/”从而引起请求的地址发生变,最终返回404。
通过debug调试可以发现,当传入url参数时RestTemplate内部分调用UriTemplateHandler. expand(String uriTemplate, Object... uriVariables)方法将url转换URI对象,如下图:
在内部实现过程中首先会将url拆分成一个HierarchicalUriComponents对象(包括协议、地址、端口以及path等),同时会对path进行一次格式化,具体代码如下:
经过该方法后会自动将//替换为/,因此导致最终调用的地址发生了改变。
1.3解决方案
1、确保请求的地址中的path中尽量不能存在//的情况;
2、使用RestTemplate调用外部接口时,尽量不使用restTemplate.getForEntity(String url, Class<T> responseType)方法,可以在调用之前通过URI.create(url)将url转换为URI再调用相关的方法。