精华内容
参与话题
问答
  • HttpClient使用详解

    万次阅读 多人点赞 2014-02-28 11:04:29
    Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http...

    Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入。

    一、简介

    HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。

    下载地址: http://hc.apache.org/downloads.cgi

    二、特性

    1. 基于标准、纯净的java语言。实现了Http1.0和Http1.1

    2. 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。

    3. 支持HTTPS协议。

    4. 通过Http代理建立透明的连接。

    5. 利用CONNECT方法通过Http代理建立隧道的https连接。

    6. Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。

    7. 插件式的自定义认证方案。

    8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。

    9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。

    10. 自动处理Set-Cookie中的Cookie。

    11. 插件式的自定义Cookie策略。

    12. Request的输出流可以避免流中内容直接缓冲socket服务器。

    13. Response的输入流可以有效的从socket服务器直接读取相应内容。

    14. 在http1.0和http1.1中利用KeepAlive保持持久连接。

    15. 直接获取服务器发送的response code和 headers。

    16. 设置连接超时的能力。

    17. 实验性的支持http1.1 response caching。

    18. 源代码基于Apache License 可免费获取。

    三、使用方法

    使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。

    1. 创建HttpClient对象。

    2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。

    3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。

    4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。

    5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。

    6. 释放连接。无论执行方法是否成功,都必须释放连接

    四、实例

    package com.test;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.security.KeyManagementException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.CertificateException;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.net.ssl.SSLContext;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.NameValuePair;
    import org.apache.http.ParseException;
    import org.apache.http.client.ClientProtocolException;
    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.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLContexts;
    import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
    import org.apache.http.entity.ContentType;
    import org.apache.http.entity.mime.MultipartEntityBuilder;
    import org.apache.http.entity.mime.content.FileBody;
    import org.apache.http.entity.mime.content.StringBody;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.util.EntityUtils;
    import org.junit.Test;
    
    public class HttpClientTest {
    
    	@Test
    	public void jUnitTest() {
    		get();
    	}
    
    	/**
    	 * HttpClient连接SSL
    	 */
    	public void ssl() {
    		CloseableHttpClient httpclient = null;
    		try {
    			KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    			FileInputStream instream = new FileInputStream(new File("d:\\tomcat.keystore"));
    			try {
    				// 加载keyStore d:\\tomcat.keystore  
    				trustStore.load(instream, "123456".toCharArray());
    			} catch (CertificateException e) {
    				e.printStackTrace();
    			} finally {
    				try {
    					instream.close();
    				} catch (Exception ignore) {
    				}
    			}
    			// 相信自己的CA和所有自签名的证书
    			SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();
    			// 只允许使用TLSv1协议
    			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
    					SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
    			httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
    			// 创建http请求(get方式)
    			HttpGet httpget = new HttpGet("https://localhost:8443/myDemo/Ajax/serivceJ.action");
    			System.out.println("executing request" + httpget.getRequestLine());
    			CloseableHttpResponse response = httpclient.execute(httpget);
    			try {
    				HttpEntity entity = response.getEntity();
    				System.out.println("----------------------------------------");
    				System.out.println(response.getStatusLine());
    				if (entity != null) {
    					System.out.println("Response content length: " + entity.getContentLength());
    					System.out.println(EntityUtils.toString(entity));
    					EntityUtils.consume(entity);
    				}
    			} finally {
    				response.close();
    			}
    		} catch (ParseException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} catch (KeyManagementException e) {
    			e.printStackTrace();
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		} catch (KeyStoreException e) {
    			e.printStackTrace();
    		} finally {
    			if (httpclient != null) {
    				try {
    					httpclient.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    
    	/**
    	 * post方式提交表单(模拟用户登录请求)
    	 */
    	public void postForm() {
    		// 创建默认的httpClient实例.  
    		CloseableHttpClient httpclient = HttpClients.createDefault();
    		// 创建httppost  
    		HttpPost httppost = new HttpPost("http://localhost:8080/myDemo/Ajax/serivceJ.action");
    		// 创建参数队列  
    		List formparams = new ArrayList();
    		formparams.add(new BasicNameValuePair("username", "admin"));
    		formparams.add(new BasicNameValuePair("password", "123456"));
    		UrlEncodedFormEntity uefEntity;
    		try {
    			uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
    			httppost.setEntity(uefEntity);
    			System.out.println("executing request " + httppost.getURI());
    			CloseableHttpResponse response = httpclient.execute(httppost);
    			try {
    				HttpEntity entity = response.getEntity();
    				if (entity != null) {
    					System.out.println("--------------------------------------");
    					System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8"));
    					System.out.println("--------------------------------------");
    				}
    			} finally {
    				response.close();
    			}
    		} catch (ClientProtocolException e) {
    			e.printStackTrace();
    		} catch (UnsupportedEncodingException e1) {
    			e1.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			// 关闭连接,释放资源  
    			try {
    				httpclient.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    	/**
    	 * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
    	 */
    	public void post() {
    		// 创建默认的httpClient实例.  
    		CloseableHttpClient httpclient = HttpClients.createDefault();
    		// 创建httppost  
    		HttpPost httppost = new HttpPost("http://localhost:8080/myDemo/Ajax/serivceJ.action");
    		// 创建参数队列  
    		List formparams = new ArrayList();
    		formparams.add(new BasicNameValuePair("type", "house"));
    		UrlEncodedFormEntity uefEntity;
    		try {
    			uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
    			httppost.setEntity(uefEntity);
    			System.out.println("executing request " + httppost.getURI());
    			CloseableHttpResponse response = httpclient.execute(httppost);
    			try {
    				HttpEntity entity = response.getEntity();
    				if (entity != null) {
    					System.out.println("--------------------------------------");
    					System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8"));
    					System.out.println("--------------------------------------");
    				}
    			} finally {
    				response.close();
    			}
    		} catch (ClientProtocolException e) {
    			e.printStackTrace();
    		} catch (UnsupportedEncodingException e1) {
    			e1.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			// 关闭连接,释放资源  
    			try {
    				httpclient.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    	/**
    	 * 发送 get请求
    	 */
    	public void get() {
    		CloseableHttpClient httpclient = HttpClients.createDefault();
    		try {
    			// 创建httpget.  
    			HttpGet httpget = new HttpGet("http://www.baidu.com/");
    			System.out.println("executing request " + httpget.getURI());
    			// 执行get请求.  
    			CloseableHttpResponse response = httpclient.execute(httpget);
    			try {
    				// 获取响应实体  
    				HttpEntity entity = response.getEntity();
    				System.out.println("--------------------------------------");
    				// 打印响应状态  
    				System.out.println(response.getStatusLine());
    				if (entity != null) {
    					// 打印响应内容长度  
    					System.out.println("Response content length: " + entity.getContentLength());
    					// 打印响应内容  
    					System.out.println("Response content: " + EntityUtils.toString(entity));
    				}
    				System.out.println("------------------------------------");
    			} finally {
    				response.close();
    			}
    		} catch (ClientProtocolException e) {
    			e.printStackTrace();
    		} catch (ParseException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			// 关闭连接,释放资源  
    			try {
    				httpclient.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    	/**
    	 * 上传文件
    	 */
    	public void upload() {
    		CloseableHttpClient httpclient = HttpClients.createDefault();
    		try {
    			HttpPost httppost = new HttpPost("http://localhost:8080/myDemo/Ajax/serivceFile.action");
    
    			FileBody bin = new FileBody(new File("F:\\image\\sendpix0.jpg"));
    			StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);
    
    			HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("bin", bin).addPart("comment", comment).build();
    
    			httppost.setEntity(reqEntity);
    
    			System.out.println("executing request " + httppost.getRequestLine());
    			CloseableHttpResponse response = httpclient.execute(httppost);
    			try {
    				System.out.println("----------------------------------------");
    				System.out.println(response.getStatusLine());
    				HttpEntity resEntity = response.getEntity();
    				if (resEntity != null) {
    					System.out.println("Response content length: " + resEntity.getContentLength());
    				}
    				EntityUtils.consume(resEntity);
    			} finally {
    				response.close();
    			}
    		} catch (ClientProtocolException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				httpclient.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }

    本实例是采用HttpClient4.3最新版本。该版本与之前的代码写法风格相差较大,大家多留意下。

    展开全文
  • Client客户端下载

    2017-12-01 10:36:59
    Socket、TCP/IP!,比较使用的一款小程序,亲测过,拿来可以直接使用,如有需要可以下载!
  • HttpClient入门教程

    万次阅读 2017-12-20 13:45:04
    HttpClient简介 HttpClient 功能介绍  1. 读取网页(HTTP/HTTPS)内容  2、使用POST方式提交数据(httpClient3)   3. 处理页面重定向  4. 模拟登录开心网  5.... 6.... 7....httpClient


     

    HttpClient简介

    HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。更多信息请关注http://hc.apache.org/

     

    HttpClient 功能介绍

    以下列出的是 HttpClient 提供的主要的功能,要知道更多详细的功能可以参见 HttpClient 的主页。

    • 实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)

    • 支持自动转向

    • 支持 HTTPS 协议

    • 支持代理服务器等

    应用HttpClient来对付各种顽固的WEB服务器
    转自:http://blog.csdn.net/ambitiontan/archive/2006/01/06/572171.aspx

    一般的情况下我们都是使用IE或者Navigator浏览器来访问一个WEB服务器,用来浏览页面查看信息或者提交一些数据等等。所访问的这些页面有的仅仅是一些普通的页面,有的需要用户登录后方可使用,或者需要认证以及是一些通过加密方式传输,例如HTTPS。目前我们使用的浏览器处理这些情况都不会构成问题。不过你可能在某些时候需要通过程序来访问这样的一些页面,比如从别人的网页中“偷”一些数据;利用某些站点提供的页面来完成某种功能,例如说我们想知道某个手机号码的归属地而我们自己又没有这样的数据,因此只好借助其他公司已有的网站来完成这个功能,这个时候我们需要向网页提交手机号码并从返回的页面中解析出我们想要的数据来。如果对方仅仅是一个很简单的页面,那我们的程序会很简单,本文也就没有必要大张旗鼓的在这里浪费口舌。但是考虑到一些服务授权的问题,很多公司提供的页面往往并不是可以通过一个简单的URL就可以访问的,而必须经过注册然后登录后方可使用提供服务的页面,这个时候就涉及到COOKIE问题的处理。我们知道目前流行的动态网页技术例如ASP、JSP无不是通过COOKIE来处理会话信息的。为了使我们的程序能使用别人所提供的服务页面,就要求程序首先登录后再访问服务页面,这过程就需要自行处理cookie,想想当你用java.net.HttpURLConnection来完成这些功能时是多么恐怖的事情啊!况且这仅仅是我们所说的顽固的WEB服务器中的一个很常见的“顽固”!再有如通过HTTP来上传文件呢?不需要头疼,这些问题有了“它”就很容易解决了!

     

    我们不可能列举所有可能的顽固,我们会针对几种最常见的问题进行处理。当然了,正如前面说到的,如果我们自己使用java.net.HttpURLConnection来搞定这些问题是很恐怖的事情,因此在开始之前我们先要介绍一下一个开放源码的项目,这个项目就是Apache开源组织中的httpclient,它隶属于Jakarta的commons项目,目前的版本是2.0RC2。commons下本来已经有一个net的子项目,但是又把httpclient单独提出来,可见http服务器的访问绝非易事。

    Commons-httpclient项目就是专门设计来简化HTTP客户端与服务器进行各种通讯编程。通过它可以让原来很头疼的事情现在轻松的解决,例如你不再管是HTTP或者HTTPS的通讯方式,告诉它你想使用HTTPS方式,剩下的事情交给httpclient替你完成。本文会针对我们在编写HTTP客户端程序时经常碰到的几个问题进行分别介绍如何使用httpclient来解决它们,为了让读者更快的熟悉这个项目我们最开始先给出一个简单的例子来读取一个网页的内容,然后循序渐进解决掉前进中的所有问题。

     

    1. 读取网页(HTTP/HTTPS)内容

    下面是我们给出的一个简单的例子用来访问某个页面

    复制代码
    /** 
     *最简单的HTTP客户端,用来演示通过GET或者POST方式访问某个页面
      *@authorLiudong
    */
    public class SimpleClient {
    public static void main(String[] args) throws IOException 
    {
      HttpClient client = new HttpClient(); 
          // 设置代理服务器地址和端口      
          //client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port); 
          // 使用 GET 方法 ,如果服务器需要通过 HTTPS 连接,那只需要将下面 URL 中的 http 换成 https 
             HttpMethod method=new GetMethod("http://java.sun.com");
          //使用POST方法
          //HttpMethod method = new PostMethod("http://java.sun.com");
          client.executeMethod(method);
    
          //打印服务器返回的状态
          System.out.println(method.getStatusLine());
          //打印返回的信息
          System.out.println(method.getResponseBodyAsString());
          //释放连接
          method.releaseConnection();
       }
    }
    复制代码

     

    在这个例子中首先创建一个HTTP客户端(HttpClient)的实例,然后选择提交的方法是GET或者POST,最后在HttpClient实例上执行提交的方法,最后从所选择的提交方法中读取服务器反馈回来的结果。这就是使用HttpClient的基本流程。其实用一行代码也就可以搞定整个请求的过程,非常的简单!

     

    2、使用POST方式提交数据(httpClient3)

    httpclient使用了单独的一个HttpMethod子类来处理文件的上传,这个类就是MultipartPostMethod,该类已经封装了文件上传的细节,我们要做的仅仅是告诉它我们要上传文件的全路径即可,下面这里将给出关于两种模拟上传方式的代码

     

    第一种:模拟上传url文件(该方式也适合做普通post请求):

    复制代码
    /**
         * 上传url文件到指定URL
         * @param fileUrl 上传图片url
         * @param postUrl 上传路径及参数,注意有些中文参数需要使用预先编码 eg : URLEncoder.encode(appName, "UTF-8")
         * @return
         * @throws IOException
         */
        public static String doUploadFile(String postUrl) throws IOException {
            if(StringUtils.isEmpty(postUrl))
                return null;
            String response = "";
            PostMethod postMethod = new PostMethod(postUrl);
            try {
                HttpClient client = new HttpClient();
                client.getHttpConnectionManager().getParams()
                        .setConnectionTimeout(50000);// 设置连接时间
                int status = client.executeMethod(postMethod);
                if (status == HttpStatus.SC_OK) {
                    InputStream inputStream = postMethod.getResponseBodyAsStream();
                    BufferedReader br = new BufferedReader(new InputStreamReader(
                            inputStream));
                    StringBuffer stringBuffer = new StringBuffer();
                    String str = "";
                    while ((str = br.readLine()) != null) {
                        stringBuffer.append(str);
                    }
                    response = stringBuffer.toString();
                } else {
                    response = "fail";
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 释放连接
                postMethod.releaseConnection();
            }
            return response;
        }
    复制代码

     

     

    第二种:模拟文件上传到指定位置

     

    复制代码
    /**
         * 上传文件到指定URL
         * @param file
         * @param url
         * @return
         * @throws IOException
         */
        public static String doUploadFile(File file, String url) throws IOException {
            String response = "";
            if (!file.exists()) {
                return "file not exists";
            }
            PostMethod postMethod = new PostMethod(url);
            try {
                //----------------------------------------------
                // FilePart:用来上传文件的类,file即要上传的文件
                FilePart fp = new FilePart("file", file);
                Part[] parts = { fp };
    
                // 对于MIME类型的请求,httpclient建议全用MulitPartRequestEntity进行包装
                MultipartRequestEntity mre = new MultipartRequestEntity(parts,
                        postMethod.getParams());
                postMethod.setRequestEntity(mre);
                //---------------------------------------------
                HttpClient client = new HttpClient();
                client.getHttpConnectionManager().getParams()
                        .setConnectionTimeout(50000);// 由于要上传的文件可能比较大 , 因此在此设置最大的连接超时时间
                int status = client.executeMethod(postMethod);
                if (status == HttpStatus.SC_OK) {
                    InputStream inputStream = postMethod.getResponseBodyAsStream();
                    BufferedReader br = new BufferedReader(new InputStreamReader(
                            inputStream));
                    StringBuffer stringBuffer = new StringBuffer();
                    String str = "";
                    while ((str = br.readLine()) != null) {
                        stringBuffer.append(str);
                    }
                    response = stringBuffer.toString();
                } else {
                    response = "fail";
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 释放连接
                postMethod.releaseConnection();
            }
            return response;
        }
    复制代码

     

     

    3. 处理页面重定向

    在JSP/Servlet编程中response.sendRedirect方法就是使用HTTP协议中的重定向机制。它与JSP中的<jsp:forward …>的区别在于后者是在服务器中实现页面的跳转,也就是说应用容器加载了所要跳转的页面的内容并返回给客户端;而前者是返回一个状态码,这些状态码的可能值见下表,然后客户端读取需要跳转到的页面的URL并重新加载新的页面。就是这样一个过程,所以我们编程的时候就要通过HttpMethod.getStatusCode()方法判断返回值是否为下表中的某个值来判断是否需要跳转。如果已经确认需要进行页面跳转了,那么可以通过读取HTTP头中的location属性来获取新的地址。

     


    下面的代码片段演示如何处理页面的重定向

    复制代码
    client.executeMethod(post);
    System.out.println(post.getStatusLine().toString());
    post.releaseConnection();
    // 检查是否重定向
    int statuscode = post.getStatusCode();
    if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) || (statuscode == HttpStatus.SC_MOVED_PERMANENTLY) || 
    (statuscode ==HttpStatus.SC_SEE_OTHER) || (statuscode == HttpStatus.SC_TEMPORARY_REDIRECT)) {
    // 读取新的 URL 地址 
       Header header=post.getResponseHeader("location");
       if (header!=null){
          Stringnewuri=header.getValue();
          if((newuri==null)||(newuri.equals("")))
             newuri="/";
             GetMethodredirect=newGetMethod(newuri);
             client.executeMethod(redirect);
             System.out.println("Redirect:"+redirect.getStatusLine().toString());
             redirect.releaseConnection();
       }else 
        System.out.println("Invalid redirect");
    }
    复制代码

     

     

    我们可以自行编写两个JSP页面,其中一个页面用response.sendRedirect方法重定向到另外一个页面用来测试上面的例子。

     

    4. 模拟登录开心网

    本小节应该说是HTTP客户端编程中最常碰见的问题,很多网站的内容都只是对注册用户可见的,这种情况下就必须要求使用正确的用户名和口令登录成功后,方可浏览到想要的页面。因为HTTP协议是无状态的,也就是连接的有效期只限于当前请求,请求内容结束后连接就关闭了。在这种情况下为了保存用户的登录信息必须使用到Cookie机制。以JSP/Servlet为例,当浏览器请求一个JSP或者是Servlet的页面时,应用服务器会返回一个参数,名为jsessionid(因不同应用服务器而异),值是一个较长的唯一字符串的Cookie,这个字符串值也就是当前访问该站点的会话标识。浏览器在每访问该站点的其他页面时候都要带上jsessionid这样的Cookie信息,应用服务器根据读取这个会话标识来获取对应的会话信息。

    对于需要用户登录的网站,一般在用户登录成功后会将用户资料保存在服务器的会话中,这样当访问到其他的页面时候,应用服务器根据浏览器送上的Cookie中读取当前请求对应的会话标识以获得对应的会话信息,然后就可以判断用户资料是否存在于会话信息中,如果存在则允许访问页面,否则跳转到登录页面中要求用户输入帐号和口令进行登录。这就是一般使用JSP开发网站在处理用户登录的比较通用的方法。

    这样一来,对于HTTP的客户端来讲,如果要访问一个受保护的页面时就必须模拟浏览器所做的工作,首先就是请求登录页面,然后读取Cookie值;再次请求登录页面并加入登录页所需的每个参数;最后就是请求最终所需的页面。当然在除第一次请求外其他的请求都需要附带上Cookie信息以便服务器能判断当前请求是否已经通过验证。说了这么多,可是如果你使用httpclient的话,你甚至连一行代码都无需增加,你只需要先传递登录信息执行登录过程,然后直接访问想要的页面,跟访问一个普通的页面没有任何区别,因为类HttpClient已经帮你做了所有该做的事情了,太棒了!下面的例子实现了模拟登陆开心网并向自己好友发送消息的功能。

     

    复制代码
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    
    import org.apache.commons.httpclient.Cookie;
    import org.apache.commons.httpclient.Header;
    import org.apache.commons.httpclient.HttpClient;
    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.HttpClientParams;
    import org.apache.commons.httpclient.params.HttpMethodParams;
    
    class Login {
        public static String loginurl = "https://security.kaixin001.com/login/login_post.php";
        static Cookie[] cookies = {};
    
        static HttpClient httpClient = new HttpClient();
        
        static String email = "xxx@qq.com";//你的email
        static String psw = "xxx";//你的密码
        // 消息发送的action
        String url = "http://www.kaixin001.com/home/";
    
        public static void getUrlContent()
                throws Exception {
    
            HttpClientParams httparams = new HttpClientParams();
            httparams.setSoTimeout(30000);
            httpClient.setParams(httparams);
    
            httpClient.getHostConfiguration().setHost("www.kaixin001.com", 80);
    
            httpClient.getParams().setParameter(
                    HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
    
            PostMethod login = new PostMethod(loginurl);
            login.addRequestHeader("Content-Type",
                    "application/x-www-form-urlencoded; charset=UTF-8");
    
            NameValuePair Email = new NameValuePair("loginemail", email);// 邮箱
            NameValuePair password = new NameValuePair("password", psw);// 密码
            // NameValuePair code = new NameValuePair( "code"
            // ,"????");//有时候需要验证码,暂时未解决
    
            NameValuePair[] data = { Email, password };
            login.setRequestBody(data);
    
            httpClient.executeMethod(login);
            int statuscode = login.getStatusCode();
            System.out.println(statuscode + "-----------");
            String result = login.getResponseBodyAsString();
            System.out.println(result+"++++++++++++");
    
            cookies = httpClient.getState().getCookies();
            System.out.println("==========Cookies============");
            int i = 0;
            for (Cookie c : cookies) {
                System.out.println(++i + ":   " + c);
            }
            httpClient.getState().addCookies(cookies);
    
            // 当state为301或者302说明登陆页面跳转了,登陆成功了
            if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY)
                    || (statuscode == HttpStatus.SC_MOVED_PERMANENTLY)
                    || (statuscode == HttpStatus.SC_SEE_OTHER)
                    || (statuscode == HttpStatus.SC_TEMPORARY_REDIRECT)) {
                // 读取新的 URL 地址
                Header header = login.getResponseHeader("location");
                // 释放连接
                login.releaseConnection();
                System.out.println("获取到跳转header>>>" + header);
                if (header != null) {
                    String newuri = header.getValue();
                    if ((newuri == null) || (newuri.equals("")))
                        newuri = "/";
                    GetMethod redirect = new GetMethod(newuri);
                    // 
                    redirect.setRequestHeader("Cookie", cookies.toString());
                    httpClient.executeMethod(redirect);
                    System.out.println("Redirect:"
                            + redirect.getStatusLine().toString());
                    redirect.releaseConnection();
    
                } else
                    System.out.println("Invalid redirect");
            } else {
                // 用户名和密码没有被提交,当登陆多次后需要验证码的时候会出现这种未提交情况
                System.out.println("用户没登陆");
                System.exit(1);
            }
    
        }
    
        public static void sendMsg() throws Exception {
            // 登录后发消息
            System.out.println("*************发消息***********");
    
            String posturl = "http://www.kaixin001.com/msg/post.php";
            PostMethod poster = new PostMethod(posturl);
    
            poster.addRequestHeader("Content-Type",
                    "application/x-www-form-urlencoded; charset=UTF-8");
            poster.setRequestHeader("Cookie", cookies.toString());
    
            NameValuePair uids = new NameValuePair("uids", "89600585");// 发送的好友对象的id,此处换成你的好友id
            NameValuePair content = new NameValuePair("content", "你好啊!");// 需要发送的信息的内容
            NameValuePair liteeditor_0 = new NameValuePair("liteeditor_0", "你好啊!");// 需要发送的信息的内容
            NameValuePair texttype = new NameValuePair("texttype", "plain");
            NameValuePair send_separate = new NameValuePair("send_separate", "0");
            NameValuePair service = new NameValuePair("service", "0");
            NameValuePair[] msg = { uids, content, texttype, send_separate, service,liteeditor_0 };
    
            poster.setRequestBody(msg);
            httpClient.executeMethod(poster);
    
            String result = poster.getResponseBodyAsString();
            System.out.println(result+"++++++++++++");
            //System.out.println(StreamOut(result, "iso8859-1"));
            int statuscode = poster.getStatusCode();
            System.out.println(statuscode + "-----------");
            if(statuscode == 301 || statuscode == 302){
                // 读取新的 URL 地址
                Header header = poster.getResponseHeader("location");
                System.out.println("获取到跳转header>>>" + header);
                if (header != null) {
                    String newuri = header.getValue();
                    if ((newuri == null) || (newuri.equals("")))
                        newuri = "/";
                    GetMethod redirect = new GetMethod(newuri);
                    // 
                    redirect.setRequestHeader("Cookie", cookies.toString());
                    httpClient.executeMethod(redirect);
                    System.out.println("Redirect:"
                            + redirect.getStatusLine().toString());
                    redirect.releaseConnection();
    
                } else
                    System.out.println("Invalid redirect");
            }
            
                poster.releaseConnection();
        }
    
        public static String StreamOut(InputStream txtis, String code)
                throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(txtis,
                    code));
            String tempbf;
            StringBuffer html = new StringBuffer(100);
            while ((tempbf = br.readLine()) != null) {
                html.append(tempbf + "\n");
            }
            return html.toString();
    
        }
    }
    复制代码

     

     

    5. 提交XML格式参数

    提交XML格式的参数很简单,仅仅是一个提交时候的ContentType问题,下面的例子演示从文件文件中读取XML信息并提交给服务器的过程,该过程可以用来测试Web服务。

    复制代码
    import java.io.File; 
    import java.io.FileInputStream; 
    import org.apache.commons.httpclient.HttpClient; 
    import org.apache.commons.httpclient.methods.EntityEnclosingMethod; 
    import org.apache.commons.httpclient.methods.PostMethod;
    /** 
     *用来演示提交XML格式数据的例子
    */
    public class PostXMLClient {
    
       public static void main(String[] args) throws Exception {
          File input = new File(“test.xml”);
          PostMethod post = new PostMethod(“http://localhost:8080/httpclient/xml.jsp”);
    
          // 设置请求的内容直接从文件中读取
          post.setRequestBody( new FileInputStream(input)); 
          if (input.length() < Integer.MAX_VALUE)
             post.setRequestContentLength(input.length());
          else
             post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED);
    
          // 指定请求内容的类型
          post.setRequestHeader( "Content-type" , "text/xml; charset=GBK" );
          HttpClient httpclient = new HttpClient();
          int result = httpclient.executeMethod(post);
          System.out.println( "Response status code: " + result);
          System.out.println( "Response body: " );
          System.out.println(post.getResponseBodyAsString()); 
          post.releaseConnection(); 
       } 
    }
    复制代码

     

     

    6. 访问启用认证的页面

    我们经常会碰到这样的页面,当访问它的时候会弹出一个浏览器的对话框要求输入用户名和密码后方可,这种用户认证的方式不同于我们在前面介绍的基于表单的用户身份验证。这是HTTP的认证策略,httpclient支持三种认证方式包括:基本、摘要以及NTLM认证。其中基本认证最简单、通用但也最不安全;摘要认证是在HTTP 1.1中加入的认证方式,而NTLM则是微软公司定义的而不是通用的规范,最新版本的NTLM是比摘要认证还要安全的一种方式。

    下面例子是从httpclient的CVS服务器中下载的,它简单演示如何访问一个认证保护的页面:

    复制代码
    import org.apache.commons.httpclient.HttpClient; 
    import org.apache.commons.httpclient.UsernamePasswordCredentials; 
    import org.apache.commons.httpclient.methods.GetMethod; 
    
    public class BasicAuthenticationExample { 
    
       public BasicAuthenticationExample() { 
       }
    
       public static void main(String[] args) throws Exception {
          HttpClient client = new HttpClient();
          client.getState().setCredentials( "www.verisign.com" , "realm" , new UsernamePasswordCredentials( "username" , "password" ) );
    
          GetMethod get = new GetMethod( "https://www.verisign.com/products/index.html" );
          get.setDoAuthentication( true );
          int status = client.executeMethod( get );
          System.out.println(status+ "\n" + get.getResponseBodyAsString());
          get.releaseConnection();
       } 
    }
    复制代码

     

     

    7. 多线程模式下使用

    多线程同时访问httpclient,例如同时从一个站点上下载多个文件。对于同一个HttpConnection同一个时间只能有一个线程访问,为了保证多线程工作环境下不产生冲突,httpclient使用了一个多线程连接管理器的类:MultiThreadedHttpConnectionManager,要使用这个类很简单,只需要在构造HttpClient实例的时候传入即可,代码如下:

    MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();

    HttpClient client = new HttpClient(connectionManager);

    以后尽管访问client实例即可。

     

    httpClient完整封装

    HttpInvoke.java:封装了HttpClient调度的必要参数设置,以及post,get等常用方法

    复制代码
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.commons.httpclient.*;
    import org.apache.commons.httpclient.auth.AuthScope;
    import org.apache.commons.httpclient.methods.PostMethod;
    import org.apache.commons.httpclient.methods.GetMethod;
    
    import java.util.Iterator;
    import java.util.Map;
    import java.net.SocketTimeoutException;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    
    public class HttpInvoker {
        private Log logger = LogFactory.getLog(HttpInvoker.class);
        private static HttpInvoker httpInvoker = new HttpInvoker();
        private HttpClient client = null;
        private String charset = "gbk";
        private int timeout = 10000;
        private boolean useProxy = false;
        private String proxyHost = null;
        private int proxyPort;
        private String proxyUsername = null;
        private String proxyPassword = null;
        private boolean initialized = false;
        
        public static HttpInvoker getInstance() {
            return httpInvoker;
        }
    
        private HttpInvoker() {
            client = new HttpClient(new MultiThreadedHttpConnectionManager());
            client.getParams().setParameter("http.protocol.content-charset", "gbk");
            client.getParams().setContentCharset("gbk");
            client.getParams().setSoTimeout(timeout);
        }
    
        public HttpInvoker(String charset, int timeout, boolean useProxy,
                           String proxyHost, int proxyPort, String proxyUsername,
                           String proxyPassword) {
            client = new HttpClient(new MultiThreadedHttpConnectionManager());
            if(charset != null && !charset.trim().equals("")) {
                this.charset = charset;
            }
            if(timeout > 0) {
                this.timeout = timeout;
            }
            client.getParams().setParameter("http.protocol.content-charset", charset);
            client.getParams().setContentCharset(charset);
            client.getParams().setSoTimeout(timeout);
            if(useProxy && proxyHost != null &&
                    !proxyHost.trim().equals("") && proxyPort > 0) {
                HostConfiguration hc = new HostConfiguration();
                hc.setProxy(proxyHost, proxyPort);
                client.setHostConfiguration(hc);
                if (proxyUsername != null && !proxyUsername.trim().equals("") &&
                        proxyPassword != null && !proxyPassword.trim().equals("")) {
                    client.getState().setProxyCredentials(AuthScope.ANY,
                        new UsernamePasswordCredentials(proxyUsername, proxyPassword));
                }
            }
            initialized = true;
            logger.debug("HttpInvoker初始化完成");
        }
    
        public synchronized void init() {
            if(charset != null && !charset.trim().equals("")) {
                client.getParams().setParameter("http.protocol.content-charset", charset);
                client.getParams().setContentCharset(charset);
            }
            if(timeout > 0) {
                client.getParams().setSoTimeout(timeout);
            }
            if(useProxy && proxyHost != null &&
                    !proxyHost.trim().equals("") && proxyPort > 0) {
                HostConfiguration hc = new HostConfiguration();
                hc.setProxy(proxyHost, proxyPort);
                client.setHostConfiguration(hc);
                if (proxyUsername != null && !proxyUsername.trim().equals("") &&
                        proxyPassword != null && !proxyPassword.trim().equals("")) {
                    client.getState().setProxyCredentials(AuthScope.ANY,
                        new UsernamePasswordCredentials(proxyUsername, proxyPassword));
                }
            }
            initialized = true;
            logger.debug("HttpInvoker初始化完成");
        }
    
        public String invoke(String url) throws Exception {
            return invoke(url, null, false);
        }
    
        public String invoke(String url, Map params, boolean isPost) throws Exception {
            logger.debug("HTTP调用[" + (isPost?"POST":"GET") + "][" + url + "][" + params + "]");
            HttpMethod httpMethod = null;
            String result = "";
            try {
                if(isPost && params != null && params.size() > 0) {
                    Iterator paramKeys = params.keySet().iterator();
                    httpMethod = new PostMethod(url);
                    NameValuePair[] form = new NameValuePair[params.size()];
                    int formIndex = 0;
                    while(paramKeys.hasNext()) {
                        String key = (String)paramKeys.next();
                        Object value = params.get(key);
                        if(value != null && value instanceof String && !value.equals("")) {
                            form[formIndex] = new NameValuePair(key, (String)value);
                            formIndex++;
                        } else if(value != null && value instanceof String[] &&
                                ((String[])value).length > 0) {
                            NameValuePair[] tempForm =
                                    new NameValuePair[form.length + ((String[])value).length - 1];
                            for(int i=0; i<formIndex; i++) {
                                tempForm[i] = form[i];
                            }
                            form = tempForm;
                            for(String v : (String[])value) {
                                form[formIndex] = new NameValuePair(key, (String)v);
                                formIndex++;
                            }
                        }
                    }
                    ((PostMethod)httpMethod).setRequestBody(form);
                } else {
                    if(params != null && params.size() > 0) {
                        Iterator paramKeys = params.keySet().iterator();
                        StringBuffer getUrl = new StringBuffer(url.trim());
                        if(url.trim().indexOf("?") > -1) {
                            if(url.trim().indexOf("?") < url.trim().length()-1 &&
                                    url.trim().indexOf("&")  < url.trim().length()-1) {
                                getUrl.append("&");
                            }
                        } else {
                            getUrl.append("?");
                        }
                        while(paramKeys.hasNext()) {
                            String key = (String)paramKeys.next();
                            Object value = params.get(key);
                            if(value != null && value instanceof String && !value.equals("")) {
                                getUrl.append(key).append("=").append(value).append("&");
                            } else if(value != null && value instanceof String[] &&
                                    ((String[])value).length > 0) {
                                for(String v : (String[])value) {
                                    getUrl.append(key).append("=").append(v).append("&");
                                }
                            }
                        }
                        if(getUrl.lastIndexOf("&") == getUrl.length()-1) {
                            httpMethod = new GetMethod(getUrl.substring(0, getUrl.length()-1));
                        } else {
                            httpMethod = new GetMethod(getUrl.toString());
                        }
                    } else {
                        httpMethod = new GetMethod(url);
                    }
                }
                client.executeMethod(httpMethod);
    //            result = httpMethod.getResponseBodyAsString();
                BufferedReader reader = new BufferedReader(new InputStreamReader(
                        httpMethod.getResponseBodyAsStream(),"ISO-8859-1"));
                String line = null;
                String html = null;
                while((line = reader.readLine()) != null){
                    if(html == null) {
                        html = "";
                    } else {
                        html += "\r\n";
                    }
                    html += line;
                }
                if(html != null) {
                    result = new String(html.getBytes("ISO-8859-1"), charset);
                }
            } catch (SocketTimeoutException e) {
                logger.error("连接超时[" + url + "]");
                throw e;
            } catch (java.net.ConnectException e) {
                logger.error("连接失败[" + url + "]");
                throw e;
            } catch (Exception e) {
                logger.error("连接时出现异常[" + url + "]");
                throw e;
            } finally {
                if (httpMethod != null) {
                    try {
                        httpMethod.releaseConnection();
                    } catch (Exception e) {
                        logger.error("释放网络连接失败[" + url + "]");
                        throw e;
                    }
                }
            }
    
            return result;
        }
    
        public void setCharset(String charset) {
            this.charset = charset;
        }
    
        public void setTimeout(int timeout) {
            this.timeout = timeout;
        }
    
        public void setProxyHost(String proxyHost) {
            this.proxyHost = proxyHost;
        }
    
        public void setProxyPort(int proxyPort) {
            this.proxyPort = proxyPort;
        }
    
        public void setProxyUsername(String proxyUsername) {
            this.proxyUsername = proxyUsername;
        }
    
        public void setProxyPassword(String proxyPassword) {
            this.proxyPassword = proxyPassword;
        }
    
        public void setUseProxy(boolean useProxy) {
            this.useProxy = useProxy;
        }
    
        public synchronized boolean isInitialized() {
            return initialized;
        }
    }
    复制代码

     

    http访问网络的代理ip和端口,还有使用用户及密码都可以在Spring容器中注入进来:

    复制代码
    <bean id="httpInvoker" class="HttpInvoker">
            <constructor-arg type="java.lang.String" value="gbk" /><!--useProxy-->
            <constructor-arg type="int" value="10000" /><!--useProxy-->
            <constructor-arg type="boolean" value="true" /><!--useProxy-->
            <!--代理地址 -->
            <constructor-arg type="java.lang.String" value="192.168.1.1" />
            <constructor-arg type="int" value="8080" />
            <constructor-arg type="java.lang.String" value="" /><!--用户名-->
            <constructor-arg type="java.lang.String" value="" /><!--密码-->
    </bean>
    复制代码

     

     

    使用方式:post

    Map<String,String> params = new HashMap<String,String>();
    params.put("check", check);
    String result = httpInvoker.invoke( "someURL", params, true);

    使用方式:get

    String content  = httpInvoker.invoke(url);

     

    参考资料:

    httpclient首页:    http://jakarta.apache.org/commons/httpclient/
    关于NTLM是如何工作:  http://davenport.sourceforge.net/ntlm.html


    --------------------------------------------

    HttpClient入门
    http://blog.csdn.net/ambitiontan/archive/2006/01/07/572644.aspx

    Jakarta Commons HttpClient 学习笔记
    http://blog.csdn.net/cxl34/archive/2005/01/19/259051.aspx

    Cookies,SSL,httpclient的多线程处理,HTTP方法
    http://blog.csdn.net/bjbs_270/archive/2004/11/05/168233.aspx

     

    原文地址:https://www.cnblogs.com/ITtangtang/p/3968093.html


    展开全文
  • Client当然是客户端程序,ORACLE 9I+PLSQL是服务器端程序。 但是日常管理你不可能每次都登录到服务器吧,Client就是可以让你不用登录服务器就可以远程管理的,那个PLSQL就是远程管理程序可以装在服务器,也可以装在...
  • 客户端使用200个线程往服务器端发送数据,每次数据量约100K. 发送的时候使用了多线程连接池管理器 ...private MultiThreadedHttpConnectionManager connectionManager = new ...


    客户端使用200个线程往服务器端发送数据,每次数据量约100K.

    发送的时候使用了多线程连接池管理器

    private MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
    private HttpClient httpClient = new HttpClient(connectionManager);
    
    
    httpClient.getHttpConnectionManager().getParams()
    .setDefaultMaxConnectionsPerHost(WORKER_COUNT * 2);
    httpClient.getHttpConnectionManager().getParams()
    .setMaxTotalConnections(WORKER_COUNT * 5);
    httpClient.getHttpConnectionManager().getParams().setSoTimeout(0);
    httpClient.getHttpConnectionManager().getParams()
    .setStaleCheckingEnabled(true);
    <span style="font-family: Arial, Helvetica, sans-serif;">// 使用DefaultHttpMethodRetryHandler是希望在发送失败后能够自动重新发送</span>
    <span style="font-family: Arial, Helvetica, sans-serif;">httpClient.getHttpConnectionManager().getParams()</span>
    .setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());

    结果在实际的运行过程中发现不少的异常,导致数据没有发送成功:

    [INFO ] 2014-08-31 13:00:35,804 -xxx.http.HttpMessageManager -430870 [pool-2-thread-126] INFO  xxx.http.HttpMessageManager  - io exception when send http.
     java.net.SocketException: Connection reset
            at java.net.SocketInputStream.read(SocketInputStream.java:168)
            at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
            at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
            at org.apache.commons.httpclient.HttpParser.readRawLine(Unknown Source)
            at org.apache.commons.httpclient.HttpParser.readLine(Unknown Source)
            at org.apache.commons.httpclient.HttpConnection.readLine(Unknown Source)
            at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.readLine(Unknown Source)
            at org.apache.commons.httpclient.HttpMethodBase.readStatusLine(Unknown Source)
            at org.apache.commons.httpclient.HttpMethodBase.readResponse(Unknown Source)
            at org.apache.commons.httpclient.HttpMethodBase.execute(Unknown Source)
            at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(Unknown Source)
            at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(Unknown Source)
            at org.apache.commons.httpclient.HttpClient.executeMethod(Unknown Source)
            at org.apache.commons.httpclient.HttpClient.executeMethod(Unknown Source)
            at xxx.http.HttpMessageManager$MessageSendWorker.sendHttp(HttpMessageManager.java:308)
            at xxx.http.HttpMessageManager$MessageSendWorker.run(HttpMessageManager.java:253)
            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
            at java.util.concurrent.FutureTask.run(FutureTask.java:138)
            at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
            at java.lang.Thread.run(Thread.java:662)
    [ERROR] 2014-08-31 13:00:35,805 - xxx.http.HttpMessageManager -430871 [pool-2-thread-126] ERROR xxx.http.HttpMessageManager  - send http fail after retry 3 times, url=http://10.10.10.10/metrics/put

    加粗部分的日志是我自己打印的,因为DefaultHttpMethodRetryHandler在发送失败时会重试3次。


    分析发现,通过netstat -an命令查看,客户端会出现几十个CLOSE_WAIT状态的socket连接,server端会出现一些FIN_WAIT2状态的连接,很明显server端主动发起了断连。查看server端的keepalive超时设置为15000毫秒,达到了此阈值时,就会强制关闭连接。


    server端断连是一个正常的操作,关键是http client端不是有重发机制吗?所以不应该最后没有发送成功呀


    http Client下 多个线程共享connet连接池,每次发送时从池中获取一个连接:


        public void executeMethod(final HttpMethod method) throws IOException, HttpException {
            if (method == null) {
                throw new IllegalArgumentException("Method may not be null");
            }
            // Link all parameter collections to form the hierarchy:
            // Global -> HttpClient -> HostConfiguration -> HttpMethod
            this.hostConfiguration.getParams().setDefaults(this.params);
            method.getParams().setDefaults(this.hostConfiguration.getParams());
            
            // Generate default request headers
            Collection defaults = (Collection)this.hostConfiguration.getParams().
                getParameter(HostParams.DEFAULT_HEADERS);
            if (defaults != null) {
                Iterator i = defaults.iterator();
                while (i.hasNext()) {
                    method.addRequestHeader((Header)i.next());
                }
            }
            
            try {
                int maxRedirects = this.params.getIntParameter(HttpClientParams.MAX_REDIRECTS, 100);
    
    
                for (int redirectCount = 0;;) {
    
    
                    // make sure the connection we have is appropriate
                    if (this.conn != null && !hostConfiguration.hostEquals(this.conn)) {
                        this.conn.setLocked(false);
                        this.conn.releaseConnection();
                        this.conn = null;
                    }
            
                    // get a connection, if we need one
                    if (this.conn == null) {
                        <strong>this.conn = connectionManager.getConnectionWithTimeout(
                            hostConfiguration,
                            this.params.getConnectionManagerTimeout() 
                        );
                        this.conn.setLocked(true);
                        if (this.params.isAuthenticationPreemptive()
                         || this.state.isAuthenticationPreemptive()) 
                        {
                            LOG.debug("Preemptively sending default basic credentials");
                            method.getHostAuthState().setPreemptive();
                            method.getHostAuthState().setAuthAttempted(true);
                            if (this.conn.isProxied() && !this.conn.isSecure()) {
                                method.getProxyAuthState().setPreemptive();
                                method.getProxyAuthState().setAuthAttempted(true);
                            }
                        }</strong>
                    }
                    authenticate(method);
                    <strong>executeWithRetry(method);</strong>
                    if (this.connectMethod != null) {
                        fakeResponse(method);
                        break;
                    }
                    
                    。。。。。
    
    
                } //end of retry loop
            } finally {
                if (this.conn != null) {
                    this.conn.setLocked(false);
                }
                // If the response has been fully processed, return the connection
                // to the pool.  Use this flag, rather than other tests (like
                // responseStream == null), as subclasses, might reset the stream,
                // for example, reading the entire response into a file and then
                // setting the file as the stream.
                if (
                    (releaseConnection || method.getResponseBodyAsStream() == null) 
                    && this.conn != null
                ) {
                    this.conn.releaseConnection();
                }
            }
    
    
        }


        private void executeWithRetry(final HttpMethod method) 
            throws IOException, HttpException {
            
            /** How many times did this transparently handle a recoverable exception? */
            int execCount = 0;
            // loop until the method is successfully processed, the retryHandler 
            // returns false or a non-recoverable exception is thrown
            try {
                while (true) {
                    execCount++;
                    try {
    
    
                        if (LOG.isTraceEnabled()) {
                            LOG.trace("Attempt number " + execCount + " to process request");
                        }
                        if (this.conn.getParams().isStaleCheckingEnabled()) {
                            this.conn.closeIfStale();
                        }
                        if (!this.conn.isOpen()) {
                            // this connection must be opened before it can be used
                            // This has nothing to do with opening a secure tunnel
                            this.conn.open();
                            if (this.conn.isProxied() && this.conn.isSecure() 
                            && !(method instanceof ConnectMethod)) {
                                // we need to create a secure tunnel before we can execute the real method
                                if (!executeConnect()) {
                                    // abort, the connect method failed
                                    return;
                                }
                            }
                        }
                        applyConnectionParams(method);                    
                        method.execute(state, this.conn);
                        break;
                    } catch (HttpException e) {
                        // filter out protocol exceptions which cannot be recovered from
                        throw e;
                    } catch (IOException e) {
                        LOG.debug("Closing the connection.");
                        this.conn.close();
                        。。。。
    <strong>                    // ========================================
                        HttpMethodRetryHandler handler = 
                            (HttpMethodRetryHandler)method.getParams().getParameter(
                                    HttpMethodParams.RETRY_HANDLER);</strong>
                        if (handler == null) {
                            handler = new DefaultHttpMethodRetryHandler();
                        }
                       <strong> if (!handler.retryMethod(method, e, execCount)) {</strong>
                            LOG.debug("Method retry handler returned false. "
                                    + "Automatic recovery will not be attempted");
                            throw e;
                        }
                        。。。。
                    }
                }
            } catch (IOException e) {
                if (this.conn.isOpen()) {
                    LOG.debug("Closing the connection.");
                    this.conn.close();
                }
                releaseConnection = true;
                throw e;
            } catch (RuntimeException e) {
                if (this.conn.isOpen()) {
                    LOG.debug("Closing the connection.");
                    this.conn.close();
                }
                releaseConnection = true;
                throw e;
            }
        }

        public boolean retryMethod(
            final HttpMethod method, 
            final IOException exception, 
            int executionCount) {
            if (method == null) {
                throw new IllegalArgumentException("HTTP method may not be null");
            }
            if (exception == null) {
                throw new IllegalArgumentException("Exception parameter may not be null");
            }
            // HttpMethod interface is the WORST thing ever done to HttpClient
            if (method instanceof HttpMethodBase) {
    <strong>            // 此处判断如果连接异常,则不重发
                if (((HttpMethodBase)method).isAborted()) {
                    return false;
                }</strong>
            }
            。。。。。
            return false;
        }

    一直以为连接异常时也会重发,当server端主动断开时,client会根据StaleCheckingEnabled的值检测连接是否正常,如果正常才发送,发送异常时会重发。今天才发现http client的重发机制也是有限制的,如果网络异常退出,就不会重发,而是直接抛出异常。


    解决办法:


    不适用httpclient的重发机制,自己搞一个:


    // 重试3次
    int retry = 0;
    do {
    try {
    int status = httpClient.executeMethod(postMethod);
    
    if (HttpStatus.SC_OK == status) {
    if (LOGGER.isDebugEnabled()) {
    LOGGER.debug("send http success, url=" + url
    + ", content=" + message);
    }
    }else {
    String rsp = HttpUtils
    .getInputStreamAsString(postMethod
    .getResponseBodyAsStream());
    LOGGER.error("send http fail, status is: " + status
    + ", response is: " + rsp);
    }
    return;
    } catch (HttpException e) {
    postMethod.abort();
    LOGGER.info("http exception when send http.", e);
    } catch (IOException e) {
    postMethod.abort();
    LOGGER.info("io exception when send http.", e);
    } finally {
    postMethod.releaseConnection();
    }
    LOGGER.info("send http fail, retry:" + retry);
    } while (++retry < 3);
    // 如果到了第3次还未发送成功,则记录日志
    LOGGER.error("send http fail after retry 3 times, url=" + url);
    
    
    




    展开全文
  • client.zip

    2013-12-01 20:28:08
    获取ios设备的mac地址,直接使用这个类就可以得到
  • 搜了一下网络上别人封装的HttpClient,大部分特别简单,有一些看起来比较高级,但是用起来都不怎么好用。调用关系不清楚,结构有点混乱。所以也就萌生了自己封装HttpClient工具类的想法。要做就做最好的,本工具类...

           搜了一下网络上别人封装的HttpClient,大部分特别简单,有一些看起来比较高级,但是用起来都不怎么好用。调用关系不清楚,结构有点混乱。所以也就萌生了自己封装HttpClient工具类的想法。要做就做最好的,本工具类支持插件式配置Header、插件式配置httpclient对象,这样就可以方便地自定义header信息、配置ssl、配置proxy等。


           是不是觉得说的有点悬乎了,那就先看看调用吧:

    	public static void testSimple() throws HttpProcessException{
    		String url = "http://www.oschina.net";
    		//简单调用
    		String resp = HttpClientUtil.send(url);
    		System.out.println("请求结果内容长度:"+ resp.length());
    	}
    	
    	public static void testOne() throws HttpProcessException{		
    		String url = "https://sso.tgb.com:8443/cas/login";
    		
    		//自定义HttpClient,设置超时、代理、ssl
    		//HttpClient client= HCB.custom().timeout(10000).proxy("127.0.0.1", 8087).ssl().build();//采用默认方式(绕过证书验证)
    		HttpClient client= HCB.custom().timeout(10000).ssl("D:\\keys\\wsriakey","tomcat").build();
    		
    		//设置header信息
    		Header[] headers=HttpHeader.custom().keepAlive("false").connection("close").contentType(Headers.APP_FORM_URLENCODED).build();
    		
    		//执行请求
    		String resp=HttpClientUtil.send(client, url, headers);
    		System.out.println("请求结果如下:");
    		System.out.println(resp);
    	}

           轻松配置了代理、自定义证书的ssl、以及各种header头信息,是不是觉得还凑合呢,那就继续看吧。


           写这个工具类时,抽象了一下所有的demo,最后封装了一个最基本的方法(拆分成了2个方法了),其所有参数列表有:HttpClient对象、url(必须有)、请求方式、请求参数parasMap、header数组、编码格式encoding。


           由于封装的是工具类,所以最好是无状态的,可以支持多线程的方式调用的,所以方法都是static类型的。这也是为什么要把HttpClient对象也是作为了一个参数传入而非成员变量了,而且这样也为扩展HttpClient的配置提供了便利。


           因为HTTP1.1规范中定义了6种HTTP方法:GET, HEAD, POST, PUT, DELETE, TRACE 和 OPTIONS,其实还有一个PATCH,这几个方法在HttpClient中都有一个对应的类:HttpGet,HttpHead,HttpPost,HttpPut,HttpDelete,HttpTrace、HttpOptions以及HttpPatch。所有的这些类均继承了HttpRequestBase超类,故可以作为参数使用(用枚举类作为参数,用另一个方法来创建具体的请求方法对象)。


           Header头信息也是作为一个重要的参数,在请求特定网站的时候需要设置不同的Header,而header又是比较繁杂的,所以这里也是作为了一个参数传入的,也是方便扩展。


           使用map来作为post方式传入参数是习惯使然,不做过多的解释。


           编码这个参数主要是为了为待提交的数据和反馈结果进行转码处理。


           简单说一下流程:

      1. 创建请求对象request;
      2. 为request设置header信息;
      3. 判断当前请求对象是否是HttpEntityEnclosingRequestBase的子类,如果是,则支持setEntity方法,来设置参数。
      4. 执行请求,并拿到结果(同步阻塞);
      5. 获取并解码请求结果实体;
      6. 关闭链接

           就是这么简单,具体来看看代码吧:

    	/**
    	 * 请求资源或服务,自定义client对象,传入请求参数,设置内容类型,并指定参数和返回数据的编码
    	 * 
    	 * @param client		client对象
    	 * @param url			资源地址
    	 * @param httpMethod	请求方法
    	 * @param parasMap		请求参数
    	 * @param headers		请求头信息
    	 * @param encoding		编码
    	 * @return				返回处理结果
    	 * @throws HttpProcessException 
    	 */
    	public static String send(HttpClient client, String url, HttpMethods httpMethod, Map<String,String>parasMap, 
    				Header[] headers, String encoding) throws HttpProcessException {
    		String body = "";
    		try {
    			//创建请求对象
    			HttpRequestBase request = getRequest(url, httpMethod);
    			
    			//设置header信息
    			request.setHeaders(headers);
    			
    			//判断是否支持设置entity(仅HttpPost、HttpPut、HttpPatch支持)
    			if(HttpEntityEnclosingRequestBase.class.isAssignableFrom(request.getClass())){
    				List<NameValuePair> nvps = new ArrayList<NameValuePair>();
    				
    				//检测url中是否存在参数
    				url = Utils.checkHasParas(url, nvps);
    				
    				//装填参数
    				Utils.map2List(nvps, parasMap);
    				
    				//设置参数到请求对象中
    				((HttpEntityEnclosingRequestBase)request).setEntity(new UrlEncodedFormEntity(nvps, encoding));
    				
    				logger.debug("请求地址:"+url);
    				if(nvps.size()>0){
    					logger.debug("请求参数:"+nvps.toString());
    				}
    			}else{
    				int idx = url.indexOf("?");
    				logger.debug("请求地址:"+url.substring(0, (idx>0 ? idx-1:url.length()-1)));
    				if(idx>0){
    					logger.debug("请求参数:"+url.substring(idx+1));
    				}
    			}
    			
    			//调用发送请求
    			body = execute(client, request, url, encoding);
    			
    		} catch (UnsupportedEncodingException e) {
    			throw new HttpProcessException(e);
    		}
    		return body;
    	}
    		
    	
    	/**
    	 * 请求资源或服务
    	 * 
    	 * @param client		client对象
    	 * @param request		请求对象
    	 * @param url			资源地址
    	 * @param parasMap		请求参数
    	 * @param encoding		编码
    	 * @return				返回处理结果
    	 * @throws HttpProcessException 
    	 */
    	private static String execute(HttpClient client, HttpRequestBase request,String url, String encoding) throws HttpProcessException {
    		String body = "";
    		HttpResponse response =null;
    		try {
    			
    			//执行请求操作,并拿到结果(同步阻塞)
    			response = client.execute(request);
    			
    			//获取结果实体
    			HttpEntity entity = response.getEntity();
    			
    			if (entity != null) {
    				//按指定编码转换结果实体为String类型
    				body = EntityUtils.toString(entity, encoding);
    				logger.debug(body);
    			}
    			EntityUtils.consume(entity);
    		} catch (ParseException | IOException e) {
    			throw new HttpProcessException(e);
    		} finally {
    			close(response);
    		}
    		
    		return body;
    	}

           第一个方法中,我们看到有HttpMethods类型的参数,在创建request对象时,用到了它。它是什么呢?其实只是一个枚举类:

    	/**
    	 * 枚举HttpMethods方法
    	 * 
    	 * @author arron
    	 * @date 2015年11月17日 下午4:45:59 
    	 * @version 1.0
    	 */
    	public enum HttpMethods{
    		
    		/**
    		 * 求获取Request-URI所标识的资源
    		 */
    		GET(0, "GET"), 
    		
    		/**
    		 * 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。
    		 * POST请求可能会导致新的资源的建立和/或已有资源的修改
    		 */
    		POST(1, "POST"),
    		
    		/**
    		 * 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。
    		 * 这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息
    		 * 只获取响应信息报头
    		 */
    		HEAD(2, "HEAD"),
    		
    		/**
    		 * 向指定资源位置上传其最新内容(全部更新,操作幂等)
    		 */
    		PUT	(3, "PUT"), 
    		
    		/**
    		 * 请求服务器删除Request-URI所标识的资源
    		 */
    		DELETE	(4, "DELETE"), 
    		
    		/**
    		 * 请求服务器回送收到的请求信息,主要用于测试或诊断
    		 */
    		TRACE(5, "TRACE"), 
    		
    		/**
    		 * 向指定资源位置上传其最新内容(部分更新,非幂等)
    		 */
    		PATCH	(6, "PATCH"),
    		
    		/**
    		 * 返回服务器针对特定资源所支持的HTTP请求方法。
    		 * 也可以利用向Web服务器发送'*'的请求来测试服务器的功能性
    		 */
    		OPTIONS	(7, "OPTIONS"), 
    		
    //		/**
    //		 * HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
    //		 */
    //		CONNECT(99, "CONNECT"),
    		;
    		
    		private int code;
    		private String name;
    		
    		private HttpMethods(int code, String name){
    			this.code = code;
    			this.name = name;
    		}
    		public String getName() {
    			return name;
    		}
    		public int getCode() {
    			return code;
    		}
    	}

    通过getRequest方法,来实例化对应方法的请求对象。

    	/**
    	 * 根据请求方法名,获取request对象
    	 * 
    	 * @param url					资源地址
    	 * @param method			请求方式
    	 * @return
    	 */
    	private static HttpRequestBase getRequest(String url, HttpMethods method) {
    		HttpRequestBase request = null;
    		switch (method.getCode()) {
    			case 0:// HttpGet
    				request = new HttpGet(url);
    				break;
    			case 1:// HttpPost
    				request = new HttpPost(url);
    				break;
    			case 2:// HttpHead
    				request = new HttpHead(url);
    				break;
    			case 3:// HttpPut
    				request = new HttpPut(url);
    				break;
    			case 4:// HttpDelete
    				request = new HttpDelete(url);
    				break;
    			case 5:// HttpTrace
    				request = new HttpTrace(url);
    				break;
    			case 6:// HttpPatch
    				request = new HttpPatch(url);
    				break;
    			case 7:// HttpOptions
    				request = new HttpOptions(url);
    				break;
    			default:
    				request = new HttpPost(url);
    				break;
    		}
    		return request;
    	}

    当然最后的关闭链接也是一个小方法:

    	/**
    	 * 尝试关闭response
    	 * 
    	 * @param resp				HttpResponse对象
    	 */
    	private static void close(HttpResponse resp) {
    		try {
    			if(resp == null) return;
    			//如果CloseableHttpResponse 是resp的父类,则支持关闭
    			if(CloseableHttpResponse.class.isAssignableFrom(resp.getClass())){
    				((CloseableHttpResponse)resp).close();
    			}
    		} catch (IOException e) {
    			logger.error(e);
    		}
    	}

           当然各种参数的组合方法也简单提供一下(为了节约空间,已去掉注释):

    	public static String send(String url) throws HttpProcessException {
    		return send(url, Charset.defaultCharset().name());
    	}
    	public static String send(String url, String encoding) throws HttpProcessException {
    		return send(url, new Header[]{},encoding);
    	}
    	public static String send(String url, Header[] headers) throws HttpProcessException {
    		return send(url, headers, Charset.defaultCharset().name());
    	}
    	public static String send(String url, Header[] headers, String encoding) throws HttpProcessException {
    		return send(url, new HashMap<String,String>(), headers, encoding);
    	}
    	public static String send(String url, Map<String,String>parasMap) throws HttpProcessException {
    		return send(url, parasMap, Charset.defaultCharset().name());
    	}
    	public static String send(String url, Map<String,String>parasMap, String encoding) throws HttpProcessException {
    		return send(url, parasMap, new Header[]{}, encoding);
    	}
    	public static String send(String url, Map<String,String>parasMap, Header[] headers) throws HttpProcessException {
    		return send(url, parasMap, headers, Charset.defaultCharset().name());
    	}
    	public static String send(String url, Map<String,String>parasMap, Header[] headers, String encoding) throws HttpProcessException {
    		return send(url, HttpMethods.POST, parasMap, headers, encoding);
    	}	
    	public static String send(String url, HttpMethods httpMethod) throws HttpProcessException {
    		return send(url, httpMethod, Charset.defaultCharset().name());
    	}
    	public static String send(String url, HttpMethods httpMethod, String encoding) throws HttpProcessException {
    		return send(url, httpMethod, new Header[]{},encoding);
    	}
    	public static String send(String url, HttpMethods httpMethod, Header[] headers) throws HttpProcessException {
    		return send(url, httpMethod, headers, Charset.defaultCharset().name());
    	}
    	public static String send(String url, HttpMethods httpMethod, Header[] headers, String encoding) throws HttpProcessException {
    		return send(url, httpMethod, new HashMap<String, String>(), headers, encoding);
    	}
    	public static String send(String url, HttpMethods httpMethod, Map<String,String>parasMap) throws HttpProcessException {
    		return send(url, httpMethod, parasMap, Charset.defaultCharset().name());
    	}
    	public static String send(String url, HttpMethods httpMethod, Map<String,String>parasMap, String encoding) throws HttpProcessException {
    		return send(url, httpMethod, parasMap, new Header[]{}, encoding);
    	}
    	public static String send(String url, HttpMethods httpMethod, Map<String,String>parasMap, Header[] headers) throws HttpProcessException {
    		return send(url, httpMethod, parasMap, headers, Charset.defaultCharset().name());
    	}	
    	public static String send(String url, HttpMethods httpMethod, Map<String,String>parasMap, Header[] headers, String encoding) throws HttpProcessException {
    		return send(create(url), url, httpMethod, parasMap, headers, encoding);
    	}
    	
    	public static String send(HttpClient client, String url) throws HttpProcessException {
    		return send(client, url, Charset.defaultCharset().name());
    	}
    	public static String send(HttpClient client, String url, String encoding) throws HttpProcessException {
    		return send(client, url, new Header[]{}, encoding);
    	}
    	public static String send(HttpClient client, String url, Header[] headers) throws HttpProcessException {
    		return send(client, url, headers, Charset.defaultCharset().name());
    	}
    	public static String send(HttpClient client, String url, Header[] headers, String encoding) throws HttpProcessException {
    		return send(client, url, new HashMap<String, String>(), headers, encoding);
    	}
    	public static String send(HttpClient client, String url, Map<String,String>parasMap) throws HttpProcessException {
    		return send(client, url, parasMap, Charset.defaultCharset().name());
    	}
    	public static String send(HttpClient client, String url, Map<String,String>parasMap, String encoding) throws HttpProcessException {
    		return send(client, url, parasMap, new Header[]{}, encoding);
    	}
    	public static String send(HttpClient client, String url, Map<String,String>parasMap, Header[] headers) throws HttpProcessException {
    		return send(client, url, parasMap, headers, Charset.defaultCharset().name());
    	}
    	public static String send(HttpClient client, String url, Map<String,String>parasMap,Header[] headers,String encoding) throws HttpProcessException {
    		return send(client, url, HttpMethods.POST, parasMap, headers, encoding);
    	}
    	public static String send(HttpClient client, String url, HttpMethods httpMethod) throws HttpProcessException {
    		return send(client, url, httpMethod, Charset.defaultCharset().name());
    	}
    	public static String send(HttpClient client, String url, HttpMethods httpMethod, String encoding) throws HttpProcessException {
    		return send(client, url, httpMethod, new Header[]{}, encoding);
    	}
    	public static String send(HttpClient client, String url, HttpMethods httpMethod, Header[] headers) throws HttpProcessException {
    		return send(client, url, httpMethod, headers, Charset.defaultCharset().name());
    	}
    	public static String send(HttpClient client, String url, HttpMethods httpMethod, Header[] headers, String encoding) throws HttpProcessException {
    		return send(client, url, httpMethod, new HashMap<String, String>(), headers, encoding);
    	}
    	public static String send(HttpClient client, String url, HttpMethods httpMethod, Map<String,String>parasMap) throws HttpProcessException {
    		return send(client, url, httpMethod, parasMap, Charset.defaultCharset().name());
    	}
    	public static String send(HttpClient client, String url, HttpMethods httpMethod, Map<String,String>parasMap, String encoding) throws HttpProcessException {
    		return send(client, url, httpMethod, parasMap, new Header[]{}, encoding);
    	}
    	public static String send(HttpClient client, String url, HttpMethods httpMethod, Map<String,String>parasMap, Header[] headers) throws HttpProcessException {
    		return send(client, url, httpMethod, parasMap, headers, Charset.defaultCharset().name());
    	}

           可以看到上面这一堆方法,其实主要分成2类,一类是传入client对象的,一组是没有传入的。也就是说该工具类提供了一种默认的client对象。这个将会在下一篇文章会有补充。


           当然,为了方便操作,还是提供了get、post、put、patch、delete、head、options、trace等方法,由于推荐使用send方法,所以这几个方法只是做了一个简单的调用:

    	public static String get(String url, Header[] headers,String encoding) throws HttpProcessException {
    		return get(create(url), url, headers, encoding);
    	}	
    	public static String get(HttpClient client, String url, Header[] headers,String encoding) throws HttpProcessException {
    		return send(client, url, HttpMethods.GET, headers, encoding);
    	}
    	
    	public static String post(String url, Map<String,String>parasMap,Header[] headers,String encoding) throws HttpProcessException {
    		return post(create(url), url, parasMap, headers, encoding);
    	}
    	public static String post(HttpClient client, String url, Map<String,String>parasMap,Header[] headers,String encoding) throws HttpProcessException {
    		return send(client, url, HttpMethods.POST, parasMap, headers, encoding);
    	}
    	
    	public static String put(String url, Map<String,String>parasMap,Header[] headers,String encoding) throws HttpProcessException {
    		return put(create(url), url, parasMap, headers, encoding);
    	}
    	public static String put(HttpClient client, String url, Map<String,String>parasMap,Header[] headers,String encoding) throws HttpProcessException {
    		return send(client, url, HttpMethods.PUT, parasMap, headers, encoding);
    	}
    	
    	public static String delete(String url, Header[] headers,String encoding) throws HttpProcessException {
    		return delete(create(url), url, headers, encoding);
    	}
    	public static String delete(HttpClient client, String url, Header[] headers,String encoding) throws HttpProcessException {
    		return send(client, url, HttpMethods.DELETE, headers, encoding);
    	}
    	
    	public static String patch(String url, Map<String,String>parasMap,Header[] headers,String encoding) throws HttpProcessException {
    		return patch(create(url), url, parasMap, headers, encoding);
    	}
    	public static String patch(HttpClient client, String url, Map<String,String>parasMap, Header[] headers,String encoding) throws HttpProcessException {
    		return send(client, url, HttpMethods.PATCH, parasMap, headers, encoding);
    	}
    	
    	public static String head(String url, Header[] headers,String encoding) throws HttpProcessException {
    		return head(create(url), url, headers, encoding);
    	}
    	public static String head(HttpClient client, String url, Header[] headers,String encoding) throws HttpProcessException {
    		return send(client, url, HttpMethods.HEAD, headers, encoding);
    	}
    	
    	public static String options(String url, Header[] headers,String encoding) throws HttpProcessException {
    		return options(create(url), url, headers, encoding);
    	}
    	public static String options(HttpClient client, String url, Header[] headers,String encoding) throws HttpProcessException {
    		return send(client, url, HttpMethods.OPTIONS, headers, encoding);
    	}
    	
    	public static String trace(String url, Header[] headers,String encoding) throws HttpProcessException {
    		return trace(create(url), url, headers, encoding);
    	}
    	public static String trace(HttpClient client, String url, Header[] headers,String encoding) throws HttpProcessException {
    		return send(client, url, HttpMethods.TRACE, headers, encoding);
    	}

           差点忘记了,最后还有一个简单的通用工具类

    /** 
     * 
     * @author arron
     * @date 2015年11月10日 下午12:49:26 
     * @version 1.0 
     */
    public class Utils {
    
    	/**
    	 * 检测url是否含有参数,如果有,则把参数加到参数列表中
    	 * 
    	 * @param url					资源地址
    	 * @param nvps				参数列表
    	 * @return	返回去掉参数的url
    	 */
    	public static String checkHasParas(String url, List<NameValuePair> nvps) {
    		// 检测url中是否存在参数
    		if (url.contains("?") && url.indexOf("?") < url.indexOf("=")) {
    			Map<String, String> map = buildParas(url.substring(url
    					.indexOf("?") + 1));
    			map2List(nvps, map);
    			url = url.substring(0, url.indexOf("?"));
    		}
    		return url;
    	}
    
    	/**
    	 * 参数转换,将map中的参数,转到参数列表中
    	 * 
    	 * @param nvps				参数列表
    	 * @param map				参数列表(map)
    	 */
    	public static void map2List(List<NameValuePair> nvps, Map<String, String> map) {
    		if(map==null) return;
    		// 拼接参数
    		for (Entry<String, String> entry : map.entrySet()) {
    			nvps.add(new BasicNameValuePair(entry.getKey(), entry
    					.getValue()));
    		}
    	}
    	
    	
    	/**
    	 * 生成参数
    	 * 参数格式“k1=v1&k2=v2”
    	 * 
    	 * @param paras				参数列表
    	 * @return						返回参数列表(map)
    	 */
    	public static Map<String,String> buildParas(String paras){
    		String[] p = paras.split("&");
    		String[][] ps = new String[p.length][2];
    		int pos = 0;
    		for (int i = 0; i < p.length; i++) {
    			pos = p[i].indexOf("=");
    			ps[i][0]=p[i].substring(0,pos);
    			ps[i][1]=p[i].substring(pos+1);
    			pos = 0;
    		}
    		return buildParas(ps);
    	}
    	
    	/**
    	 * 生成参数
    	 * 参数类型:{{"k1","v1"},{"k2","v2"}}
    	 * 
    	 * @param paras 				参数列表
    	 * @return						返回参数列表(map)
    	 */
    	public static Map<String,String> buildParas(String[][] paras){
    		// 创建参数队列    
    		Map<String,String> map = new HashMap<String, String>();
    		for (String[] para: paras) {
    			map.put(para[0], para[1]);
    		}
    		return map;
    	}
    	
    }

           简单的封装就是这样了。


           由于HttpClient和Header都作为参数传入,所以也可以进行扩展,比如代理、ssl等都是对HttpClient进行配置的,下面的文章就分别分享一下如何插件式配置HttpClient以及Header。敬请期待。

           代码已上传https://github.com/Arronlong/httpclientUtil

           httpclientUtil (QQ交流群:548452686 httpclientUtil交流

    展开全文
  • HttpClient

    万次阅读 2019-03-30 23:25:46
    HttpClient 入门
  • CLIENT.zip

    2017-01-03 23:44:47
    这里上传上网络调试调试工具:http://download.csdn.net/detail/chengdong1314/9723958 UDP数据传输的源代码:http://download.csdn.net/detail/chengdong1314/9726724 我编写出这个程序的文档:... ...
  • HttpClient详细使用示例

    万次阅读 多人点赞 2018-07-14 12:11:04
    HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中...HttpClient 是 Apache Jakarta Common 下的子项目,用...
  • Client-go之Informer机制初探 启航 本篇将开始我的源码剖析之路,先会讲client-go中的一些经典的机制和代码,然后讲一些我是用client-go中的一些小示例。最后开始读k8s scheduler源码。 背景 在k8s系统中,组件之间...
  • 概述: 1: 作用: 对测类,方法,函数进行测试。 2: 单元测试是测试的最小单位 3: 由于django的特殊性,通过接口测试单元。因为django中的每个单元都是在类视图中。 4: 单元测试的好处: 消除低级错误 ...
  • MQTT C Client实现消息推送(入门指南)

    万次阅读 多人点赞 2017-05-01 14:26:25
    MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,通过MQTT协议,目前已经扩展出了数十个MQTT服务器端程序,可以通过PHP,JAVA,Python,C,C#等系统语言来向MQTT发送...
  • 今天在电脑上安装了Mysql 8.0.11,然后又屁颠屁颠地安装了Navicat for MySQL,打开Navicat准备链接数据库的时候出现了如下提示: 上网搜索解决方案,网上说出现这种情况的原因是:mysql8 之前的版本中加密规则是...
  • client-go的使用及源码分析

    万次阅读 2017-12-16 20:21:12
    本文个人博客地址:http://www.huweihuang.com/article/source-analysis/client-go-source-analysis/...​ client-go是一个调用kubernetes集群资源对象API的客户端,即通过client-go实现对kubernetes集群中资源对象(包
  • 解决方法: 在pom.xml中加入或者父pom.xml中加入 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>... ...
  • ElasticSearch Client详解

    万次阅读 2018-10-19 21:06:48
       本文将重点探讨ElasticSearch Client的相关知识,重点关注TransportClient与Rest Client。Elasticsearch client 是我们进入ElasticSearch的大门。 1、概述    本节描述Elasticsearch提供的Java AP...
  • 转载请注明出处:java中提交argo工作流 背景 argo是一个建立在k8s框架之上的工作流调度工具。 详见 工作流workflow任务调度工具argo 需求是通过api来进行argo的调度脚本提交,不通过shell的手动提交方式。...
  • java实现websocket client

    千次下载 热门讨论 2013-11-08 17:47:12
    java_websocket.jar最新jar包 可用java实现websocket客户端,使用demo: https://github.com/TooTallNate/Java-WebSocket/blob/master/src/main/example/ExampleClient.java
  • Eureka入口之DiscoveryClient

    万次阅读 2018-08-19 18:54:59
    首先我们用EurekaClient 就必须用到图上的两个注解之一。这两个注解有什么关系呢? 两个注解 这边很明显的 EnableEurekaClient 注解里面包含了EnableDiscoveryClient注解 其他的注解和EnableDiscoveryClient 中...

空空如也

1 2 3 4 5 ... 20
收藏数 1,790,630
精华内容 716,252
关键字:

client