Java网络编程:利用apache的HttpClient包进行http操作
本文介绍如何利用apache的HttpClient包进行http操作,包括get操作和post操作。
一、下面的代码是对HttpClient包的封装,以便于更好的编写应用代码。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.httpclient.util.URIUtil; import org.apache.commons.lang.StringUtils; public class MyHttpClient { private HttpClient httpClient; private String cookies; public MyHttpClient(String ip) { this(ip, 80); } public MyHttpClient(String ip, int port) { httpClient = new HttpClient(); httpClient.getHostConfiguration().setHost(ip, port, "http"); httpClient.getParams().setCookiePolicy( CookiePolicy.BROWSER_COMPATIBILITY); } public String getCookies(){ return cookies; } public void setCookies(String cookies){ this.cookies = cookies; } public String doGet(String url) throws IOException{ return doGet(url,null); } public String doGet(String url, String paras) throws IOException { GetMethod method = new GetMethod(url); if (StringUtils.isNotBlank(paras)) { method.setQueryString(URIUtil.encodeQuery(paras)); } return sendRequest(method); } public String doPost(String url) throws IOException{ return doPost(url,new HashMap<String,String>()); } public String doPost(String url, String paras) throws IOException { Map<String,String> paraMap = new HashMap<String,String>(); String[] values = paras.split("&"); for(String value:values){ String[] item = value.split("="); if(item.length==2){ paraMap.put(item[0].trim(), item[1].trim()); } } return doPost(url,paraMap); } public String doPost(String url, Map<String,String> paras) throws IOException{ int index=0; NameValuePair[] data = new NameValuePair[paras.size()]; for(Map.Entry<String,String> entry:paras.entrySet()){ data[index++] = new NameValuePair(entry.getKey(),entry.getValue()); } return doPost(url,data); } private String doPost(String url, NameValuePair[] data) throws IOException{ PostMethod method = new PostMethod(url); method.setRequestBody(data); method.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"utf-8"); return sendRequest(method); } private String sendRequest(HttpMethod method) throws IOException{ StringBuffer response = new StringBuffer(); try { method.setRequestHeader("Cookie", cookies); httpClient.executeMethod(method); if (method.getStatusCode() == HttpStatus.SC_OK) { response.append(getResponseBody(method)); }else if(method.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY){ //302 重定向 response.append(getResponseHeader(method)); }else { System.out.println("response statuscode : " + method.getStatusCode()); throw new IllegalStateException("response statuscode : " + method.getStatusCode()); } fetchCookies(); }finally { method.releaseConnection(); } return response.toString(); } private void fetchCookies(){ Cookie[] values = httpClient.getState().getCookies(); StringBuffer cookieBuffer = new StringBuffer(); for (Cookie c : values) { cookieBuffer.append(c.toString()).append(";"); } cookies = cookieBuffer.toString(); } private String getResponseBody(HttpMethod method) throws IOException, IOException { StringBuffer response = new StringBuffer(); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader( method.getResponseBodyAsStream(), "UTF-8")); String line; while ((line = reader.readLine()) != null) { response.append(line).append( System.getProperty("line.separator")); } }finally { if (reader != null) { try { reader.close(); } catch (IOException e) { } } } return response.toString(); } private String getResponseHeader(HttpMethod method){ StringBuffer response = new StringBuffer(); Header[] headers = method.getResponseHeaders(); for(Header header:headers){ String line = header.getName()+" : "+header.getValue(); response.append(line); response.append(System.getProperty("line.separator")); } return response.toString(); } }
说明:上面代码中doGet方法中的 语句 String encodeQuery = URIUtil.encodeQuery(paras);
存在一点问题,当url部门有特殊字符,如空格、+ 号等,这些字符需要被编码。
这时需要换成 String encodeQuery = URIUtil.encodePath(paras); 语句,即用encodePath方法替代encodeQuery方法。
二、下面来进行实际的使用举例
1、简单的get操作
下面的代码完成对一个url的get操作。我们封装了两个doGet操作,一个是带参数的,一个是不带参数的。待参数的参数格式如 name1=value1&name2=value2
MyHttpClient httpClient = new MyHttpClient("xxxx"); //xxxx是web服务器的地址
String result = httpClient.doGet(url); //url是请求的url地址
System.out.println(result);
2、简单的post操作
下面的代码完成对一个url的post操作.
MyHttpClient httpClient = new MyHttpClient("localhost"); Map<String,String> paras = new HashMap<String,String>(); paras.put("para1", "value1"); paras.put("para2", "value2"); String result = httpClient.doPost(url,paras); System.out.println(result);
3、有重定向的get操作
如果发起的一个get操作,被服务器重定向到一个新的url。这时我们封装的doGet操作返回的是新的url(重定向后的)对应的信息。
4、有重定向的post操作
如果发起的一个post操作,被服务器重定向到一个新的url。我们封装的doPost操作,与doGet操作返回的结果不同,doPost是返回重定向头信息,而不是新的url的信息。如返回如下的信息,其中Location对应的值login就是重定向的url
Server : Apache-Coyote/1.1
Set-Cookie : JSESSIONID=8115A882086E7F27809FDF24213F82F5; Path=/boot/; HttpOnly
Set-Cookie :Expires=Thu, 01-Jan-1970 00:00:10 GMT
Location : login
Content-Length : 0
Date : Sat, 09 Jan 2016 07:41:21 GMT
5、需要登录的请求
有的web服务器有鉴权功能,当发起一个请求时,如果在该请求之前还没有登录,会自动重定向到登录页面,登录成功后才会跳转到想要请求的页面。
这时代码应该这样写:
MyHttpClient httpClient = new MyHttpClient("localhost"); //下面是登录请求 httpClient.doPost(loginUrl,"username=xxx&password=yyy"); //因为前面已经登录,下面的url将不会发生重定向。而是返回该url对应页面的本身信息。 String result = httpClient.doGet(url); System.out.println(result);
6、与cookie有关的请求
有的web应用中,用到了cookie。所谓的cookie,就是希望浏览器操作关闭后,会在浏览器本地客户端机器上记录下一些信息。当下次打开浏览器,操作相关的页面后,这些信息能被带到服务器。我们封装的这个功能对此也支持。具体通过例子说明:
MyHttpClient httpClient = new MyHttpClient("localhost"); //下面的操作,会产生cookie httpClient.doPost(url,paras); //获取本次会话产生的cookie String cookies = httpClient.getCookies(); //开启一个新的会话 MyHttpClient otherHttpClient = new MyHttpClient("localhost"); //将上次会话的cookie设置到本次会话中,以便于cookie能带到服务器 otherHttpClient.setCookies(cookies); //这次请求就会上个会话产生的cookie带到服务器 String result = otherHttpClient.doGet(otherUrl); System.out.println(result);
三、小结
我们封装的这个httpclient类,可以很方便的完成http请求的一些基本操作。并且对有鉴权控制、cookie功能的网站也能较好的满足。