标签:java httpclient http协议
相对于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 = he.getValue(); if (value != null && param.equalsIgnoreCase("timeout")) { try { System.out.println("服务器指定的超时时间:" + value + " 秒"); return Long.parseLong(value) * 1000; } catch (NumberFormatException ignore) { ignore.printStackTrace(); } } } long keepAlive = super.getKeepAliveDuration(response, context); // 如果服务器未指定超时时间,则客户端默认30s超时 if (keepAlive == -1) { keepAlive = 30 * 1000; } return keepAlive; /*如果访问webservice.webxml.com.cn主机,则超时时间5秒,其他主机超时时间30秒 HttpHost host = (HttpHost) context.getAttribute(HttpClientContext.HTTP_TARGET_HOST); if ("webservice.webxml.com.cn".equalsIgnoreCase(host.getHostName())) { keepAlive = 10 * 1000; } else { keepAlive = 30 * 1000; }*/ } }; CloseableHttpClient client = HttpClients.custom().setKeepAliveStrategy(strategy).build(); URI uri = null;//构建uri实体 try { uri = new URIBuilder() .setScheme("http") .setHost("webservice.webxml.com.cn") .setPath("/WebServices/MobileCodeWS.asmx/getDatabaseInfo") .setParameter("", "") .build(); } catch (URISyntaxException e) { e.printStackTrace(); } HttpPost post = new HttpPost(uri); try { CloseableHttpResponse response = client.execute(post); if(response.getStatusLine().getStatusCode()==200){ String result = EntityUtils.toString(response.getEntity()); System.out.println("返回的结果====="+result); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 构建复杂请求体 * * RequestConfig将会保存在context上下文中,并会在连续的请求中进行传播(来自官方文档); * */ private void test5(){ CloseableHttpClient client = HttpClients.createDefault(); //构建请求配置 RequestConfig config = RequestConfig. custom(). setSocketTimeout(1000*10). setConnectTimeout(1000*10). build(); //============================================================== 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){ 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; 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); post.setConfig(config);//设置请求配置 try { Object obj = client.execute(post, handler); System.out.println("返回结果:"+obj); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 异常恢复机制: * * HttpRequestRetryHandler连接失败后,可以针对相应的异常进行相应的处理措施; * HttpRequestRetryHandler接口须要用户自己实现; * */ private static void test6(){ HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() { /** * exception异常信息; * executionCount:重连次数; * context:上下文 */ @Override public boolean retryRequest(IOException exception, int executionCount,HttpContext context) { System.out.println("重连接次数:"+executionCount); if (executionCount >= 5) {//如果连接次数超过5次,就不进行重复连接 return false; } if (exception instanceof InterruptedIOException) {//io操作中断 return false; } if (exception instanceof UnknownHostException) {//未找到主机 // Unknown host return false; } if (exception instanceof ConnectTimeoutException) {//连接超时 return true; } if (exception instanceof SSLException) { // SSL handshake exception return false; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) { // Retry if the request is considered idempotent return true; } return false; } }; CloseableHttpClient client = HttpClients.custom().setRetryHandler(retryHandler).build(); RequestConfig config = RequestConfig. custom(). setSocketTimeout(1000*10). setConnectTimeout(1000*10). build(); HttpPost post = new HttpPost("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getDatabaseInfo"); post.setConfig(config); try { HttpResponse response = client.execute(post); HttpEntity entity = response.getEntity(); 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)); } System.out.println("返回的结果:"+sb.toString()); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * HTTP请求过滤器,在执行请求之前拦截HttpRequest 和 HttpContext; */ private static void test7() throws ClientProtocolException, IOException{ HttpRequestInterceptor requestInterceptor = new HttpRequestInterceptor() { /** * 处理请求: * 如果是客户端:这个处理在发送请求之前执行; * 如果是服务器:这个处理在接收到请求体之前执行; */ public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { AtomicInteger count = (AtomicInteger) context.getAttribute("count"); request.addHeader("count", Integer.toString(count.getAndIncrement())); } }; CloseableHttpClient httpclient = HttpClients. custom(). addInterceptorLast(requestInterceptor). build(); AtomicInteger count = new AtomicInteger(1); HttpClientContext context = HttpClientContext.create(); context.setAttribute("count", count); HttpGet httpget = new HttpGet("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getDatabaseInfo"); for (int i = 0; i < 10; i++) { CloseableHttpResponse response = httpclient.execute(httpget,context); try { HttpEntity entity = response.getEntity(); // System.out.println(EntityUtils.toString(entity)); } finally { response.close(); } } } /** * * httpclient会自动处理重定向; * * 301 永久重定向,告诉客户端以后应从新地址访问. 302 作为HTTP1.0的标准,以前叫做Moved Temporarily ,现在叫Found. 现在使用只是为了兼容性的 处理,包括PHP的默认Location重定向用的也是302. 但是HTTP 1.1 有303 和307作为详细的补充,其实是对302的细化 303:对于POST请求,它表示请求已经被处理,客户端可以接着使用GET方法去请求Location里的URI。 307:对于POST请求,表示请求还没有被处理,客户端应该向Location里的URI重新发起POST请求。 */ private static void test8() throws ClientProtocolException, IOException, URISyntaxException { LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy(); CloseableHttpClient httpclient = HttpClients.custom().setRedirectStrategy(redirectStrategy).build(); HttpClientContext context = HttpClientContext.create(); HttpGet httpget = new HttpGet("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getDatabaseInfo"); CloseableHttpResponse response = httpclient.execute(httpget, context); try { HttpHost target = context.getTargetHost(); List<URI> redirectLocations = context.getRedirectLocations(); URI location = URIUtils.resolve(httpget.getURI(), target, redirectLocations); System.out.println("Final HTTP location: " + location.toASCIIString()); } finally { response.close(); } } }
JAVA: httpclient 详解;,布布扣,bubuko.com
标签:java httpclient http协议
原文地址:http://blog.csdn.net/lyc66666666666/article/details/36899463