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

如何在Java 8中规避JDK-8272702缺陷实现相对URI正确解析

解决Java 8中URI相对路径解析的JDK-8272702缺陷

Java 8的java.net.URI.resolve()方法存在JDK-8272702缺陷:当基础URI(base URI)没有末尾斜杠且路径为空时(如https://a.com),解析相对路径会错误拼接,例如将https://a.com和path拼成https://a.compath,而非预期的https://a.com/path。Java 21已修复该问题,以下是兼容Java 8的通用解决方案,支持所有URI协议。

实现思路

针对层次化URI(如HTTP/HTTPS/FTP等),如果基础URI的路径为空且无末尾斜杠,先为其添加单个斜杠,再调用原生resolve()方法;非层次化URI(如mailto)直接使用原生解析逻辑,无需调整。

代码实现

import java.net.URI;
import java.net.URISyntaxException;

public class UriResolver {

    public static URI resolveUri(URI baseUri, String relativePath) throws URISyntaxException {
        // 非绝对URI直接用原生解析
        if (!baseUri.isAbsolute()) {
            return baseUri.resolve(relativePath);
        }

        // 非层次化URI(如mailto)无需调整,直接解析
        if (baseUri.isOpaque()) {
            return baseUri.resolve(relativePath);
        }

        // 层次化URI:路径为空时,添加末尾斜杠
        String basePath = baseUri.getPath();
        URI adjustedBase = baseUri;
        if (basePath == null || basePath.isEmpty()) {
            adjustedBase = new URI(
                    baseUri.getScheme(),
                    baseUri.getUserInfo(),
                    baseUri.getHost(),
                    baseUri.getPort(),
                    "/",
                    baseUri.getQuery(),
                    baseUri.getFragment()
            );
        }

        return adjustedBase.resolve(relativePath);
    }

    // 测试示例
    public static void main(String[] args) throws URISyntaxException {
        // HTTP基础URI无斜杠的情况
        URI base = new URI("https://a.com");
        System.out.println(resolveUri(base, "path")); // 输出: https://a.com/path

        // 带端口的HTTP URI
        base = new URI("http://localhost:8080");
        System.out.println(resolveUri(base, "api/v1/users")); // 输出: http://localhost:8080/api/v1/users

        // 已有路径的基础URI
        base = new URI("https://a.com/foo");
        System.out.println(resolveUri(base, "bar")); // 输出: https://a.com/bar

        // 非层次化mailto URI
        base = new URI("mailto:user@example.com");
        System.out.println(resolveUri(base, "?subject=Greeting")); // 输出: mailto:user@example.com?subject=Greeting

        // FTP协议URI
        base = new URI("ftp://ftp.example.org");
        System.out.println(resolveUri(base, "docs/readme.txt")); // 输出: ftp://ftp.example.org/docs/readme.txt
    }
}

关键说明

  • 协议兼容性:通过isOpaque()区分层次化与非层次化URI,确保mailto、tel等特殊协议不受影响。
  • 无侵入调整:仅在基础URI路径为空时添加斜杠,不改变已有路径的URI解析逻辑(如https://a.com/foo解析bar仍得到https://a.com/bar)。
  • 保留原属性:调整基础URI时,完整保留scheme、用户信息、主机、端口、查询参数、片段等所有原生属性。
  • 异常兼容:抛出URISyntaxException与原生URI方法一致,保持API行为一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:49:59