Java Spring Boot中RestTemplate.exchange请求URL二次编码问题如何解决?
问题原因
Spring Boot自带的RestTemplate默认会对传入的字符串类型URL做自动URL编码处理:当你传入已经完成编码的URL时,RestTemplate会将URL中已有的百分号%识别为普通特殊字符,再次编码为%25,最终就出现了%2F变为%252F这类二次编码问题。
解决方案
可以根据你的业务场景选择以下任意一种方案处理:
- 方案1:将已编码的URL转为URI对象传入
如果你拿到的URL已经是完成编码的完整地址,直接用URI.create()将字符串转为URI对象再调用exchange方法,RestTemplate就不会再做二次编码:protected String requestData(String url,HttpEntity headers){ System.out.println(url); URI uri = URI.create(url); return new RestTemplate().exchange(uri, HttpMethod.GET,headers,String.class).getBody(); } - 方案2:使用占位符方式传参,由RestTemplate统一编码
如果参数是你自行拼接的,不要手动编码后拼到URL上,改用占位符传参让RestTemplate统一做一次编码,避免编码时机冲突:protected String requestData(HttpEntity headers){ String baseUrl = "http://data.gb.go.kr/opendata/service/rest/gbDongrak/getRecordList?numOfRows={numOfRows}&pageNo={pageNo}&serviceKey={serviceKey}&b_year={b_year}&b_month={b_month}"; // 构造参数Map,serviceKey传入原始未编码的值即可 Map<String, Object> paramMap = new HashMap<>(); paramMap.put("numOfRows", 10); paramMap.put("pageNo", 1); paramMap.put("serviceKey", "K/hDtuwgRPJ287yiPCY4lRN9nbdVwy6/qDM9BFW/Imn7TpcqXMI+S4/6/5GuRyoMudE5SnR6a4xpj62S2OnIjw=="); paramMap.put("b_year", 2020); paramMap.put("b_month", "09"); return new RestTemplate().exchange(baseUrl, HttpMethod.GET, headers, String.class, paramMap).getBody(); } - 方案3:修改RestTemplate全局编码策略(不推荐)
如果你需要统一处理所有RestTemplate请求的编码逻辑,可以修改UriBuilderFactory的编码模式为NONE,关闭默认自动编码:
注意该方案会全局关闭编码逻辑,如果你传入未编码的URL可能会出现请求异常,仅建议你所有请求的URL都自行完成编码时使用。RestTemplate restTemplate = new RestTemplate(); DefaultUriBuilderFactory uriFactory = new DefaultUriBuilderFactory(); uriFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE); restTemplate.setUriTemplateHandler(uriFactory);
内容的提问来源于stack exchange,提问作者swz
相关产品推荐
相关产品推荐

