[转载]URI 源码分析
需要提前了解下什么是URI,及URI和URL的区别:
URI、 URL 和 URN 的区别
URI 引用包括最多三个部分:模式、模式特定部分和片段标识符。一般为:
模式:模式特定部分:片段
如果省略模式,这个URI引用则是相对的。如果省略片段标识符,这个URI引用就是一个纯URI。
URI是对URL的抽象,不仅包括统一资源定位符URL,还包括统一资源名URN。实际上使用的URI大多都是URL。在java中,URI使用java.net.URI类表示,URI类只能标识资源,和解析URI,而不能获取URI所标识的资源(URN是无法定位到资源的)。
构造
public URI(String str) throws URISyntaxException {
new Parser(str).parse(false);
}
public URI(String scheme, String host, String path, String fragment)
throws URISyntaxException{
this(scheme, null, host, -1, path, null, fragment);
}
public URI(String scheme,
String authority,
String path, String query, String fragment)
throws URISyntaxException{
....
}
public URI(String scheme,
String userInfo, String host, int port,
String path, String query, String fragment)
throws URISyntaxException{
...
}
public URI(String scheme, String ssp, String fragment) throws URISyntaxException {
new Parser(toString(scheme, ssp, null, null, null, -1, null, null, fragment)).parse(false);
}
URI类提供了5中构造方法
- 根据提供的一个uri字符串构造一个URI对象。
- 主要针对层次的URI。通过 模式、服务器地址、文件路径、片段标识构造URI。
- 主要针对层次的URI。通过 模式、授权机构、文件路径、查询条件、片段标识构造URI。
- 主要针对层次的URI。通过 模式、用户信息、服务器地址、端口、文件路径、查询条件、片段标识构造URI。
- 主要针对非层次URI。通过 模式、模式特定部分和片段标识创建URI。
create方法
public static URI create(String str) {
try {
return new URI(str);
} catch (URISyntaxException x) {
throw new IllegalArgumentException(x.getMessage(), x);
}
}
如果可以确认URI的格式正确,可使用create的工厂方法创建URI。因为该方法不会抛出URISyntaxException异常。
是否透明URL
URI通常情况下都是层次(带“/”)的,但是也有不透明(没有“/”)的,层次的URI包含模式,主机,站点等各个部分,当然可能某些部分不包含,但是不透明的URI只包含三个部分,Scheme,Scheme-specific-part,Fragment.
如:mailto:jijianshuai@infcn.com.cn
public boolean isOpaque() {
return path == null;
}
判断path是否为空,如果为空则是不透明的,说明URI中没有“/”。

在URI构造器中解析URI,代码:new Parser(str).parse(false);
判断URI中是否存在“/”符号,如果存在就是有层次结构的URI。
如果存在“/”,则调用parseAuthority方法进行解析path。
URI获取各部分信息
- 获得模式
public String getScheme(); - 获得模式特定部分
public String getSchemeSpecificPart();
public String getRawSchemeSpecificPart(); - 获得片段
public String getFragment();
public String getRawFragment(); - 获得授权机构
public String getAuthority();
public String getRawAuthority()
授权机构包括:用户信息、服务器地址(域名或ip)、端口
user:password@localhost:80 - 获取片段标识
public String getFragment()
public String getRawFragment() - 获取服务器地址(域名或ip)
public String getHost() - 获取路径
public String getPath()
public String getRawPath()
路径包括(目录结构和文件部分)。如:/dir/index.html - 获取端口
public int getPort()
如果没有端口则返回-1; - 获取URI的查询字符串
public String getQuery()
public String getRawQuery() - 获取用户信息
public String getUserInfo()
public String getRawUserInfo()
如果URI是非透明只能获取到1~3个信息。
如果URI是层次结构则能获取所有信息。
方法中带Raw的,是获取编码后的URI部分信息。非ascii的字符需要进行编码,不带Raw的方法是解码后的信息。
getScheme、getHost、getPort这三个方法没有Raw方法,是因为这三部分不会出现非ascii的字符。
resolve 方法
resolve方法可以将相对URI转换成绝对URI。示例如下:
URI a = URI.create("http://localhost:8080/index.html");
URI b = URI.create("user/userInfo.html");
URI c = a.resolve(b);
System.out.println(c);
根据a获取b的绝对路径
打印结果为:http://localhost:8080/user/userInfo.html
源码如下
public URI resolve(URI uri) {
return resolve(this, uri);
}
private static URI resolve(URI base, URI child) {
// check if child if opaque first so that NPE is thrown
// if child is null.
if (child.isOpaque() || base.isOpaque())
return child;
// 5.2 (2): Reference to current document (lone fragment)
if ((child.scheme == null) && (child.authority == null)
&& child.path.equals("") && (child.fragment != null)
&& (child.query == null)) {
if ((base.fragment != null) && child.fragment.equals(base.fragment)) {
return base;
}
URI ru = new URI();
ru.scheme = base.scheme;
ru.authority = base.authority;
ru.userInfo = base.userInfo;
ru.host = base.host;
ru.port = base.port;
ru.path = base.path;
ru.fragment = child.fragment;
ru.query = base.query;
return ru;
}
// 5.2 (3): Child is absolute
if (child.scheme != null)
return child;
URI ru = new URI(); // Resolved URI
ru.scheme = base.scheme;
ru.query = child.query;
ru.fragment = child.fragment;
// 5.2 (4): Authority
if (child.authority == null) {
ru.authority = base.authority;
ru.host = base.host;
ru.userInfo = base.userInfo;
ru.port = base.port;
String cp = (child.path == null) ? "" : child.path;
if ((cp.length() > 0) && (cp.charAt(0) == '/')) {
// 5.2 (5): Child path is absolute
ru.path = child.path;
} else {
// 5.2 (6): Resolve relative path
ru.path = resolvePath(base.path, cp, base.isAbsolute());
}
} else {
ru.authority = child.authority;
ru.host = child.host;
ru.userInfo = child.userInfo;
ru.host = child.host;
ru.port = child.port;
ru.path = child.path;
}
// 5.2 (7): Recombine (nothing to do here)
return ru;
}
- 是否是非透明URI,如果是,则直接返回child。
- 判断child是否只有fragment(片段标识)。如果child只有片段标识则执行2.1。否则执行3。
2.1 如果child的fragment和base的片段标识一样,就直接返回base的url
2.2 把base不包含fragment的部分和child的fragment构造一个新的URI返回。 - 判断child的scheme不为空则直接返回child。不为空说明他是绝对路径。
- 根据base的URI各部分构造child的绝对路径URI并返回。
relativize 方法
relativize 方法可以将绝对路径的URI转换成相对路径的URI。
URI a = URI.create("http://localhost:8080/");
URI b = URI.create("http://localhost:8080/index.html");
URI c = a.relativize(b);
System.out.println(c);
获取b相对a的相对路径。
打印的结果为:index.html
private static URI relativize(URI base, URI child) {
// check if child if opaque first so that NPE is thrown
// if child is null.
if (child.isOpaque() || base.isOpaque())
return child;
if (!equalIgnoringCase(base.scheme, child.scheme)
|| !equal(base.authority, child.authority))
return child;
String bp = normalize(base.path);
String cp = normalize(child.path);
if (!bp.equals(cp)) {
if (!bp.endsWith("/"))
bp = bp + "/";
if (!cp.startsWith(bp))
return child;
}
URI v = new URI();
v.path = cp.substring(bp.length());
v.query = child.query;
v.fragment = child.fragment;
return v;
}
- 判断child是否不是透明URI,如果不是则直接返回child。不是层次结构的uri是没有相对路径的。
- 判断两个URI的scheme和授权机构是否不同,如果不同则直接返回child。
- 判断base是否“/”结尾,如果不是则加上“/”
- 判断child是否以base开头,如果不是则直接返回child。
- 返回child中,不包含base的部分,构造一个新URI返回。
作者:jijs
链接:https://www.jianshu.com/p/24a2da876372
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
[转载]URI 源码分析的更多相关文章
- [转载]URL 源码分析
URI 引用包括最多三个部分:模式.模式特定部分和片段标识符.一般为: 模式:模式特定部分:片段 如果省略模式,这个URI引用则是相对的.如果省略片段标识符,这个URI引用就是一个纯URI. URI是 ...
- [转载] Netty源码分析
转载自http://blog.csdn.net/kobejayandy/article/details/11836813 Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高 ...
- ArrayList实现原理及源码分析之JDK8
转载 ArrayList源码分析 一.ArrayList介绍 Java 集合框架主要包括两种类型的容器: 一种是集合(Collection),存储一个元素集合. 一种是图(Map),存储键/值对映射. ...
- 转载-HashMap1.7源码分析
原文地址-https://www.cnblogs.com/chengxiao/p/6059914.html HashMap实现原理及源码分析 哈希表(hash table)也叫散列表,是一种非常重 ...
- EasyUI学习总结(三)——easyloader源码分析(转载)
声明:这一篇文章是转载过来的,转载地址忘记了,原作者如果看到了,希望能够告知一声,我好加上去! easyloader模块是用来加载jquery easyui的js和css文件的,而且它可以分析模块的依 ...
- jQuery源码分析系列(转载来源Aaron.)
声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...
- ArrayList源码分析超详细(转载)
ArrayList源码分析超详细 ArrayList源码分析超详解 想要分析下源码是件好事,但是如何去进行分析呢?以我的例子来说,我进行源码分析的过程如下几步: 找到类:利用 IDEA 找到所需要 ...
- 【转载】Android异步消息处理机制详解及源码分析
PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbob ...
- 【转载】Android应用AsyncTask处理机制详解及源码分析
[工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 1 背景 Android异步处理机制一直都是Android的一个核心,也是应用工程师面试的一个 ...
随机推荐
- Contributed to JFairy
虽然delay了一个多月才看到,但第一次被一个开源项目正式感谢,开心. 其实写过的很多东西都有机会contr的,只是有些是公司代码...
- (63)Wangdao.com第十天_预处理、预解析_函数 上下文对象、参数列表对象
预解析.预处理 1. 在全局代码执行之前,js 引擎 就会创建一个栈来存储管理所有的 执行上下文对象 2. 在 全局执行上下文 window 确定以后,进行压栈 3. 在 函数执行上下文对象 确定以后 ...
- [LeetCode] All Paths From Source to Target 从起点到目标点到所有路径
Given a directed, acyclic graph of N nodes. Find all possible paths from node 0 to node N-1, and re ...
- Laravel项目部署上线(阿里云 Ubuntu 16.04)
第一次尝试把本地的项目上线, 购买了某云的轻量应用服务器, 镜像为Ubuntu 16.04 直接运行 apt-get install nginx 出错 根据提示运行 apt-get upda ...
- vscode插件安装失败的解决方案
在vscode中点击对应插件的install按钮安装,安装失败,软件提示手动安装(manually install). 手动下载vsix安装包,然后点击install from VSIX...,选择v ...
- Jmeter应用-接口测试
1.BS架构应用性能 2.HTTP协议接口功能与性能 3.FTP协议接口功能与性能 4.Mysql数据库性能 5.MongoDB数据库性能 6.支持自定义Java组件开发 测试计划-右键-添加线程组 ...
- 七、Servlet概述
Servlet概述 生命周期方法:void init(ServletConfig):出生之后(1次):void service(ServletRequest request, ServletRes ...
- CSP201312-4 有趣的数【dp】
问题描述 试题编号: 201312-4 试题名称: 有趣的数 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, ...
- 腾讯云“智能+互联网TechDay”:揭秘智慧出行核心技术与创新实践
现如今,地面交通出行与大家的生活息息相关.在当前城市道路日益复杂和拥挤的情况下,如何保证交通出行的安全和便捷相信是每个人以及众多专家.科研工作者重点关注的问题. “智慧交通”系统是解决交通发展瓶颈的有 ...
- CGI的工作原理
文章摘自https://blog.csdn.net/nyist327/article/details/41049699 CGI是Web服务器和外部程序之间的一个接口.利用CGI程序可以处理从Web上客 ...