Spring RestTemplate:如何让fromUriString保留URL中的#字符
解决RestTemplate传递含#字符密码被截断的问题
这个问题我之前也碰到过,核心原因是**#在URI规范里是片段标识符的起始字符**,默认的URI解析逻辑会把#后面的内容当成页面内锚点,不会作为请求参数的一部分发送给服务器,自然就被"丢弃"了。下面给你几个靠谱的解决办法:
方法一:用UriComponentsBuilder构建编码后的URI
这是最推荐的方式,Spring提供的UriComponentsBuilder会自动帮你处理参数编码,完全不用手动操心:
import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; public class RestTemplateExample { public static void main(String[] args) { String password = "myPass#123"; // 构建URI组件,自动编码参数 UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("http://your-server.com/api/auth") .queryParam("username", "testUser") .queryParam("password", password) .build(true); // 传入true表示对所有组件进行URL编码 RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> response = restTemplate.getForEntity(uriComponents.toUri(), String.class); } }
这里的build(true)是关键,它会把密码里的#转换成%23,这样服务器就能正确解析到完整的密码字符串。
方法二:手动编码密码参数
如果你习惯直接拼接URL,可以用Spring的UriUtils工具类手动编码密码部分(别用Java自带的URLEncoder,它的编码规则和URI规范不完全一致):
import org.springframework.web.util.UriUtils; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import java.nio.charset.StandardCharsets; public class RestTemplateManualEncode { public static void main(String[] args) { String password = "myPass#123"; // 手动编码密码,指定UTF-8字符集 String encodedPassword = UriUtils.encode(password, StandardCharsets.UTF_8.name()); // 拼接成完整URL String url = String.format("http://your-server.com/api/auth?username=testUser&password=%s", encodedPassword); RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> response = restTemplate.getForEntity(url, String.class); } }
为什么不能直接让fromUriString保留#?
这里要澄清一个误区:原始的#字符根本不应该出现在查询参数里。根据URI规范,#是保留字符,专门用来标识片段,如果你不编码直接传递,HTTP客户端(包括RestTemplate)会自动把#后面的内容从请求URL中剥离,服务器永远接收不到这部分内容。所以正确的做法是编码,而不是强制保留原始的#。
内容的提问来源于stack exchange,提问作者junderwood
相关产品推荐
相关产品推荐

