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

RestTemplate exchange方法URI双重编码致404问题求助

我来帮你解决这个问题!你遇到的其实是URL二次编码的问题——你手动把空格转成了%20,但RestTemplate默认会对整个URI再次编码,导致%被转成%25,于是%20就变成了%2520,这自然会让XWiki找不到对应的资源。

核心原因

RestTemplate的exchange方法如果接收的是字符串类型的URL,会默认把它当作未编码的原始字符串进行编码处理。而你已经提前将空格转成了%20,这就导致%字符被二次编码为%25,最终出现%2520的错误格式。

解决方案1:让UriComponentsBuilder自动处理编码(推荐)

不要提前手动编码URL,而是使用原始的带空格的路径,让UriComponentsBuilder帮你完成编码工作,从根源避免二次编码:

public static void main(String[] args) throws IOException, URISyntaxException {
    // 使用原始空格的路径,不要手动转%20
    String baseUrl = "http://swininducasa02.ptx.fr.sopra:8080/xwiki-enterprise-web-8.4.5/rest/wikis/xwiki/spaces/Main/spaces/PIC/spaces/Serveur de virtualisation/spaces/Serveur de Marcoussis/spaces/choix/spaces/SGBFV/pages/WebHome";
    
    String plainCreds = "user:passwd";
    byte[] plainCredsBytes = plainCreds.getBytes();
    byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
    String base64Creds = new String(base64CredsBytes);

    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Basic " + base64Creds);
    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

    // 构建正确编码的URI,自动处理空格转%20
    URI uri = UriComponentsBuilder.fromHttpUrl(baseUrl)
            .queryParam("media", "json")
            .build()
            .toUri();

    RestTemplate restTemplate = new RestTemplate();
    System.out.println("Begin /GET request!");
    HttpEntity<String> request = new HttpEntity<>(headers);
    ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, request, String.class);

    Map<String, String> map = new ObjectMapper().readValue(response.getBody(), Map.class);
    System.out.println(map.get("content"));
}

解决方案2:直接使用已编码的URI对象

如果你必须使用已经手动编码好的URL字符串,可以直接创建URI对象传入exchange方法——当传入URI对象时,RestTemplate会跳过编码步骤:

public static void main(String[] args) throws IOException, URISyntaxException {
    String link = "http://swininducasa02.ptx.fr.sopra:8080/xwiki-enterprise-web-8.4.5/rest/wikis/xwiki/spaces/Main/spaces/PIC/spaces/Serveur%20de%20virtualisation/spaces/Serveur%20de%20Marcoussis/spaces/choix/spaces/SGBFV/pages/WebHome";
    
    String plainCreds = "user:passwd";
    byte[] plainCredsBytes = plainCreds.getBytes();
    byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
    String base64Creds = new String(base64CredsBytes);

    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Basic " + base64Creds);
    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

    // 直接创建URI对象,避免二次编码
    URI uri = new URI(link + "?media=json");

    RestTemplate restTemplate = new RestTemplate();
    System.out.println("Begin /GET request!");
    HttpEntity<String> request = new HttpEntity<>(headers);
    ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, request, String.class);

    Map<String, String> map = new ObjectMapper().readValue(response.getBody(), Map.class);
    System.out.println(map.get("content"));
}

为什么你之前的尝试没成功?

你之前用UriComponentsBuilder.fromPath(link).build(true)时,link已经是编码后的字符串,fromPath会把它当作原始路径处理,依然会对%字符进行编码,所以问题没有解决。正确的做法要么用原始路径让工具自动编码,要么直接用URI对象跳过编码环节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:16:11