首页 > 代码库 > JAVA: httpclient 详解;

JAVA: httpclient 详解;

相对于httpurlconnection ,httpclient更加丰富,也更加强大,其中apache有两个项目都是httpclient,一个是commonts包下的,这个是通用的,更专业的是org.apache.http.包下的,所以我一般用后者;


httpclient可以处理长连接,保存会话,重连接,以及请求过滤器,连接重用等等...


下面是测试代码(全部总结来自官方文档,以及翻译)


须要下载核心包:httpclient-4.3.4.jar ,也可在官网下载:http://hc.apache.org/downloads.cgi



package httpClientTest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import javax.net.ssl.SSLException;

import org.apache.http.Consts;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpClientConnection;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.ConnectionRequest;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

public class Main {

	
	public static void main(String[] args) {
		
		try {
			test9();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
	
	
	
	/**
	 * 测试1: 构建复杂uri,这种方式会很方便的设置多个参数;
	 * 
	 * HttpClients类是client的具体一个实现类;
	 * 
	 * URIBuilder包含:协议,主机名,端口(可选),资源路径,和多个参数(可选)
	 * 
	 */
	private static void test1() {
		
		CloseableHttpClient client = HttpClients.createDefault();
		
		URI uri = null;
		try {
			uri = new URIBuilder()
			.setScheme("http")
			.setHost("webservice.webxml.com.cn")
			.setPath("/WebServices/MobileCodeWS.asmx/getDatabaseInfo")
			.setParameter("", "")//这里可以设置多个参数
			.setParameter("", "")
			.setParameter("", "")
			.setParameter("", "")
			.build();
		} catch (URISyntaxException e1) {
			e1.printStackTrace();
		}
		
		//http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getDatabaseInfo
		HttpGet get = new HttpGet(uri);
		try {
			CloseableHttpResponse response = client.execute(get);
			
			if(response.getStatusLine().getStatusCode()==200){
				
				
				System.out.println(EntityUtils.toString(response.getEntity()));
				
				//以下这种方式读取流也可以,只不过用EntityUtils会更方便
				/*InputStream is = response.getEntity().getContent();
				ByteArrayOutputStream os = new ByteArrayOutputStream();
				byte[] buffer = new byte[1024];
				int len=-1;
				while((len = is.read(buffer))!=-1){
					os.write(buffer,0,len);
				}
				os.close();
				is.close();
				System.out.println(os.size()+new String(os.toByteArray(),"utf-8"));*/
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	/**
	 * 为uri进行加密,并进行表单提交;
	 * 
	 * 许多应用需要模拟提交的HTML表单的处理,例如,在
		为了登录到Web应用程序或提交的输入数据。 HttpClient提供的实体类
		UrlEncodedFormEntity可以实现该过程;
	 */
	private static void test2(){
		
		CloseableHttpClient client = HttpClients.createDefault();
		
		HttpPost httppost = new HttpPost("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo");
		
		//构建请求参数
		List<NameValuePair> list = new ArrayList<NameValuePair>();
		list.add(new BasicNameValuePair("mobileCode", "110"));
		list.add(new BasicNameValuePair("userID", ""));

		//构建url加密实体,并以utf-8方式进行加密;
		UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, Consts.UTF_8);
		httppost.setEntity(entity);
		
		try {
			CloseableHttpResponse response = client.execute(httppost);
			
			if(response.getStatusLine().getStatusCode()==200){
				
				//org.apache.http.util.EntityUtils类可以快速处理服务器返回实体对象
				System.out.println(EntityUtils.toString(response.getEntity()));
				
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
	}
	
	
	/**
	 * 以回调方式处理返回结果
	 * 
	 *  处理响应的最简单和最方便的方法是通过使用ResponseHandler的
		接口。用户不必担心连接管理的问题。当使用一个
		ResponseHandler的时候,无论是否请求执行成功或导致异常,HttpClient将会自动释放连接。
	 */
	private static void test3(){
		
		CloseableHttpClient client = HttpClients.createDefault();
		
		//==============================================================
		ResponseHandler<Object> handler = new ResponseHandler<Object>() {
			@Override
			public Object handleResponse(final HttpResponse response) throws IOException {
				
				HttpEntity entity = response.getEntity();
				
				if (entity == null) {
					throw new ClientProtocolException("返回结果为空");
				}
			
				if(response.getStatusLine().getStatusCode()==200){
					
					//获取返回结果的字符集 如:utf-8  gbk,并以这种字符集来读取流信息
					ContentType contentType = ContentType.getOrDefault(entity);
					Charset charset = contentType.getCharset();
					
					InputStreamReader reader = new InputStreamReader(entity.getContent(), charset);
					BufferedReader br = new BufferedReader(reader);
					StringBuffer sb = new StringBuffer();
					char[] buffer = new char[1024];
					while (br.read(buffer)!=-1) {
						sb.append(new String(buffer));
					}
					
					return sb.toString();
				}
				
				return null;
				
			}
		};
		//===================================================================
		
		URI uri = null;//构建uri实体
		try {
			uri = new URIBuilder()
			.setScheme("http")
			.setHost("webservice.webxml.com.cn")
			.setPath("/WebServices/MobileCodeWS.asmx/getDatabaseInfo")
			.setParameter("", "")
			.setParameter("", "")
			.setParameter("", "")
			.build();
			
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		
		HttpPost post = new HttpPost(uri);
		
		try {
			
			//handler回调
			 Object obj = client.execute(post, handler);
			 
			 System.out.println("返回结果:"+obj);
			
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	
	
	/**
	 * 	设置长连接策略,根据服务器的约束或者客户端的约束来设置长连接的时长;
	 */
	private static void test4() {
		
		ConnectionKeepAliveStrategy strategy = new DefaultConnectionKeepAliveStrategy() {
			
			/**
			 * 服务器端配置(以tomcat为例):keepAliveTimeout=60000,表示在60s内内,服务器会一直保持连接状态。
			 * 也就是说,如果客户端一直请求服务器,且间隔未超过60s,则该连接将一直保持,如果60s内未请求,则超时。
			 * 
			 * getKeepAliveDuration返回超时时间;
			 */
			@Override
			public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
				
				
				//如果服务器指定了超时时间,则以服务器的超时时间为准
		        HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
		        while (it.hasNext()) {
					HeaderElement he = it.nextElement();
					String param = he.getName();
					String value = http://www.mamicode.com/he.getValue();>