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

Java 11中java.net.URI为何不编码所有保留字符?

Java.net.URI构造函数的编码逻辑疑问及自定义编码实现困惑

我想用scheme、userInfo、host、port、path、query、fragment这些独立URI组件创建java.net.URI实例,该类提供了对应的构造函数,源码如下:

public URI(String scheme,
           String authority,
           String path, String query, String fragment)
    throws URISyntaxException
{
    String s = toString(scheme, null,
                        authority, null, null, -1,
                        path, query, fragment);
    checkPath(s, scheme, path);
    new Parser(s).parse(false);
}

该构造函数会对path、query和fragment部分进行编码,若传入已编码字符串会导致双重编码。

根据该构造函数的JavaDoc描述:

  • 若传入path,则追加该路径。仅对非未保留字符、非标点字符、非转义字符,且不是斜杠(/)或@字符的内容进行编码。
  • 若传入query,则追加问号(?)和query内容。仅对非法URI字符进行编码。
  • 若传入fragment,则追加哈希(#)和fragment内容。仅对非法URI字符进行编码。

其中明确,未保留字符、标点字符(包含!、#、$、&、'、(、)、*、+、,、;、=、:)以及转义字符不会被编码。

根据RFC 3986的定义,保留字符分为以下两类:

reserved    = gen-delims / sub-delims

gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"

sub-delims  = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

我的疑问是,@、/、+明明属于保留字符,为什么java.net.URI的构造函数不对它们进行编码?

比如下面的测试代码:

String scheme = "http";
String userInfo = "username:password";
String host = "example.com";
int port = 80;
String path = "/path/t+/resource";
String query = "q=search+term";
String fragment = "section1";

URI uri = new URI(scheme, userInfo, host, port, path, query, fragment);

uri.toString(); // 结果中path里的`+`不会被编码

我还困惑,如果这种行为是正确的,那RFC为什么要把这些字符定义为保留字符?另外我正尝试实现一个完整URI字符串的编码函数,需要提取各组件分别编码后再重组,现在不知道该遵循哪种规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:30:59