You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Spring RestTemplate正确转义URL变量(含加号转义)

解决RestTemplate GET请求中URL参数加号(+)的正确转义问题

我太懂这个痛点了!当用RestTemplate.exchange发送带参数的GET请求时,参数里的加号(+)总是被Spring当成空格解析,试过UriComponentsBuilder和UriTemplate都只能搞定空格,加号死活不转义对吧?这其实是Spring默认的URI编码规则在搞鬼。

为啥会这样?

Spring默认遵循RFC 3986规范处理URI编码,在Query参数里,加号(+)被定义成了空格的等价表示。所以默认的expand()和encode()方法根本不会把参数里的加号转成%2B——它觉得这是合法的空格替代符,不是你要传递的实际字符。

靠谱的解决方案

这里有两种方法能彻底解决这个问题,按需选择就行:

方法1:手动给参数做URL编码

直接用URLEncoder单独编码每个参数值,把加号转成%2B,再传给URI构建工具或者RestTemplate。注意只编码参数值,别编码整个URL,不然会把?、&这些关键符号也编码了,URI就失效了。

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.client.RestTemplate;

public class ManualEncodingExample {
    public static void main(String[] args) {
        String foo = "fo+o";
        String bar = "ba r";
        
        // 手动编码参数,一定要指定UTF-8字符集
        String encodedFoo = URLEncoder.encode(foo, StandardCharsets.UTF_8);
        String encodedBar = URLEncoder.encode(bar, StandardCharsets.UTF_8);
        
        // 构建正确的URI
        UriComponentsBuilder ucb = UriComponentsBuilder.fromUriString("http://example.com/?foo={foo}&bar={bar}");
        String finalUri = ucb.buildAndExpand(encodedFoo, encodedBar).toUriString();
        
        // 用RestTemplate发送请求
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.exchange(finalUri, HttpMethod.GET, null, String.class);
    }
}

方法2:给RestTemplate配置自定义编码策略

这个方法更优雅,不用手动编码每个参数,直接给RestTemplate设置一个自定义的URI构建工厂,强制对参数值做完整编码,包括把加号转成%2B。

import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriBuilderFactory;

public class ConfiguredRestTemplateExample {
    public static void main(String[] args) {
        RestTemplate restTemplate = new RestTemplate();
        
        // 创建URI构建工厂,设置编码模式为「仅编码参数值」
        DefaultUriBuilderFactory uriFactory = new DefaultUriBuilderFactory();
        uriFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
        
        // 把这个工厂设置给RestTemplate
        restTemplate.setUriTemplateHandler(uriFactory);
        
        String foo = "fo+o";
        String bar = "ba r";
        
        // 直接发请求就行,参数会自动被正确编码
        restTemplate.exchange(
            "http://example.com/?foo={foo}&bar={bar}",
            HttpMethod.GET,
            null,
            String.class,
            foo,
            bar
        );
    }
}

这个配置下,RestTemplate会自动把foo=fo+o编码成foo=fo%2Bo,bar=ba r编码成bar=ba%20r,完美匹配你的需求。

再说说你之前的尝试

你用UriComponentsBuilder和UriTemplate没搞定,就是因为它们默认的编码逻辑不处理加号——毕竟RFC规范里加号是空格的合法替代。只有显式指定编码策略,或者手动编码参数,才能让加号被当作普通字符转义成%2B。

内容的提问来源于stack exchange,提问作者Pablo Fernandez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:14:37