public final class URI
表示一个统一资源标识符 (URI) 引用。
除了以下提到的一些细微不同之处外,此类的实例代表一个 URI 引用,这在以下文档中定义:RFC 2396: Uniform Resource Identifiers (URI):Generic Syntax ;在此文件中对其内容又进行了修正:RFC 2732:Format for Literal IPv6 Addresses in URLs 。字面值 IPv6 地址格式还支持 scope_ids。scope_ids 的语法和用法在此处 描述。此类提供了 用于从其组成部分或通过解析其字符串形式创建 URI 实例的构造方法、用于访问实例的各个不同组成部分的方法,以及用于对 URI 实例进行规范化、解析和相对化的方法。此类的实例不可变。
在最高级别上,字符串形式的 URI 引用(以下简写为 "URI")语法如下
[ scheme : ] scheme-specific-part [ # fragment ]
其中,方括号 [...] 用于描述可选组成部分,字符 : 和 # 代表它们自身。
绝对 URI 指定了方案 (scheme);非绝对的 URI 称为相对 URI。URI 还可以根据其是否为不透明的 或分层的 进行分类。
不透明 URI 为绝对 URI,其特定于方案的部分不是以斜线字符 ('/' ) 开始。不透明 URI 无法进行进一步解析。下面是不透明 URI 的一些示例:
mailto:[email protected]
news:comp.lang.java
urn:isbn:096139210x
分层 URI 或者为绝对 URI(其特定于方案的部分以斜线字符开始),或者为相对 URI,即不指定方案的 URI。下面是分层 URI 的一些示例:
http://java.sun.com/j2se/1.3/
docs/guide/collections/designfaq.html#28
../../../demo/jfc/SwingSet2/src/SwingSet2.java
file:///~/calendar
分层 URI 还要按照下面的语法进行进一步的解析
[ scheme : ][ // authority ][ path ][ ? query ][ # fragment ]
其中,: 、/ 、? 和 # 代表它们自身。分层 URI 的特定于方案的部分包含方案和片段部分之间的字符。
分层 URI 的授权组成部分(如果指定)为基于服务器的 或基于注册表的 。基于服务器的授权按照如下众所周知的语法进行解析:
[ user-info @ ] host [ : port ]
其中,字符 @ 和 : 代表它们自身。几乎当前使用的所有 URI 方案都是基于服务器的。不能采用这种方式解析的授权组成部分被视为基于注册表的。
如果分层 URI 的路径组成部分以斜线字符 ('/') 开始,则称此 URI 本身为绝对的;否则它为相对的。 分层 URI 或者为绝对的,或者指定了授权的路径,它始终为绝对的。
如上所述,URI 实例具有以下九个组成部分:
组成部分 类型 方案 String 特定于方案的部分 String 授权 String 用户信息 String 主机 String 端口 int 路径 String 查询 String 片段 String
在给定实例中,任何特殊组成部分都或者为未定义的 ,或者为已定义的 ,并且有不同的值。未定义的字符串组成部分由 null 表示,未定义的整数组成部分由 -1 表示。已定义的字符串组成部分的值可以为空字符串;这与未定义的组成部分不等效。
实例中特定的组成部分是已定义的还是未定义的取决于所代表的 URI 类型。绝对 URI 具有方案组成部分。不透明的 URI 具有一个方案、一个特定于方案的部分,以及可能会有一个片段,但是没有其他组成部分。分层 URI 总是有一个路径(尽管可能为空)和一个特定于方案的部分(它至少包含一个路径),还可以包含任何其他组成部分。如果有授权组成部分且它又是基于服务器的,则主机组成部分将被定义,也有可能定义用户信息和端口组成部分。
此类支持的主要运算有规范化 、解析 和相对化
运算。
规范化 是将分层 URI 的路径组成部分中的不必要的 "." 和 ".." 部分移除的过程。每个 "." 部分都将被移除。".." 部分也被移除,除非它前面有一个非 ".." 部分。规范化对不透明 URI 不产生任何效果。
解析 是根据另一个基本 URI 解析某个 URI 的过程。得到的 URI 由两个 URI 组成部分构造,构造方式由 RFC 2396 指定,从基本 URI 取出原始 URI 中未指定的组成部分。对于分层 URI,原始的路径根据基本路径进行解析,然后进行规范化。例如,解析以下 URI
docs/guide/collections/designfaq.html#28 (1)
根据基本 URI http://java.sun.com/j2se/1.3/ 解析,结果为 URI
http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html#28 (3)
解析相对 URI
../../../demo/jfc/SwingSet2/src/SwingSet2.java (2)
根据此结果应生成
http://java.sun.com/j2se/1.3/demo/jfc/SwingSet2/src/SwingSet2.java 此结果的基本URI是(3)
支持对绝对和相对 URI,以及分层 URI 的绝对和相对路径的解析。根据任何其他 URI 对 URI file:///~calendar 进行解析只能生成原始的 URI,因为它是绝对路径。根据相对基础 URI (1) 解析相对 URI (2) 将生成规范的但依然是相对的 URI
demo/jfc/SwingSet2/src/SwingSet2.java
最后,相对化 是解析的逆过程:对于任何两个规范的 URI u 和 v ,
u .relativize( u .resolve( v )).equals( v ) 和
u .resolve( u .relativize( v )).equals( v ) 。
此运算在下面的场合非常有用:构造一个包含 URI 的文档,该 URI 必须尽可能是根据文档的基本 URI 建立的相对 URI。例如,相对化 URI
http://java.sun.com/j2se/1.3/docs/guide/index.html
根据基本 URI
http://java.sun.com/j2se/1.3
生成了相对 URI docs/guide/index.html
。
RFC 2396 精确指出 URI 引用中的各个不同组成部分允许使用的字符。以下分类大部分取自该规范,这些约束的用法描述如下:
alpha US-ASCII 字母字符,'A' 到 'Z' 以及 'a' 到 'z' digit US-ASCII 十进制数字符,'0' 到 '9' alphanum 所有 alpha 和 digit 字符 unreserved 所有 alphanum 字符及字符串 "_-!.~'()*" 中包含的字符 punct 字符串 ",;:$&+=" 中包含的字符 reserved 所有 punct 字符及字符串 "?/[]@" 中包含的字符 escaped 转义八位组,即三部分组合:百分号 ('%' ) 后跟两个十六进制数('0' -'9' 、'A' -'F' 和 'a' -'f' ) other 未包含在 US-ASCII 字符集中的 Unicode 字符不是控制字符(根据 Character.isISOControl
方法),并且不是空格字符(根据Character.isSpaceChar
方法)(与 RFC 2396 有些出入 ,RFC 2396 限制为 US-ASCII)
全部合法 URI 字符集包含 unreserved 、reserved 、escaped 和 other 字符。
RFC 2396 允许用户信息、路径、查询和片段组成部分中包含转义八位组。转义在 URI 中实现两个目的:
当要求 URI 不能包含任何 other 字符以严格遵守 RFC 2396 时,需要对非 US-ASCII 字符进行编码 。
要引用 组成部分中的非法字符。用户信息、路径、查询和片段组成部分在判断哪些字符合法哪些字符非法上稍有不同。
在此类中由三个相关的运算实现了这两个目的:
字符的编码 方式是,用代表该字符在 UTF-8 字符集中的字符的转义八位组序列取代该字符。例如,欧元符号 ('/u20AC' ) 编码后为 "%E2%82%AC" 。(与 RFC 2396 有些出入 ,RFC 2396 未指定任何特殊字符集) 。
非法字符通过简单地对它进行编码来引用 。例如,空格字符,用 "%20" 取代它来进行引用。UTF-8 包含 US-ASCII,因此对于 US-ASCII 字符,此转换具有的效果与 RFC 2396 的要求相同。
对转义八位组序列进行解码 的方法是,用它所代表的 UTF-8 字符集中的字符的序列将它取代。UTF-8 包含 US-ASCII,因此解码具有对引用的任何 US-ASCII 字符取消引用的效果,以及对任何编码的非 US-ASCII 字符进行解码的效果。如果在对转义八位组进行解码时出现解码错误 ,则出错的八位组用 Unicode 替换字符 '/uFFFD' 取代。
这些运算在此类的构造方法和方法中公开,如下所示:
要求对参数中的任何非法字符都必须引用,并保留出现的任何转义八位组和 other 字符。 单参数构造方法
根据其中出现的组成部分的需要对非法字符进行引用。百分号字符 ('%' ) 始终通过这些构造方法引用。任何 other 字符都将被保留。 多参数构造方法
getRawUserInfo
、getRawPath
、getRawQuery
、getRawFragment
、getRawAuthority
和 getRawSchemeSpecificPart
方法以原始形式返回它们的相应组成部分的值,不解释任何转义八位组。由这些方法返回的字符串有可能包含转义八位组和 other 字符,但不包含任何非法字符。
getUserInfo
、getPath
、getQuery
、getFragment
、getAuthority
和 getSchemeSpecificPart
方法解码相应的组成部分中的任何转义八位组。由这些方法返回的字符串有可能包含 other 字符和非法字符,但不包含任何转义八位组。
toString
返回带所有必要引用的 URI 字符串,但它可能包含 other 字符。
toASCIIString
方法返回不包含任何 other 字符的、完全引用的和经过编码的 URI 字符串。
对于任何 URI u ,下面的标识有效
new URI( u .toString()).equals( u ) .
对于不包含冗余语法的任何 URI u ,比如在一个空授权前面有两根斜线(如 file:///tmp/ )和主机名后面跟一个冒号但没有端口(如 http://java.sun.com: ),以及除必须引用的字符之外不对字符编码的情况,下面的标识也有效:
new URI( u .getScheme()、
u .getSchemeSpecificPart()、
u .getFragment())
.equals( u )
在所有情况下,以下标识有效
new URI( u .getScheme()、
u .getUserInfo()、 u .getAuthority()、
u .getPath()、 u .getQuery()、
u .getFragment())
.equals( u )
如果 u 为分层的,则以下标识有效
new URI( u .getScheme()、
u .getUserInfo()、 u .getHost()、 u .getPort()、
u .getPath()、 u .getQuery()、
u .getFragment())
.equals( u )
如果 u 为分层的并且没有授权或没有基于服务器的授权。
URI 是统一资源标识符 ,而 URL 是统一资源定位符 。因此,笼统地说,每个 URL 都是 URI,但不一定每个 URI 都是 URL。这是因为 URI 还包括一个子类,即统一资源名称 (URN),它命名资源但不指定如何定位资源。上面的 mailto 、news 和 isbn URI 都是 URN 的示例。
URI 和 URL 概念上的不同反映在此类和 URL
类的不同中。
此类的实例代表由 RFC 2396 定义的语法意义上的一个 URI 引用。URI 可以是绝对的,也可以是相对的。对 URI 字符串按照一般语法进行解析,不考虑它所指定的方案(如果有)不对主机(如果有)执行查找,也不构造依赖于方案的流处理程序。相等性、哈希计算以及比较都严格地根据实例的字符内容进行定义。换句话说,一个 URI 实例和一个支持语法意义上的、依赖于方案的比较、规范化、解析和相对化计算的结构化字符串差不多。
作为对照,URL
类的实例代表了 URL 的语法组成部分以及访问它描述的资源所需的信息。URL 必须是绝对的,即它必须始终指定一个方案。URL 字符串按照其方案进行解析。通常会为 URL 建立一个流处理程序,实际上无法为未提供处理程序的方案创建一个 URL 实例。相等性和哈希计算依赖于方案和主机的 Internet 地址(如果有);没有定义比较。换句话说,URL 是一个结构化字符串,它支持解析的语法运算以及查找主机和打开到指定资源的连接之类的网络 I/O 操作。
public final class URL
类 URL
代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。
URL 类自身并不根据 RFC2396 中定义的转义机制编码或解码任何 URL 部分。由调用方对任何需要在调用 URL 前进行转义的字段进行编码,并对从 URL 返回的任何经过转义的字段进行解码。进一步而言,由于 URL 不懂 URL 转义,所以它不会识别同一 URL 的对等编码和解码形式。例如,对于这两个 URL:
http://foo.com/hello world/ 和 http://foo.com/hello%20world
将被视为互不相等。
注意,URI
类在某些特定情况下对其组成字段执行转义。建议使用 URI
管理 URL 的编码和解码,并使用 toURI()
和 URI.toURL()
实现这两个类之间的转换。
也可以使用 URLEncoder
和 URLDecoder
类,但是只适用于 HTML 形式的编码,它与 RFC2396 中定义的编码机制不同。
URLConnection |
openConnection () 返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。 |
URLConnection |
openConnection (Proxy proxy) 与 openConnection() 类似,所不同是连接通过指定的代理建立;不支持代理方式的协议处理程序将忽略该代理参数并建立正常的连接。 |
InputStream |
openStream () 打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream 。 |