为了辅助编码,Java提供了java.net.URLEncoder类,它声明了一对静态的encode()方法。每个方法有一个String参数并返回包含已编码的参数内容的String对象的引用。例如,如果encode()发现参数中有空格,它在结果中用加号代替空格。

  下面的代码片断演示了调用URLEncoder的encode(String s)方法,对a 空格 b字符串进行编码。结果a+b存储在一个新的String对象中,result引用它。

String result = URLEncoder.encode ("a b");

  作为准备窗体数据的补充,必须告诉URLConnection对象数据已经被发送了,因为URLConnection默认的操作是获取数据。为了完成这种事务,你可以首先把openConnection()的返回值转换为HttpURLConnection类型(在确保该返回值的类型正确后)。接着调用结果对象的setRequestMethod(String method)方法,把POST作为method参数引用的对象的值。

  另一个必须完成的事务是调用URLConnection的setDoOutput(boolean doOutput)方法,其参数的值必须为true。这种事务是必要的,因为URLConnection对象在默认情况下不支持输出。(接着程序最终可以调用URLConnection的getOutputStream()方法,为发送的窗体数据返回一个资源的输出流的引用)。

  列表6是URLDemo3的源代码,它演示了把窗体数据发送给某个"了解"application/x-www-form-urlencoded内容类型的资源。它实现了前面提到的各种事务。

  列表6: URLDemo3.java

// URLDemo3.java

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

class URLDemo3
{
public static void main (String [] args) throws IOException
{
// 检查最后两个参数和参数的数量

if (args.length < 2 || args.length % 2 != 0)
{
System.err.println ("usage: java URLDemo3 name value " +
"[name value ...]");
return;
}

// 建立程序连接服务器程序资源的URL对象,它返回一个窗体的名称/值对

URL url;
url = new URL
("http://banshee.cs.uow.edu.au:2000/~nabg/echo.cgi");

// 向某个特定协议对象返回表现http资源连接的引用

URLConnection uc = url.openConnection ();

// 验证连接的类型,必须是HttpURLConnection的

if (!(uc instanceof HttpURLConnection))
{
System.err.println ("Wrong connection type");
return;
}

// 表明程序必须把名称/值对输出到服务器程序资源

uc.setDoOutput (true);

// 表明只能返回有用的信息

uc.setUseCaches (false);

//设置Content-Type头部指示指定URL已编码数据的窗体MIME类型

uc.setRequestProperty ("Content-Type",
"application/x-www-form-urlencoded");

// 建立名称/值对内容发送给服务器

String content = buildContent (args);

//设置Content-Type头部指示指定URL已编码数据的窗体MIME类型

uc.setRequestProperty ("Content-Length",
"" + content.length ());

// 提取连接的适当的类型

HttpURLConnection hc = (HttpURLConnection) uc;

// 把HTTP请求方法设置为POST(默认的是GET)

hc.setRequestMethod ("POST");

// 输出内容

OutputStream os = uc.getOutputStream ();
DataOutputStream dos = new DataOutputStream (os);
dos.writeBytes (content);
dos.flush ();
dos.close ();

// 从服务器程序资源输入和显示内容

InputStream is = uc.getInputStream ();

int ch;
while ((ch = is.read ()) != -1)
System.out.print ((char) ch);

is.close ();
}

static String buildContent (String [] args)
{
StringBuffer sb = new StringBuffer ();

for (int i = 0; i < args.length; i++)
{
// 为正确的传输对参数编码

String encodedItem = URLEncoder.encode (args [i]);

sb.append (encodedItem);

if (i % 2 == 0)
sb.append ("="); // 分离名称和值
else
sb.append ("&"); // 分离名称/值对
}

// 删除最后的 & 间隔符

sb.setLength (sb.length () - 1);

return sb.toString ();
}
}

  你可以会奇怪为什么URLDemo3没有调用URLConnection的connect()的方法。这个方法没有被明显的调用,因为如果连向资源的连接没有建立的话,其它的URLConnection方法(例如getContentLength())会明确的调用connect()方法。但是一旦连建立了接,调用这些方法(例如setDoOutput(boolean doOutput))就是违反规定的。在connect()被(明确地或隐含地)调用后,这些方法会产生一个IllegalStateException对象。
在URLDemo3编译后,在命令行输入java URLDemo3 name1 value1 name2 value2 name3 value3,你可以看到下面的输出:

<html> <head>
<title>Echoing your name value pairs</title>
</head>
<body>
<ol>
<li>name1 : value1
<li>name2 : value2
<li>name3 : value3
</ol>
<hr>
Mon Feb 18 08:58:45 2002
</body>
</html>

  该服务器程序资源的输出由HTML组成,这些HTML回应的是name1、value1、name2、 value2、name3和value3。

  技巧

  如果你需要URL对象的URL的字符串表现形式,请调用toExternalForm()或toString()。两种方法的功能是相同的。

  总结

  本文研究了Java的网络API,聚焦于URI、URL和URN。你学习了这些概念,以及怎样使用URI和URL(URL相关)的类工作,同时你学习了MIME的知识以及它与URL的关系。现在你应该编写一些代码熟悉一下所学的内容了。
posted on 2004-10-22 10:09  Johnny  阅读(615)  评论(0)    收藏  举报