第5章 URL和URI

第5章 URL和URI

URI统一资源标识符是采用一种特定语法标识一个资源的字符串。所标识的资源可能是服务器上的一个文件。

URI的语法有一个模式和一个模式特定部分组成,如下:

模式:模式特地部分

模式包括:data、file、ftp、http、mailto、magnet、telnet、urn等

URI中的模式特定部门并没有特定的语法。如:

//authority/path?query

URLs

URL是一个URI,除了标识一个资源,还会为资源提供一个特定的网络位置,客户端可以用它来获取这个资源的一个表示。

URI类只标识资源,URL类既能标识资源,又能获取资源。

URL的语法为:

protocol://userInfo@host:port/path?query#fragment

协议(protocol)

主机(host)

用户信息(userInfo):可选

端口(port)

用户信息、主机和端口合在一起构成权威机构。

路径(path)

query(查询)

fragment(片段):指向远程资源的某个特定部分。如果远程资源是HTML,那么这个片段标识符将指定该HTML文档中的一个锚。

相对URL

不完整的URL称为相对URL。完整指定的URL称为绝对URL。

URL类

Java.net.URL类是对统一资源定位符的抽象。

创建新的URL

public URL(Stringurl) throws MalformedURLException

从字符串构建URL

public URL(Stringprotocol, String hostname, String file) throws MalformedURLException

由组成部分构造URL

public URL(Stringprotocol, String host, int port, String file) throws MalformedURLException

构造相对URL

public URL(URLbase, String relative) throws MalformedURLException

其他URL对象来源

从URL获取数据

从URL获取数据方法

public InputStream openStream() throws IOException

openStream()方法连接到URL所用的资源,在客户端和服务端之间完成必要的握手,返回一个InputStream,可以由此读取数据。从这个InputStream获得的数据是URL引用的原始内容。

示例5-2:下载一个web页面SourceViewer

public URLConnection openConnection() throws IOException

openConnection()方法为指定的URL打开一个socket,并返回一个URLConnection对象。URLConnection表示一个网络资源的打开的连接。

try{
       URL u = new URL(“https://news.ycombinator.com/”);

       try{

              URLConnection uc =u.openConnection();

              InputStream in =uc.getInputStream();

              //从连接读取。。。

       }catch(IOException ex){

              System.err.println(ex);

       }

}catch(MalformedURLException ex){

       System.err.println(ex);

}

通过URLConnection,可以访问服务器发送的所有数据:除了原始的文档本身外,还可以访问这个协议指定的所有元数据。除了从URL读取,URLConnection还允许你向URL写入数据。

publicURLConnection openConnection(Proxy proxy) throws IOException

public ObjectgetContent() throws IOException

getContent()方法获取由URL引用的数据,尝试由它建立某种类型的对象。如果URL指示文本,返回InputStream;如果指示图像,返回java.awt.ImageProducer。

URL u  =  new URL("http://mesola.obspm.fr/");

Object o = u.getContent();

//将Object强制转化为适当的类型

//处理这个Object...

public ObjectgetContent(Class[] classes) throws IOException

URL的内容处理器可以提供一个资源的不同视图。getContent()方法的这个重载版本允许你选择希望将内容做一个哪个类返回。

分解URL

URL由5部分组成:

*模式

*授权机构(授权机构可以划分为用户信息、主机和端口)

*路径

*片段标识符,也称为段或ref

*查询字符串

getProtocol() 获得URL的模式

getHost()获得URL的主机名

getPort()获得URL中指定的端口号,如果没有指定端口,返回-1

getDefaultPort()获得URL的协议所使用的默认端口

getFile()获得URL的路径部分,从主机名后的第一个斜线(/)一直到开始片段标识符的#号之前的字符。

getPath(),和getFile()类似,但是不包括查询字符串

getRef()获得URL中片段标识符部分

getQuery()获得URL的查询字符串

getUserInfo()获得用户名,有时包含口令信息

getAuthority()获得授权机构,包含用户信息、主机和端口

相等性比较

equals()

hashCode()

sameFile()判断两个URL是否指向相同的资源,不考虑片段标识符

比较

toString()

toExternalForm()

toURI()

toURL()方法将URL对象转换为对应的URI对象。URI类提供了比URL类更精确、更符合规范的行为。对于像绝对化和编码等操作,在选择时应当首选URI类。如果需要把URL存储在一个散列表或其他数据结构中,也应当首选URI类,因为它的equals()方法不会阻塞。URL类应当主要用于从服务器下载内容。

URI类

URI类是对URL的抽象,不仅包括统一资源定位符,还包括统一资源名。

URL对象是对应网络获取的应用层协议的一个表示,而URI对象纯粹用于解析和处理字符串。URI类没有网络获取功能。

构造一个URI

与URL类不同,URI类不依赖与底层协议处理器。只要是URI语法上正确,Java就不需要为了创建URI对象而理解其协议。

public URI(String uri) throwsURISyntaxException

几乎所有字符串都可以解释为URI。

public URI(String scheme,StringschemeSpecificPart,String fragment) throws URISyntaxException 用于非层次URI

URI absolut = new URI(“http”,”//www.ibiblio.org”,null);绝对URI

URI relative = new URI(null,”/javafaq/index.shtml”,”today”);相对URI

模式特定部分取决于URI模式的语法。因为URI类会用百分号转义字符来对无效字符编码,实际上着部分不会有任何语法错误。

public URI(String scheme,String host,Stringpath,String fragment) throws URISyntaxException 用于层次URI

URI today = new URI(“http”,www.ibiblio.org,”/javafaq/index.html”,”today”);

public URI(String scheme,Stringauthority,String path,String query,String fragment) throws URISyntaxException

public URI(String scheme,StringuserInfo,String host,int port,String path,String query,String fragment) throwsURISyntaxException

URI的各部分

一般格式为:

模式:模式特定部分:片段

省略模式,这个URI引用则是相对的。

省略片段标识符,这个URI引用就是一个纯URI。

获取各部分方法:

x-www-form-urlencoded

URL中使用的字符必须来自ASCII的一个固定的子集。

编码方式非常简单。除了ASCII数字、字母和前面指定的标点符号以外,所有其他字符都要转换为字节,每个字节要写为百分号后面加两个十六进制数字。

URL类不自动编码或解码。

URLEncoder

URLEncoder.encode(),第二个参数指定字符集,一般使用“UTF-8”

需要逐部分地对URL进行编码,而不是在一个方法调用中对整个URL编码。

URLEncoder最常见的用法是准备查询字符串,从而与使用GET方法的服务器端程序通信。

URLDecode

URLDecode.decode();

由于这个方法对非转移字符不过处理,所有可以传入整个URL,而不需要首先将它分解为各个部分。

解析相对URI 

URI类提供了3个方法可以在相对和绝对URI之间来回转换。

代理

通过代理服务器访问Web,一是出于安全,二是可以限制访问一些网站。

系统属性

Proxy类

Proxy类允许从Java程序中对代理服务器进行更细粒度的控制。有三种代理:HTTP、SOCKS和直接连接,用三个常量表示:

*Proxy.Type.DIRECT

*Proxy.Type.HTTP

*Proxy.Type.SOCKS

除了类型之外,关于代理的其他重要信息包括它的地址和端口,用SocketAddress对象来表示。

创建一个Proxy对象,表示proxy.example.com的端口80上的一个HTTP代理服务器:

SocketAddressaddress = new InetSocketAddress(“proxy.example.com”,80);

Proxy proxy = newProxy(Proxy.Type.HTTP,address);

ProxySelector类

通过GET与服务器端程序通信

URL类使得应用程序和服务器端程序(如CGI、servlet、PHP页面和其他使用GET方法的程序)的通信非常容易。

使用POST方法的服务器端程序需要使用URLConnection类。

你只需要知道程序希望接收怎样的名-值组合,然后用查询字符串构造URL,这个查询字符串提供所需的名和值。所有名和值都必须经过编码。

例如:要搜索“java”,可以打开与URL http://www.dmoz.org/search?q=java的连接,读取得到的输入流。

示例5-10:完成一个Open Directory搜索

import java.io.*;
import java.net.*;

public class DMoz {

  public static void main(String[] args) {
  
    String target = "";
    for (int i = 0; i < args.length; i++) {
      target += args[i] + " ";
    }
    target = target.trim();

    QueryString query = new QueryString();
    query.add("q", target);
    try {
      URL u = new URL("http://www.dmoz.org/search/q?" + query);
      try (InputStream in = new BufferedInputStream(u.openStream())) {
        InputStreamReader theHTML = new InputStreamReader(in);
        int c;
        while ((c = theHTML.read()) != -1) {
          System.out.print((char) c);
        } 
      }
    } catch (MalformedURLException ex) {
      System.err.println(ex);
    } catch (IOException ex) {
      System.err.println(ex);
    }
  }
}

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class QueryString {

  private StringBuilder query = new StringBuilder();
  
  public QueryString() {
  }

  public synchronized void add(String name, String value) { 
    query.append('&');
    encode(name, value);
  }
  
  private synchronized void encode(String name, String value) {
    try { 
      query.append(URLEncoder.encode(name, "UTF-8"));
      query.append('='); 
      query.append(URLEncoder.encode(value, "UTF-8"));
    } catch (UnsupportedEncodingException ex) {
      throw new RuntimeException("Broken VM does not support UTF-8");
    }
  }
  
  public synchronized String getQuery() {
    return query.toString();
  }
  
  @Override
  public String toString() {
    return getQuery();
  }
}


访问口令保护的网站

Java的URL类可以访问使用HTTP认证的网站,不过,当然需要提供用户名和口令。

Authenticator类

java.net.Authenticator类为使用HTTP认证自我保护的网站提供用户名和口令

public abstract class Authenticator extends Object










你可能感兴趣的:(第5章 URL和URI)