最近做一个RSS功能,通过后台读取另一服务器上的RSS内容,第三方公司提供了一个公共的请求地址,他们内部会根据请求参数cmd重定向(将公共的请求地址后的参数附上),如下图:
1、在IE中直接请求“http://*******/CRBT_new/jsp/rss.jsp?cmd=search&module=12530-search&nums=10&keywords=中国&page=1&category=2” 有数据输出
2、通过以下代码获取时无结果输出,即使将keywords中的中文通过URLEncoder.encode("中国", "GBK")、URLEncoder.encode("中国", "UTF-8")转码也无结果输出
public static void main(String[] args) throws IOException {
String urlStr = "http://*******/CRBT_new/jsp/rss.jsp?cmd=search&module=12530-search&nums=10&keywords=中国&page=1&category=2";
// String urlStr = "http://*******/rss/rssSearchRing.action?category=2&page=1&keywords=中国&pageCount=10";
URL url = new URL(urlStr);
URLConnection conn=(URLConnection)url.openConnection();
InputStream input = conn.getInputStream();
String content = InputStreamUtils.getContentsAsString(input, "UTF-8");
System.out.println(content);
}
3、如果将urlStr换成重重定向后的地址,有数据返回
原因
当执行conn.getInputStream()时,服务端返回重定向的地址和请求参数给客户端,客户端再次编码,所以导致了乱码(可能理解不太正确,欢迎纠正),结果如下:
rssSearchRing.action?category=2&page=1&keywords=Öйú&pageCount=10
解决方法
使用HttpClient的GetMethod方法,默认状态下GetMethod的实例是自动处理跳转的,POST和PUT,不支持自动转发,完整代码如下
public static void main(String[] args) throws HttpException, IOException {
HttpClient httpclient = new HttpClient();
String source = " http://*****/CRBT_new/jsp/rss.jsp";
GetMethod getMethod = new GetMethod(source);
NameValuePair[] pairs = new NameValuePair[6];
pairs[0] = new NameValuePair("keywords", URLEncoder.encode("中国", "GBK"));
pairs[1] = new NameValuePair("cmd", "search");
pairs[2] = new NameValuePair("module", "12530-search");
pairs[3] = new NameValuePair("nums", "10");
pairs[4] = new NameValuePair("page", "1");
pairs[5] = new NameValuePair("category", "2");
getMethod.setQueryString(pairs);
httpclient.executeMethod(getMethod);
InputStream input = getMethod.getResponseBodyAsStream();
getMethod.releaseConnection();//记得释放连接
}
总结
jdk自带的URLConnection处理重定向时存在一定的缺陷,尽量使用apache的HttpClient,处理http协议时jdk库不太灵活,尽量也使用apache的HttpClient