Java魔法堂:URI、URL(含URL Protocol Handler)和URN
一、前言
过去一直搞不清什么是URI什么是URL,现在是时候好好弄清楚它们了!本文作为学习笔记,以便日后查询,若有纰漏请大家指正!
二、从URI说起
1. 概念
URI(Uniform Resource Identifier,统一资源标识符)以字符串来表示某种资源的统一资源标识。
格式为: [scheme:]scheme-specific-part[#fragment]
[scheme:]组件 ,URI的名称空间标识。
scheme-specific-part组件 ,用于标识资源,内部格式由具体的 scheme 来决定。
[#fragment]组件 ,井号(#)作为fragment组件的起始字符,而fragment组件则用于聚焦到资源的某个部分。
2. 绝对URI和相对URI
绝对URI:以scheme组件起始的完整格式,如http://fsjohnhuang.cnblogs.com。表示以对标识出现的环境无依赖的方式引用资源。
相对URI:不以scheme组件起始的非完整格式,如fsjohnhuang.cnblogs.com。表示以对依赖标识出现的环境有依赖的方式引用资源。
实例:当前页面地址为http://fsjohnuang.cnblogs.com
// html snippet
<a id="test" href="test.com">test.com</a> // js snippet
<script>
var href = document.getElementById('test').href
console.log(href) // 显示 http://test.com
</script>
3. 不透明URI和分层URI
不透明URI:scheme-specific-part组件不是以正斜杠(/)起始的,如mailto:fsjohnhuang@xxx.com。由于不透明URI无需进行分解操作,因此不会对scheme-specific-part组件进行有效性验证。
分层URI:scheme-specific-part组件是以正斜杠(/)起始的,如http://fsjohnhuang.com。
scheme-specific-part组件格式为: [//authority][path][?query]
[//authority] ,表示授权机构组件,以一对正斜杠(//)起始,可以基于主机(server-based)或注册(registry-based)(而基于注册相对基于主机的数目较少),并以正斜杠、问号或无后续字符作为authority组件的结束。而authority组件的具体格式为 [userinfo@]host[:port] 。
[userinfo@] ,用户账号。
host ,主机IP或域名。
[:port] ,通信端口号,若省略则使用相应的scheme组件的默认端口号。
示例: http://fsjohnhuang@github.com:80/
[path] ,path组件表示根据authority组件识别资源的位置。path组件有一系列的路径片段(path segment)构成,路径片段间以正斜杠(/)作为分隔符。若第一个路径片段以正斜杠(/)起始则为绝对路径,否则称为相对路径。
[?query] ,query组件用于识别要传递给资源的数据,用于影响资源的响应的行为。
4. 标准化(Normalization)、解析化(Resolution)和相对化(Relativization)
标准化(Normalization):其实就是去除path组件中当前层(.)和上一层(..)这些冗余字符。如z/../y标准化为y。
解析化(Resolution):以URI A作为基本URI来和另外一个URI一同解析为一个新的标准URI。如http://fsjohnhuang.com作为基本URI和z/../y一同解析成http://fsjohnhuang.com/y。
相对化(Relativization):相对化其实就是解析化的相反操作。如http://fsjohnhuang.com作为基本URI和http://fsjohnhuang.com/z来作相对化操作得到/z。
到这里我们可能会认为这不就跟平常的网站地址一样吗?为啥大家叫网站地址为URL,而不是URI呢?
互联网之父Tim Berners-Lee引入用于识别、定位和命名互联网资源的途径——URI、URL和URN。三者彼此关联,URI的范畴位于体系的顶层,URL和URN的范畴位于体系的底层。
- URI:Uniform Resource Identifier,统一资源标识符;
- URL:Uniform Resource Locator,统一资源定位符;
- URN:Uniform Resource Name,统一资源名称。
上图可知URL和URN必须是URI,但URI却不一定是URL或URN。
URI仅仅是资源名称而已,知道了URI最多就是知道有这么一个名称的资源罢了,至于如何获取(与资源作交互)则是毫无头绪(不能定位或读取/写入资源),而这个资源名称是永久持有还是暂时持有也没有相应的规定,于是就有了URL和URN两个子集。
首先URL和URN均继承了URI格式中的各组件,然后在这基础上进行了各自的扩展?
URL
URL = URI(scheme组件为部分已知的网络协议的URI子集) + 与scheme组件标识的网络协议匹配的协议处理器(URL Protocol Handler)
1. URI的scheme组件在URL中称为protocol组件,一般http、https、ftp、file、data、jar等。
2. URL Protocol Handler则是一种资源定位器和根据协议建立的约束规则与资源通信的读写机制,用于定位、读写资源。
如:安装迅雷后点击ed2k的迅雷种子时则会自动打开迅雷下载界面,这是为什么呢?
迅雷种子就是资源,而ed2k就是资源URL的protocol组件,而迅雷就是URL Protocol Handler。而protocol组件与URL Protocol Handler间的映射关系在windows下则存放在注册表中,而Ubuntu中存放在/usr/share/applications/.desktop中。
windows7下
①. 快捷键“开始”+r 弹出运行输入框,输入regedit进入注册表;
②. 进入HKEY_CURRENT_USER/Software/Classes目录下;
③. ed2k目录下包含shell/Open/command目录,右侧窗口有一个条名称为URL Protocol的REG_SZ记录,表示这是一个URL Protocol记录(没有这一条记录也不会有影响)
④. 点击command目录后,右侧窗口有一条REG_SZ类型记录,数据列为"C:\Program Files (x86)\Thunder Network\Thunder\Program\ThunderNewTask.exe" "%1" 表示ThunderNewTask.exe作为URL Protocol Handler,而%1则是传递给Handler处理的URL。
⑤. 其实ed2k中还少了一个DefaultIcon目录,该目录下有一个REG_SZ类型的记录,用于指定该类型协议文件的图标。
ubuntu下
在/usr/share/applications/.desktop文件下添加如下内容
[Desktop Entry]
Encoding=UTF-
Version=1.0
Type=Application
Terminal=false
Exec=/usr/bin/cloudjerun -c %u
Name=tunesview
Comment=Small, easy-to-use program to access iTunesU media
Icon=/usr/share/icons/hicolor/scalable/apps/tunesview.svg
Categories=Application;Network;
MimeType=x-scheme-handler/cloudje;
Exec键值的占位符表:
Add... Accepts...
%f a single filename.
%F multiple filenames.
%u a single URL.
%U multiple URLs.
%d a single directory. Used in conjunction with %f to locate a file.
%D multiple directories. Used in conjunction with %F to locate files.
%n a single filename without a path.
%N multiple filenames without paths.
%k a URI or local filename of the location of the desktop file.
%v the name of the Device entry.
3. URL与资源地址关联,当资源位置变更后,URL也需要被修改。
URN
URN = URI(scheme组件为部分已知的网络协议的URI子集) + 与scheme组件标识的网络协议匹配的协议处理器(URL Protocol Handler) + 持久性/地址无关性
URN用于持久性地标识Internet资源,即使资源已经不存在或不可用时依然保持不变,通过实际的持久性策略实现资源位置发生变化也不用修改URI(地址无关性)。然而通过持久性策略还可以实现一条URN对应N条URI,如BT中的磁力链接(Magnet URI scheme)。
如:magnet:?xt=urn:btih:4D9FA761D69964B00DF0B3B0C9C1F968EA6C47D0&xt=urn:ed2k:7655dbacff9395e579c4c9cb49cbec0e&dn=bbb_sunflower_2160p_30fps_stereo_abl.mp4
说了这么多是时候总结一下URI、URL和URN的关联和区别了!
1. 首先URI是基础,URL和URN均属于URI;
2. URL = URI(scheme组件为部分已知的网络协议的URI子集) + 与scheme组件标识的网络协议匹配的协议处理器(URL Protocol Handler);
3. URN突出的是持久化,通过具体的持久化策略实现地址无关性。 URN = URI(scheme组件为部分已知的网络协议的URI子集) + 与scheme组件标识的网络协议匹配的协议处理器(URL Protocol Handler) + 持久性/地址无关性。
四、java.net.URI类和java.net.URL类
java当中对URI和URL单独提供java.net.URI和java.netURL两个操作类。
java.net.URI中主要提供以下功能:
1. 验证URI格式
构造函数URI(String str),若格式不正确则抛出URISyntaxException
URI.create(String str),若格式不正确则抛出unchecked的IllegalArgumentException
2. 提取URI各组件
getAuthority()
getFragment()
getHost()
getPath()
getPort()
getQuery()
getScheme()
getSchemeSpecificPart()
getUserInfo()
3. 标准化、解析化和相对化
normalize(),,返回符合标准的URI新对象。如`x/y/../z/./q`->`x/z/q`
resolve(String/URI uri),进行反向解析,以入参作为相对URI,以resolve方法所属对象作为基本URI来得到一个新的标准的URI对象
relativize(URI uri),相对化操作,就是获取URI中的相对URI 实例:
URI uriBase = new URI("http://www.somedomain.com");
URI uriRelative = new URI("x/../y");
URI uriResolve = uriBase.resolve(uriRelative); // http://www.somedomain.com/y
URI uriRelativized = uriBase.relativize(uriResolve); // y
4. 将URI转成URL
URI#toURL(),将URI转换为URL。
注意:不含任何搜索和读写资源的操作。
java.net.URL中主要提供以下功能:
URL类是依据URL Protocol Handler来处理URL字符串的,若没有相应的协议处理器则抛MalformedURLException。
内置提供http、https、ftp、file和jar协议的URL Protocol Handler。而其他协议的处理器则需开发者自行继承URLStreamHandler来实现了。处理流程如下:
1. 查看处理器缓存HashTable handlers,若存在缓存项则直接返回;
2. 若缓存中没有则查看是否有URLStreamHandlerFactory实例,若存在则调用其createURLStreamHandler(String protocol)。默认情况下URLStreamHandlerFactory实例为null;
3. 若2中返回null,则通过系统属性java.protocol.handler.pkgs获取以|分隔的包名列表,然后逐一检查是否存在继承了URLStreamHandler的<package>.<protocol>.Handler类,有则返回,无则继续遍历;
4. 若3中遍历失败,则检查是否存在继承了URLStreamHandler的<system default package>.<protocol>.Handler的内置类。
5. 上述均失败则抛出MalformedURLException。
类URL中除了提供获取各组件的方法外,还提供了读写资源的方法如 InputStream openStream() 。下面我们通过URL类来读取t.txt文本文件的内容。
class Main{
static void main(String[] args) throws IOException, MalformedURLException{
String path1 = "d:\\t.txt"
, path2 = "file:/d:/t.txt";
Main main = new Main();
main.readByFr(path1);
main.readByUrl(path2);
} // 通过FileInputStream的写法
void readByFr(String path) throws IOException{
FileReader fr = new FileReader(path);
try{
int buf;
while (- != buf){
buf = fr.read();
System.out.print((char)buf);
}
}finally{
fr.close();
}
} // 通过URL的写法
void readByURL(String path) throws MalformedURLException, IOException{
URL url = new URL(path);
InputStreamReader reader = new InputStreamReader(url.openStream());
try{
int buf;
while (- != buf){
buf = reader.read();
System.out.print((char)buf);
}
}
finally{
reader.close();
}
}
}
五、总结
上述内容若有纰漏请大家指正,谢谢!
尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/4280369.html ^_^肥仔John
六、参考
http://kb.cnblogs.com/page/90838/
https://msdn.microsoft.com/en-us/library/ms478653.aspx
http://www.cnblogs.com/wang726zq/archive/2012/12/11/UrlProtocol.html
http://stackoverflow.com/questions/16376429/ubuntu-custom-url-protocol-handler
http://www.ibm.com/developerworks/cn/xml/x-urlni.html
http://baike.baidu.com/link?url=agsiO-syltdQC_SlhSBThijAD3kSC4DVZcfnNPvO_KxGYOMCVqhiI58BDrn6tG06vohsH-evK1x7BqUj_wnR-a
JDK7 API
Java魔法堂:URI、URL(含URL Protocol Handler)和URN的更多相关文章
- Java魔法堂:类加载器入了个门
一.前言 <Java魔法堂:类加载机制入了个门>中提及整个类加载流程中只有加载阶段作为码农的我们可以入手干预,其余均由JVM处理.本文将记录加载阶段的核心组件——类加载器的相关信息,以便日 ...
- Java魔法堂:打包知识点之jar
一.前言 通过eclipse导出jar包十分方便快捷,但作为码农岂能满足GUI的便捷呢?所以一起来CLI吧! 二.JAR包 JAR包是基于ZIP文件格式,用于将多个.java文件和各种资源文件, ...
- 【转】Java魔法堂:String.format详解
Java魔法堂:String.format详解 目录 一.前言 二.重载方法 三.占位符 四.对字符.字符串进行格式化 五.对整数进行格式化 六. ...
- Java魔法堂:类加载机制入了个门
一.前言 当在CMD/SHELL中输入 $ java Main<CR><LF> 后,Main程序就开始运行了,但在运行之前总得先把Main.class及其所依赖的类加载到JVM ...
- Java魔法堂:内部类详解
一.前言 对于内部类平时编码时使用的场景不多,比较常用的地方应该就是绑定事件处理程序的时候了(从C#.JS转向Java阵营的孩子总不不习惯用匿名内部类来做事件订阅:().本文将结合Bytecode对四 ...
- Java魔法堂:深入正则表达式API
目录 一.前言 二.正则表达式的使用诉求 三.java.util.regex包 四.java.lang.String实例 五.最短路径实现诉求 六.Java支持的正则表达式功能语法 七.总结 八.参考 ...
- Java魔法堂:JUnit4使用详解
目录 1. 开 ...
- JAVA魔法堂:读取.properties配置文件
一.前言 Java工程中想log4j.数据库连接等配置信息一般都写在.properties文件中,那么如何读取这些配置信息呢?下面把相关方法记录下来供以后查阅. 二..properties文件 配置文 ...
- Java魔法堂:枚举类型详解
一.前言 Java的枚举类型相对C#来说具有更灵活可配置性,Java的枚举类型可以携带更多的信息. // C# enum MyColor{ RED = , BLUE = } Console.Write ...
随机推荐
- Android性能优化典范第一季
2015年伊始,Google发布了关于Android性能优化典范的专题,一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App.课程专题不仅仅介绍了Android系统中有关 ...
- JavaFX結合 JDBC, Servlet, Swing, Google Map及動態產生比例圖 (3):部署設定及應用 (转帖)
說明:這一篇主要是說明如何將程式部署到Application Server,以及程式如何運作,產生的檔案置於何處,以及如何以瀏覽器呈現(Applet),或是當成桌面應用程式,或是 桌面Applet,這 ...
- Java构建工具Ant小记(一)
Ant简介 Ant是基于java的构建工具.理论上来说它类似与make工具,但是却克服了make的一些固有的缺陷. 传统的Make是基于操作系统shell的构建工具,虽然也可以基于工作的os对make ...
- 深入理解openstack网络架构(3)-----路由
原文地址: https://blogs.oracle.com/ronen/entry/diving_into_openstack_network_architecture2 译文转自:http://b ...
- 让ZenCoding提升编码速度
日前写了一篇关于VS神级插件Web Essentials的系列博客,其中在HTML&CSS操作技巧一节简单提到了ZenCoding,今天来详细说一下这个东西. 摘要 Zen Coding是一种 ...
- 示例篇-购物车的简单示例和自定义JS
简介: 支持平台: Android4.0,iOS7.0,Windows 10, Windows 10 mobile 说明:主要是演示listview所在的ui和模板cell所在的ui之间数据的交互,点 ...
- hadoop 学习笔记:mapreduce框架详解
开始聊mapreduce,mapreduce是hadoop的计算框架,我学hadoop是从hive开始入手,再到hdfs,当我学习hdfs时候,就感觉到hdfs和mapreduce关系的紧密.这个可能 ...
- 整理BOM时写的关于拆分单元格的VB代码
Public Function AddRows(pos As Integer, amount As Integer) Dim rpos As Integer rpos = pos + To amoun ...
- CSS3动画:YouTube的红色激光进度条
本文只是讨论和实现了动画效果,并未将动画与页面实际下载关联,有朋友们问如何应用,可以使用现成的一些插件比如这个,这个,还有这个. 之前一篇文章<CSS3 动画一瞥>简单介绍了CSS3动画相 ...
- 翻译-使用Spring调用SOAP Web Service
原文链接: http://spring.io/guides/gs/consuming-web-service/ 调用SOAP web service 本指南将指导你使用Spring调用一个基于SOAP ...