uri遵循PFC2369规定
foo://example.com:8042/over/there?name=ferret#nose
\\_/ \\______________/\\_________/ \\_________/ \\__/
| | | | |
scheme authority path query fragment
| _____________________|__
/ \\ / \\
urn:example:animal:ferret:nose
协议规定
统一资源标志符 - 维基百科,自由的百科全书 (wikipedia.org)
**scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]
**的结构
- 协议(scheme):例如http或https。URI的方案部分应该由字母开头,后面跟着字母、数字、加号(“+”)、减号(“-”)或者点(“.”)。**
URI.create(String str)
**方法会检查方案部分是否符合这种规则。由字母开头,后面跟着字母、数字、加号(“+”)、减号(“-”)或者点(“.”)。 - 用户信息(userInfo):可选的用户信息,通常在访问需要验证的资源时使用。
- 主机名(host):服务器的名称或IP地址。URI的主机部分可以是一个域名,也可以是一个IP地址。如果是域名,那么它应该是一个有效的域名。如果是IP地址,那么它应该是一个有效的IPv4或IPv6地址。(即0-65535之间的整数)。
- 端口(port):服务器上的端口号。如果URI包含端口,那么端口应该是一个有效的端口号(即0-65535之间的整数)。
- 路径(path):服务器上资源的路径。
- 查询参数(query):查询字符串,用于向服务器传递额外的参数。参数部分应该是由有效的查询字符组成的。无效的字符应该被正确地转义。
- 片段(fragment):指向资源内部的一个标记或锚点。
url解析过程:
URI和URL的区别联系
URI:身份证号
统一资源标识符,表示Web上每一种可用的资源,如HTML文档,图像,视频片段,程序等都是由一个URI进行标识的。
Uri一定就是Url
URL:身份证住址+姓名
是URI的一个子集,统一资源定位符,URL可以用一种统一的格式来描述各种信息资源
URI解析过程
- 分解URI:将URI字符串分解为协议、主机、端口、路径和查询参数等组成部分。URI的一般格式是:
protocol://host:port/path?query
。 - 解析协议:确定URI使用的
scheme
组件(协议)(如HTTP、FTP等)。协议通常是URI的开头部分,后跟://
。 - 解析主机和端口:确定URI指向的主机和端口。主机通常是URI中
://
和/
之间的部分。 - 解析路径:确定URI指向的资源路径。路径通常是URI中主机和查询参数之间的部分,以
/
开头。 - 解析查询参数:确定URI的查询参数。查询参数通常是URI中以
?
开头的键值对。如果字符串中存在?
,解析并验证可选的query
组件(查询参数)
URI.create()源码
public static URI create(String str) {
try {
return new URI(str);
} catch (URISyntaxException x) {
throw new IllegalArgumentException(x.getMessage(), x);
}
}
//
void parse(boolean rsa) throws URISyntaxException {
requireServerAuthority = rsa;
int n = input.length();
int p = scan(0, n, "/?#", ":");//p为":"所在位置,如果找到/?#抛出异常
if ((p >= 0) && at(p, n, ':')) {
if (p == 0) // scheme为空,抛出异常
failExpecting("scheme name", 0);
checkChar(0, L_ALPHA, H_ALPHA, "scheme name");//检查scheme的合法性。scheme的第一个字符必须是字母,剩下的字符可以是字母、数字、"+"、"-"或"."。
checkChars(1, p, L_SCHEME, H_SCHEME, "scheme name");
scheme = input.substring(0, p);//截取URI的scheme部分。
p++; // Skip ':'
if (at(p, n, '/')) { //如果scheme后面紧跟着的是"/",则按照层次结构的方式解析URI
p = parseHierarchical(p, n);
} else { //否则,认为URI是不透明的
// opaque; need to create the schemeSpecificPart
int q = scan(p, n, "#");//如果URI包含"#",那么把"#"后面的部分解析为fragment。
if (q <= p)
failExpecting("scheme-specific part", p);
checkChars(p, q, L_URIC, H_URIC, "opaque part");
schemeSpecificPart = input.substring(p, q);
p = q;
}
} else {
p = parseHierarchical(0, n);
}
if (at(p, n, '#')) {
checkChars(p + 1, n, L_URIC, H_URIC, "fragment");
fragment = input.substring(p + 1, n);
p = n;
}
if (p < n)//如果在解析完所有组成部分后,还有剩余的字符,那么抛出异常,因为这些剩余的字符无法解析。
fail("end of URI", p);
}