文档

Java™ 教程-Java Tutorials 中文版
读取和写入 URLConnection
Trail: Custom Networking
Lesson: Working with URLs

读取和写入 URLConnection

URLConnection 类包含许多方法,可让你通过网络与 URL 进行通信。URLConnection 是一个以 HTTP 为中心的类;也就是说,只有在使用 HTTP URL 时,它的许多方法才有用。但是,大多数 URL 协议允许你读取和写入连接。本节介绍这两种功能。

从 URLConnection 读取

以下程序执行与 Reading Directly from a URL 中读取的 URLReader 程序相同的功能。

但是,该程序不是直接从 URL 获取输入流,而是显式获取 URLConnection 对象并从连接获取输入流。通过调用 getInputStream 隐式打开连接。然后,像 URLReader 一样,该程序在输入流上创建 BufferedReader 并从中读取。粗体语句高亮了此示例与上一个示例之间的差异:

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

public class URLConnectionReader {
    public static void main(String[] args) throws Exception {
        URL oracle = new URL("http://www.oracle.com/");
        URLConnection yc = oracle.openConnection();
        BufferedReader in = new BufferedReader(new InputStreamReader(
                                    yc.getInputStream()));
        String inputLine;
        while ((inputLine = in.readLine()) != null) 
            System.out.println(inputLine);
        in.close();
    }
}

此程序的输出与直接从 URL 打开流的程序的输出相同。你可以使用任一方式从 URL 读取。但是,从 URLConnection 读取而不是直接从 URL 读取可能更有用。这是因为你可以同时将 URLConnection 对象用于其他任务(例如写入 URL)。

同样,如果程序挂起或你看到错误消息,则可能必须设置代理主机以便程序可以找到 Oracle 服务器。

写入 URLConnection

许多 HTML 页面包含 forms (表单) - 文本框和其他 GUI 对象,可让你输入要发送到服务器的数据。键入所需信息并通过单击按钮启动查询后,Web 浏览器会通过网络将数据写入 URL。在另一端,服务器接收数据,处理数据,然后通常以新的 HTML 页面的形式向你发送响应。

许多这些 HTML 表单使用 HTTP POST METHOD 将数据发送到服务器。因此,写入 URL 通常称为 posting to a URL (发送到 URL )。服务器识别 POST 请求并读取从客户端发送的数据。

对于 Java 程序与服务器端进程交互,它必须能够写入 URL,从而向服务器提供数据。它可以通过以下步骤:

  1. 创建 URL
  2. 获取 URLConnection 对象。
  3. URLConnection 上设置输出功能。
  4. 打开与资源的连接。
  5. 从连接获取输出流。
  6. 写入输出流。
  7. 关闭输出流。

这是一个小 servlet 名为 ReverseServlet(或者如果你更喜欢 cgi-bin 脚本)。你可以使用此 servlet 来测试以下示例程序。

在容器中运行的 servlet 从其 inputstream 中读取、反转字符串并将其写入其 outputstream。servlet 需要输入格式 string=string_to_reverse,其中 string_to_reverse 是要以相反顺序显示其字符的字符串。

这是一个通过 URLConnection 在网络上运行 ReverseServlet 的示例程序:

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

public class Reverse {
    public static void main(String[] args) throws Exception {

        if (args.length != 2) {
            System.err.println("Usage:  java Reverse "
                + "http://<location of your servlet/script>"
                + " string_to_reverse");
            System.exit(1);
        }

        String stringToReverse = URLEncoder.encode(args[1], "UTF-8");

        URL url = new URL(args[0]);
        URLConnection connection = url.openConnection();
        connection.setDoOutput(true);

        OutputStreamWriter out = new OutputStreamWriter(
                                         connection.getOutputStream());
        out.write("string=" + stringToReverse);
        out.close();

        BufferedReader in = new BufferedReader(
                                    new InputStreamReader(
                                    connection.getInputStream()));
        String decodedString;
        while ((decodedString = in.readLine()) != null) {
            System.out.println(decodedString);
        }
        in.close();
    }
}

让我们检查一下程序,看看它是如何工作的。首先,程序处理其命令行参数:

if (args.length != 2) {
    System.err.println("Usage:  java Reverse "
        + "http://<location of your servlet/script>"
        + " string_to_reverse");
    System.exit(1);
}       

String stringToReverse = URLEncoder.encode(args[1], "UTF-8");

这些语句确保用户为程序提供两个且仅两个命令行参数。命令行参数是 ReverseServlet 的位置以及将被反转的字符串。它可能包含空格或其他非字母数字字符。必须对这些字符进行编码,因为字符串在到服务器的途中被处理。URLEncoder 类方法对字符进行编码。

接下来,程序创建 URL 对象,并设置连接以便它可以写入:

URL url = new URL(args[0]);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);

然后程序在连接上创建输出流并在其上打开 OutputStreamWriter

OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());

如果 URL 不支持输出,getOutputStream 方法将抛出 UnknownServiceException。如果 URL 支持输出,则此方法返回连接到服务器端 URL 的输入流的输出流 - 客户端的输出是服务器的输入。

接下来,程序将所需信息写入输出流并关闭流:

out.write("string=" + stringToReverse);
out.close();

此代码使用 write 方法写入输出流。因此,你可以看到将数据写入 URL 就像将数据写入流一样简单。写入客户端输出流的数据是服务器端 servlet 的输入。Reverse 程序通过将 string= 添加到要反转的编码字符串中,以脚本所需的格式构造输入。

servlet 读取你编写的信息,对字符串值执行反向操作,然后将其发送给你。你现在需要读取服务器已发回的字符串。Reverse 程序是这样的:

BufferedReader in = new BufferedReader(
                            new InputStreamReader(
                            connection.getInputStream()));
String decodedString;
while ((decodedString = in.readLine()) != null) {
    System.out.println(decodedString);
}
in.close();

如果你的 ReverseServlet 位于 http://example.com/servlet/ReverseServlet,那么当你使用 Reverse 程序运行时

http://example.com/servlet/ReverseServlet "Reverse Me"

作为参数(包括双引号),你应该看到这个输出:

Reverse Me
 reversed is: 
eM esreveR

Previous page: Connecting to a URL
Next page: All About Sockets