绝大部分知识与实例来自O’REILLY的《Java网络编程》(Java Network Programming,Fourth Edition,by Elliotte Rusty Harold(O’REILLY))。
URI与URL
URI全称为Uniform Resource Identifier,统一资源标识符,作用是标识某一互联网资源。
URL全称为Uniform Resource Locator,统一资源定位符,用于表示资源的地点。
URI与URL的联系是它们都能够唯一地确定一个资源,区别是URL是通过资源的地点来确定资源的。因此,可以说URL是URI的子集。
URI格式
URI没有非常具体的格式,一般由模式和模式特定部分组成,模式特定部分的语法取决于所用的格式,如下:
模式:模式特定部分[#片段标识符]
模式类型如下:
- data:Base64编码数据
- file:本地磁盘上的文件
- ftp:FTP服务器
- http:使用HTTP的国际互联网服务器
- mailto:电子邮件地址
- magnet:可通过对等网络(BT等)下载的资源
- telnet:与基于Telnet的服务的连接
- urn:统一资源名(Uniform Resource Name,URN)
除了这些标准模式,Java还支持rmi,jar,jndi,doc等非标准的定制模式,用于实现不同用途。
模式特定部分没有特定的语法,一般会采用一种层次结构形式,如下:
//authority/path?query
其中authority为授权机构,负责解析URI其余部分,path为路径,query为查询字符串。
URL格式
相比于URI,URL的格式具体的多。绝对URL格式如下:
协议方案名://[登录信息@]主机[:端口号]/带层次的文件路径[?查询字符串][#片段标识符]
protocol://[userInfo@]host[:port]/path[?query][#fragment]
下面为字段简介:
- 协议方案名(protocol):是URI中模式(scheme)的另一种叫法,可以是file,http,ftp,https等。
- 主机(host):指代提供资源的服务器。可以是主机名(www.oreilly.com)也可以是IP地址。
- 用户信息(userInfo):服务器的登录信息。
- 端口(port):可选,如果服务在默认端口进行(如HTTP使用端口80)就不需要。
- 路径(path):指向指定服务器上的一个特定目录。
- 查询(query):向服务器提供附加参数,一般只在HTTP URL中使用,其中包含表单数据,作为输入提供给在这个服务器上运行的程序。
- 片段(fragment):指向远程资源的一个特定部分。
URL还支持一种相对格式。若在XXX/doc/A.html中单击地址为B.html的超链接,浏览器会自动进入XXX/doc/B.html。若点击/help/C.html(注意开头有一个/,表示该相对URL相对于根目录),则会自动进入XXX/help/C.html。
编码与解码
为了解决跨平台的兼容问题,URI和URL规定只能使用ASCII的一个固定子集,其他的字符必须编码。直接可用的字符集如下:
- 大写字母A-Z;
- 小写字母a-z;
- 数字0-9;
- 标点符号字符- _ . ! ~ * ‘(以及,)。
除此之外,/ & ? @ # ; $ + = %这些也可以使用,不过有特定的用途(分隔符)。如果在这些用途之外使用,同样需要编码。
编码方式为:除了上面的字符集之外,所有其他字符都要用UTF-8编码成十六进制码,并在前面加上%表示转义。各个分隔符在用作分隔符时无需编码,而用在其他部分中时则需要编码。空格是一个例外,可以编码为加号+(加号本身会被编为%2B)。
补充关于分隔符部分:比如https://www.baidu.com,由于它是按http URI模式来组织的,因此里面的“/”和“:”为分隔符,因此都不用编码。而如果它们出现在其他部分(比如路径:/s/Java I/O)里面,就需要和其他特殊字符一样接受编码(类似于转义字符出现在字符串中的处理方式)。
URL类简介
java.net.URL类是Java对URL的抽象,是一个final类,不能被继承。实际上,URL类使用了策略设计模式,通过不同的协议处理器来扩展功能。
URL类是不可变的,对象构建完成后,字段就无法改变,因此能够保证线程安全。
URL类提供了多种构造器,用于在不同情况下创建对象。
从字符串构建URL对象
public URL(string url) throws MalformedURLException
根据一个字符串形式的绝对URL构建URl对象。如果构造成功,说明URL的协议得到了支持。失败则会抛出MalformedURLException异常。
实例1:检查虚拟机支持的协议类型
public static void testProtocol(String url){
try {
URL u = new URL(url);
System.out.println(u.getProtocol() + " is supported.");
} catch (MalformedURLException e) {
String protocol = url.substring(0,url.indexOf(":"));
System.out.println(protocol + " is supported.");
}
}
public static void main(String[] args) {
testProtocol("http://www.baidu.com");
}
由组成部分构建URL对象
public URL(String protocol, String host, String file)
throws Malf