4.4.1 URL和URI
URL和URLConnection类封装了大量复杂的实现细节,这些细节涉及如何从远程站点获取信息。例如,可以自一个字符串构建一个URL对象:
如果只是想获得该资源的内容,可以使用URL类中的openStream方法。该方法将产生一个InputStream对象,然后就可以按照一般的用法来使用这个对象了,比如用它构建一个Scanner对象:
java.net包对统一资源定位符(Uniform Resource Locator,URL)和统一资源标识符(Uniform Resource Identifier,URI)作了非常有用的区分。
URI是个纯粹的语法结构,包含用来指定Web资源的字符串的各种组成部分。URL是URI的一个特例,它包含了用于定位Web资源的足够信息。其他URI,比如
则不属于定位符,因为根据该标识符我们无法定位任何数据。像这样的URI我们称之为URN(uniform resource name,统一资源名称)。
在Java类库中,URI类并不包含任何用于访问资源的方法,它的唯一作用就是解析。但是,URL类可以打开一个到达资源的流。因此,URL类只能作用于那些Java类库知道该如何处理的模式,例如http:、https:、ftp:、本地文件系统(file:)和JAR文件(jar:)。
要想了解为什么对URI进行解析并非小事一桩,那么考虑一下URL会变得多么复杂。例如,
URI规范给出了标记这些标识符的规则。一个URI具有以下句法:
上式中,[...]表示可选部分,并且:和#可以被包含在标识符内。
包含scheme:部分的URI称为绝对URI。否则,称为相对URI。
如果绝对URI的schemeSpecificPart不是以/开头的,我们就称它是不透明的。例如:
所有绝对的透明URI和所有相对URI都是分层的(hierarchical)。例如:
一个分层URI的schemeSpecificPart具有以下结构:
在这里,[...]同样表示可选的部分。
对于那些基于服务器的URI,authority部分具有以下形式:
port必须是一个整数。
RFC 2396(标准化URI的文献)还支持一种基于注册表的机制,此时authority采用了一种不同的格式。不过,这种情况并不常见。
URI类的作用之一是解析标识符并将它分解成各种不同的组成部分。你可以用以下方法读取它们:
URI类的另一个作用是处理绝对标识符和相对标识符。如果存在一个如下的绝对URI:
和一个如下的相对URI:
那么可以用它们组合出一个绝对URI:
这个过程称为解析相对URL。
与此相反的过程称为相对化(relativization)。例如,假设有一个基本URI:
和另一个URI:
那么相对化之后的URI就是:
URI类同时支持以下两个操作: