《Java网络编程》内容摘抄和整理
我们知道URL是用于定位资源的一串有特定的规则的字符串。这个有规则的字符串内部包含的内容有很多,比如访问资源所有的协议、资源所在的主机地址、处理访问的端口等等。当然我们拿到这样的表示URL的字符串,可以通过自己解析的方式来获取我们需要的信息,不过java本着一切都是对象的原则,已经为我们定义了这样一个代表URL的类,从而方便我们操作。这个类就是java.net.URL类。
类简介
java.net.URL类是对统一资源定位符的抽象。它扩展了java.lang.Object,是一个final类,不能对其派生子类。它不依赖于继承来配置不同类型URL的实例,而使用了策略(strategy)设计模式。协议处理器就是策略,URL类构成了上下文,通过它来选择不同的策略。
URL是不可变的。构造一个URL对象后,其字段不在改变。这有一个副作用:可以保证它们是"线程安全"的。
类属性
URL是通过指定资源位置从而定位资源的一种方式,它是URI的一个子集。URI一般化的语法由以下五个有次序和层级的组件组成:
URI = scheme:[//authority]path[?query][#fragment]
其中,authority部分分为三个子组成部分:
authority = [userinfo@]host[:port]
组成各部分图示如下:
java.net.URL类是对URL字符串的抽象,类中定义的属性即表示URL字符串的各个组成部分。
类属性如下:
类属性 | 说明 | 详述 |
---|---|---|
authority | 授权机构 | URL字符串中的authority |
file | 文件部分 | URL字符串中的path[?query] |
host | 主机名 | URL字符串中host |
port | 端口 | URL字符串中port |
protocol | 协议 | URL字符串中的scheme |
query | 查询字符串 | URL字符串中的query |
ref | 片段标识符 | URL字符串中的fragment |
path | 路径 | URL字符串中的path |
userInfo | 用户信息 | URL字符串中authority部分的userinfo内容 |
file: Java不会把URL分解为单独的路径和文件部分。从主机名后的第一个斜线(/)一直到开始片段标识符的#号之前的字符,都被认为是文件部分。
构造方法
java.net.URL类提供了如下的构造方法:
public URL(String spec) throws MalformedURLException;
public URL(String protocol, String host, int port, String file) throws MalformedURLException;
public URL(String protocol, String host, int port, String file, URLStreamHandler handler) throws MalformedURLException;
public URL(String protocol, String host, String file) throws MalformedURLException;
public URL(URL context, String spec) throws MalformedURLException;
public URL(URL context, String spec, URLStreamHandler handler) throws MalformedURLException;
不同的构造函数所需的信息有所不同,使用哪个构造函数取决于你有哪些信息以及信息的形式。如果试图为一个不支持的协议创建URL对象,或者如果URL的语法不正确,所有这些构造函数都会抛出一个MalformedURLException异常。
支持哪些协议取决于具体实现。所有虚拟机都支持的协议只有http和file,而且后者名声很不好。如今Java还支持https、jar和ftp。一些虚拟机还支持mailto和gopher,以及一些定制协议如doc、netdoc、systemresource和Java在内部使用的verbatim。
示例1:从字符串构造URL
@Test
public void test1() {
try {
URL url = new URL("http://www.baidu.com");
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
示例2:由组成部分构造URL
@Test
public void test2() {
try {
URL url = new URL("http", "www.eff.org", "/blueribbon.html#intro");
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
@Test
public void test3() {
try {
URL url = new URL("http", "fourier.dur.ac.uk", 8000, "/~dma3mjh/jsci/");
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
示例3:构造相对URL
@Test
public void test4() {
try {
URL u1 = new URL("http://www.ibiblio.org/javafaq/index.html");
URL u2 = new URL(u1, "mailinglists.html");
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
从URL获取数据
URL类有几个方法可以从URL获取数据:
public final InputStream openStream() throws java.io.IOException;
public URLConnection openConnection() throws java.io.IOException;
public URLConnection openConnection(Proxy proxy) throws java.io.IOException;
public final Object getContent() throws IOException;
public final Object getContent(Class[] classes) throws java.io.IOException;
openStream()
openStream()方法连接到URL所引用的资源,在客户端和服务器之间完成必要的握手,返回一个InputStream,可以由此读取数据。从这个InputStream获得的数据是URL引用的原始内容(即未经解释的内容):如果读取ASCII文本则为ASCII;如果读取HTML文件则为原始HTML,如果读取图像文件则为二进制图片数据等。它不包括任何HTTP首部或者与协议有关的任何其他信息。可以像读取其他InputStream一样读取这个InputStream。
示例:
@Test
public void test5() {
try {
URL url = new URL("http://www.lolcats.com");
try (InputStream in = url.openStream()) {
int c;
while ((c = in.read()) != -1)
System.out.write(c);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
openConnection()
openConnection()方法为指定的URL打开一个socket,并返回一个URLConnection对象。URLConnection表示一个网络资源的打开的连接。如果调用失败,则openConnection()会抛出一个IOException异常。
示例:
@Test
public void test6() {
try {
URL u = new URL("https://news.ycombinator.com");
try {
URLConnection uc = u.openConnection();
InputStream in = uc.getInputStream();
// 从连接读取
} catch (IOException ex) {
ex.printStackTrace();
}
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
如果希望与服务器直接通信,应当使用这个方法。通过URLConnection,你可以访问服务器发送的所有数据:除了原始的文档本身外(如HTML、纯文本、二进制图像数据),还可以访问这个协议指定的所有元数据。例如,如果模式是HTTP或HTTPS,URLConnection允许你访问HTTP首部以及原始HTML。