问题:
你需要在一个URL中传送查询参数。
解答:
使用一个HttpMethod实例的setQueryString()方法来设置查询字符串。使用URIUtil类对包含在URL中的文本进行编码。下面的例子在查询字符串中放入了两个参数:
1 import org.apache.commons.httpclient.HttpClient;
2 import org.apache.commons.httpclient.HttpException;
3 import org.apache.commons.httpclient.HttpMethod;
4 import org.apache.commons.httpclient.NameValuePair;
5 import org.apache.commons.httpclient.methods.GetMethod;
6 import org.apache.commons.httpclient.util.URIUtil;
7
8 HttpClient client = new HttpClient( );
9
10 String url = "http://www.discursive.com/cgi-bin/jccook/param_list.cgi";
11
12 HttpMethod method = new GetMethod( url );
13
14 // 用setQueryString()来设置查询字符串
15 method.setQueryString(URIUtil.encodeQuery("test1=O Reilly&blah=Whoop"));
16 System.out.println( "With Query String: " + method.getURI( ) );
17
18 client.executeMethod( method );
19
20 System.out.println( "Response:\n " + method.getResponseBodyAsString( ) );
21 method.releaseConnection( );
param_list.cgi CGI脚本只是简单的回显接收到的所以参数,在下面的输出中,你可以看到URIUtil如何对第一个参数进行编码:
With Query String: http://www.discursive.com/cgi-bin/jccook/param_list.cgi?test1=O%20Reilly&blah=Whoop
Response:
These are the parameters I received:
test1:
O Reilly
blah:
Whoop
提示:你不必在setQueryString()方法中加入?号,当HttpClient实例执行executeMethod()方法时,它会被自动加入。
讨论:
在前面的例子中,HttpMethod的setQueryString()方法是一次性将整个查询字符串加进去,但是还有另外一种选择:通过一个NameValuePair对象的数组来设置查询字符串。当一个NameValuePair[]传入setQueryString()方法中时,HttpMethod实例会从数组中取出每一个NameValuePair对象,然后创建一系列用&号分割的参数。这种方法使程序代码更加干净,因为你不必连接字符串来传递多个参数。下面的例子用NameValuePair对象,与前一个例子设置了同样的参数:
1 // 用NameValuePair对象设置查询参数
2 HttpMethod method = new GetMethod( url );
3 NameValuePair pair = new NameValuePair( "test1", URIUtil.encodeQuery( "O Reilly" ) );
4NameValuePair pair2 = new NameValuePair( "blah", URIUtil.encodeQuery( "Whoop" ) );
5NameValuePair[] pairs = new NameValuePair[] { pair, pair2 };
6method.setQueryString( pairs );
7System.out.println( "With NameValuePairs: " + method.getURI( ) );
8client.executeMethod( method );
9 System.out.println( "Response:\n " + method.getResponseBodyAsString( ) );
10method.releaseConnection( );
根据RFC1738,URL只能够包含字母和数字字符:[0-9,a-z,A-Z]和一些特殊字符。如果你需要在参数中传送一些URL所不允许的字符,你就需要对你的字符串进行编码,以符合RFC1738的规定。URIUtil类有一个方法encodeQuery()能够对前面例子中的"O Reilly"进行编码。下面的代码展示了用URIUtil类来对包含在URL中的字符串进行编码:
1 String encoded1 = URIUtil.encodeQuery( "<test>=O'Connell" );
2 String encoded2 = URIUtil.encodeQuery( "one:two=thr ee#" );
3
4 String decoded = URIUtil.decode( "Hello%20World%3F" );
5
6 System.out.println( "Encoded: " + encoded1 );
7 System.out.println( "Encoded: " + encoded2 );
8 System.out.println( "Decoded: " + decoded );
这个简单的例子用URIUtil类对两个字符串进行了编码,并对一个经过编码的字符串进行解码。下面的输出展示了每个转换的结果:
Encoded: %3ctest%e3=O'Connell
Encoded: one%3atwo=thr%20ee#23
Decoded: Hello World?
参考:
在这个例子中,URLUtil对传入的查询字符串的内容进行了编码。最近,HttpClient小组将一些URL编码和解码的逻辑代码移入了Jakarta Commons Codec项目中,对应的类名为URLCodec。需要URLCodec更多的信息,请参考
Jakarta Commons Codec项目主页(http://jakarta.apache.org/codec)。
RFC1738讨论了URL中的合法字符,并规定了对其他字符进行编码的过程。RFC1738能够在http:// www.zvon.org/tmRFC/RFC2616/Output/index.html中找到。