· 如果query string也相同了,就比较fragment
URI除了和它们自身比较以外,不能和任何其他的类型做比较。把一个URI 和任何除了URI 以外的做比较会抛出异常ClassCastException
public String toString( )
方法toString( ) 返回一个URI 形式的未经编码的string。也就是说,像é 和 \这种字符就不会被转换成%xx,除非它们在用来生成URI 的string中已经被转换了。因此,调用这个方法后得到的结果不能保证它是一个语法正确的URI 。有时,这种形式有助于增强可读性,但是对检索来说就不一样了。
public String toASCIIString( )
方法toASCIIString( ) 返回一个编码后URI 形式的string。像é 和 \这样的字符总是是被转换成了%xx的,不管它们最初是否已经被转换。很多时间你就应该使用这种string形式 的URI。尽管toString( ) 返回的形式对于人来说更易于理解,但是它们仍然可能被复制粘贴到一些期望得到合法URI的地方。而方法toASCIIString( ) 返回语法正确的URI。
Proxies(代理服务)
许多系统都通过proxy 服务器访问网站和其他Internet上的不使用HTTP的地方。代理服务器接受从本地客户机发向远程服务器的请求,再把这个结果发送给本地客户机。这样做有时出于安全的原因,比如阻止远程服务器获取关于本地客户机网络配置的信息。有时通过过滤发出的请求和限制被访问的网站,阻止用户去访问那些被禁止访问的的网站。比如像一所小学就会阻止对http://www.playboy.com 的访问。当然有时这样做是单纯地出于对效率的考虑,当大量用户需要下载一台远程服务器上的相同文件时,就让他们从一个本地cache上下载,而不是不停地从远程服务器上下载。Java中基于URL 类的程序可以在大多数代理服务器和协议工作。的确,这就是你宁愿想选择使用URL 类而不愿意基于SOCKET自己编写HTTP包或者其他客户端程序的原因。
System Properties(系统属性)
对于基本操作而言,你需要做的就是设置一些系统属性指定你的本地代理服务器的地址。如果你使用的是一个单纯的HTTP代理,把http.proxyHost 设置为域名或者为你的代理服务器的IP地址,把http.proxyPort 设置为代理服务器的端口号(默认为80)。这里有许多种方法可以实现这个操作。包括在你的java代码中调用System.setProperty() 或者当启动程序时,使用命令选项“-D”。下面这个例子就把代理服务器设置为192.168.254.254,端口设置为9000:
% java -Dhttp.proxyHost=192.168.254.254 -Dhttp.proxyPort=9000
com.domain.Program
你如果不想让某个主机的访问通过代理服务,想直接进行连接,那么就把系统属性http.nonProxyHosts 设置为它的主机名或ip地址。如果你需要对多个主机都进行这种操作,就用“|”把它们分开。比如,这段代码片段表示它会代理所有的除去java.oreilly.com 和 xml.oreilly.com:
System.setProperty("http.proxyHost", "192.168.254.254");
System.setProperty("http.proxyPort", "9000");
System.setProperty("http.nonProxyHosts", "java.oreilly.com|xml.oreilly.com");
你也可以使用“*”作为一个通配符,表示对所有对所有有特殊域或子域的主机的访问不需要被代理。例如,对除了对oreilly.com 域的主机不代理外,对其他的都可以:
% java -Dhttp.proxyHost=192.168.254.254 -Dhttp.nonProxyHosts=*.oreilly.com
com.domain.Program
如果你使用的是个FTP代理服务器,可以用相同的方法设置系统属性,像ftp.proxyHost, ftp.proxyPort, 和 ftp.nonProxyHosts 。java不支持任何其他应用层的代理,除非如果你对所有的TCP连接都使用传输层的SOCKS代理,你可以使用相关的socksProxyHost 和 socksProxyPort 来设置系统属性。对于SOCKS,java没有提供对是否需要代理的选择。你要么选择都需要代理,要么选择都不需要代理。
The Proxy 类
Java1.5允许java程序对代理服务器进行更精细的操作。特别的是,你可以对不同的远程主机选择不同的代理服务器。代理本身是由java.net.Proxy 类的实例表示。这里仍然只有三种代理方式,HTTP, SOCKS, 和直接连接(也就是不需要代理),由Proxy.Type 型迭代器中的三个常量表示:
· Proxy.Type.DIRECT
· Proxy.Type.HTTP
· Proxy.Type.SOCKS
除了代理的类型外,其他关于代理重要信息包括它的地址和端口,由SocketAddress 的对象表示。例如,这个代码片段创建了一个代理对象,它表示proxy.example.com 端口80上的一个HTTP代理服务器:
SocketAddress address = new InetSocketAddress("proxy.example.com", 80);
Proxy proxy = new Proxy(Proxy.Type.HTTP, address);
尽管这里仅有三种代理对象,但是对于不同主机上的不同代理服务器,会有许多相同类型的代理。
The ProxySelector 类
每个java1.5的jvm都有一个java.net.ProxySelector 对象。它可以对不同的连接委派合适的代理服务器。默认的ProxySelector 仅仅是检测一下各种系统属性和URL协议,然后决定怎样连接不同的主机。尽管如此,但是你可以安装你自己的ProxySelector 子类来代替默认的选择器(selector),让它基于协议,主机,路径,日期,或其它标准来选择不同的代理。
这个类的关键就是抽象方法select( ) :
public abstract List<Proxy> select(URI uri)
java传一个表示需要被连接的主机的URI 对象给该方法。用类URL生成的这个连接对象通常是这种形式:http://www.example.com/ 或者 ftp://ftp.example.com/pub/files/, 或者其他类似的。对于由Socket类生成的单纯的TCP连接, URI会是这种形式:socket://host:port:,看一个实例,socket://www.example.com:80 。对象ProxySelector 对这种类型的对象会选择合适的代理,然后再以形式List<Proxy> 返回它们。这个类的第二个你必须实现的抽象方法是connectFailed( ):
public void connectFailed(URI uri, SocketAddress address, IOException ex)
这是个反馈方法,它警告程序代理服务器连接不成功。例子7-11表示一个ProxySelector 试图对所有的HTTP连接都使用在proxy.example.com 上的代理服务器,除非这个代理服务器在前面,对某个特殊的URL的连接已经失败了。在这种情况下,它会建议用一个直接连接代替。
Example 7-11. A ProxySelector that remembers what it can connect to