zoukankan      html  css  js  c++  java
  • 第一章 HttpClient的使用

    1、http协议(这一块儿有时间的话会做记录)

    2、常用的两种RPC方式

    • 基于http协议:HttpClient和JDK自己的Http操作类
    • 基于TCP或UDP协议:mina2和netty(这一部分以后有时间做记录)

    3、HttpClient工具类的编写(只列出了两个最常用的方法get和post)

    使用场合:我们可以在网页发送get或post请求去访问服务器server1,那我们在Java程序中想要模拟网页向服务器server1发送get和post请求的时候怎么办?--用HttpClient

    版本:httpClient4.2.6(jar或者maven坐标自己加上)

    maven坐标:

    1 <dependency>
    2     <groupId>org.apache.httpcomponents</groupId>
    3     <artifactId>httpclient</artifactId>
    4     <version>4.2.6</version>
    5 </dependency>
    View Code

    代码实现(两个类):

    MyX509TrustManager(自定义的信任管理器) 

     1 package com.util;
     2 
     3 import java.security.cert.CertificateException;
     4 import java.security.cert.X509Certificate;
     5 
     6 import javax.net.ssl.X509TrustManager;
     7 
     8 /**
     9  * 自定义的信任管理器
    10  */
    11 public class MyX509TrustManager implements X509TrustManager {
    12     /**
    13      * 检查客户端证书,若不信任,抛出异常
    14      */
    15     public void checkClientTrusted(X509Certificate[] arg0, String arg1)
    16             throws CertificateException {
    17     }
    18     /**
    19      * 检查服务端证书,若不信任,抛出异常,反之,若不抛出异常,则表示信任(所以,空方法代表信任所有的服务端证书)
    20      */
    21     public void checkServerTrusted(X509Certificate[] arg0, String arg1)
    22             throws CertificateException {
    23     }
    24     /**
    25      * 返回受信任的X509证书数组
    26      */
    27     public X509Certificate[] getAcceptedIssuers() {
    28         return null;
    29     }
    30 }
    View Code

     HttpClientUtil:

      1 package com.util;
      2 
      3 import java.io.IOException;
      4 import java.security.KeyManagementException;
      5 import java.security.NoSuchAlgorithmException;
      6 import java.security.NoSuchProviderException;
      7 import java.security.SecureRandom;
      8 import java.util.ArrayList;
      9 import java.util.List;
     10 import java.util.Map;
     11 import java.util.Properties;
     12 import java.util.Set;
     13 
     14 import javax.net.ssl.SSLContext;
     15 import javax.net.ssl.TrustManager;
     16 
     17 import org.apache.commons.collections4.MapUtils;
     18 import org.apache.http.HttpEntity;
     19 import org.apache.http.HttpResponse;
     20 import org.apache.http.HttpStatus;
     21 import org.apache.http.HttpVersion;
     22 import org.apache.http.NameValuePair;
     23 import org.apache.http.StatusLine;
     24 import org.apache.http.client.ClientProtocolException;
     25 import org.apache.http.client.HttpClient;
     26 import org.apache.http.client.entity.UrlEncodedFormEntity;
     27 import org.apache.http.client.methods.HttpGet;
     28 import org.apache.http.client.methods.HttpPost;
     29 import org.apache.http.client.utils.URLEncodedUtils;
     30 import org.apache.http.conn.scheme.PlainSocketFactory;
     31 import org.apache.http.conn.scheme.Scheme;
     32 import org.apache.http.conn.scheme.SchemeRegistry;
     33 import org.apache.http.conn.ssl.SSLSocketFactory;
     34 import org.apache.http.impl.client.DefaultHttpClient;
     35 import org.apache.http.impl.conn.PoolingClientConnectionManager;
     36 import org.apache.http.message.BasicNameValuePair;
     37 import org.apache.http.params.BasicHttpParams;
     38 import org.apache.http.params.CoreConnectionPNames;
     39 import org.apache.http.params.CoreProtocolPNames;
     40 import org.apache.http.params.HttpParams;
     41 import org.apache.http.util.EntityUtils;
     42 
     43 /**
     44  * 对HTTPClient的封装
     45  */
     46 public class HttpClientUtil {
     47 
     48     private static final String ENCODING = "UTF-8";
     49 
     50     private static HttpClient client = null;
     51     private static SchemeRegistry schemeRegistry;        //协议控制
     52     private static PoolingClientConnectionManager ccm;  //HttpClient连接池(多连接的线程安全的管理器)
     53 
     54     static {
     55         try {
     56             /*
     57              * 与https请求相关的操作
     58              */
     59             SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE");
     60             sslContext.init(null, new TrustManager[]{new MyX509TrustManager()}, new SecureRandom());
     61             SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext);
     62             /*
     63              * 定义访问协议
     64              */
     65             schemeRegistry = new SchemeRegistry();
     66             schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));//http
     67             schemeRegistry.register(new Scheme("https", 443, socketFactory));//https
     68         } catch (NoSuchAlgorithmException e) {
     69             e.printStackTrace();
     70         } catch (NoSuchProviderException e) {
     71             e.printStackTrace();
     72         } catch (KeyManagementException e) {
     73             e.printStackTrace();
     74         }
     75         
     76         Properties props = FileUtil.loadProps("http.properties");//加载属性文件
     77         
     78         // 连接池管理
     79         ccm = new PoolingClientConnectionManager(schemeRegistry);
     80         ccm.setDefaultMaxPerRoute(FileUtil.getInt(props, "httpclient.max.conn.per.route", 20));//每个路由的最大连接数
     81         ccm.setMaxTotal(FileUtil.getInt(props, "httpclient.max.conn.total", 400));//最大总连接数
     82 
     83         HttpParams httpParams = new BasicHttpParams();
     84         httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, FileUtil.getInt(props, "httpclient.max.conn.timeout", 1000));//连接超时时间(ms)
     85         httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, FileUtil.getInt(props, "httpclient.max.socket.timeout", 2000));//操作超时时间(ms)
     86         httpParams.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1);//设置http1.1或http1.0
     87 
     88         client = new DefaultHttpClient(ccm, httpParams);//一个客户端就有一个连接池
     89     }
     90 
     91     /**
     92      * get请求
     93      * @param url       请求URL
     94      * @param paramMap    请求参数
     95      * @param headerMap    请求头信息
     96      */
     97     public static String get(String url,
     98                              Map<String, String> paramMap, 
     99                              Map<String, String> headerMap) throws ClientProtocolException, 
    100                                                                     IOException {
    101         /*
    102          * 拼接URL与参数
    103          */
    104         if (MapUtils.isNotEmpty(paramMap)) {
    105             List<NameValuePair> params = new ArrayList<NameValuePair>();
    106             for (String key : paramMap.keySet()) {
    107                 params.add(new BasicNameValuePair(key, paramMap.get(key)));
    108             }
    109             String queryString = URLEncodedUtils.format(params,ENCODING);
    110             if (url.indexOf("?") > -1) {//存在?,表示这时的URL已经带参数了
    111                 url += "&" + queryString;
    112             } else {
    113                 url += "?" + queryString;
    114             }
    115         }
    116 
    117         HttpGet httpGet = new HttpGet(url);
    118 
    119         /*
    120          * 设置头信息
    121          */
    122         if (MapUtils.isNotEmpty(headerMap)) {
    123             Set<String> keySet = headerMap.keySet();
    124             for (String key : keySet) {
    125                 httpGet.addHeader(key, headerMap.get(key));
    126             }
    127         }
    128 
    129         String result = "";
    130         
    131         HttpResponse response = client.execute(httpGet);    //发出get请求
    132         StatusLine status = response.getStatusLine();        //获取返回的状态码
    133         HttpEntity entity = response.getEntity();            //获取返回的响应内容
    134         if (status.getStatusCode() == HttpStatus.SC_OK) {    //200
    135             result = EntityUtils.toString(entity, ENCODING);
    136         } 
    137         
    138         httpGet.abort();//中止请求,连接被释放回连接池
    139         return result;
    140     }
    141 
    142     /**
    143      * post请求
    144      * @param url        //请求URL
    145      * @param paramMap    //请求参数
    146      * @param headerMap    //请求头信息
    147      */
    148     public static String post(String url,
    149                               Map<String, String> paramMap, 
    150                               Map<String, String> headerMap) throws ClientProtocolException, 
    151                                                                       IOException {
    152         HttpPost httpPost = new HttpPost(url);
    153         /*
    154          * 处理参数
    155          */
    156         List<NameValuePair> params = new ArrayList<NameValuePair>();
    157         if (MapUtils.isNotEmpty(paramMap)) {
    158             Set<String> keySet = paramMap.keySet();
    159             for (String key : keySet) {
    160                 params.add(new BasicNameValuePair(key, paramMap.get(key)));
    161             }
    162         }
    163 
    164         /*
    165          * 设置头信息
    166          */
    167         if (MapUtils.isNotEmpty(headerMap)) {
    168             Set<String> keySet = headerMap.keySet();
    169             for (String key : keySet) {
    170                 httpPost.addHeader(key, headerMap.get(key));
    171             }
    172         }
    173 
    174         String result = "";
    175         
    176         httpPost.setEntity(new UrlEncodedFormEntity(params, ENCODING));//设置参数
    177         HttpResponse response = client.execute(httpPost);               //发出post请求
    178         StatusLine status = response.getStatusLine();                   //获取返回的状态码
    179         HttpEntity entity = response.getEntity();                       //获取响应内容
    180         if (status.getStatusCode() == HttpStatus.SC_OK) {
    181             result = EntityUtils.toString(entity, ENCODING);
    182         }
    183         
    184         httpPost.abort();//中止请求,连接被释放回连接池
    185         return result;
    186     }
    187 
    188     /**
    189      * 测试
    190      */
    191     public static void main(String[] args) {
    192         try {
    193             System.out.println(HttpClientUtil.get("https://www.baidu.com/", null, null));
    194             //System.out.println(HttpClientUtil.post("http://www.cppblog.com/iuranus/archive/2010/07/04/119311.html", null, null));
    195         } catch (ClientProtocolException e) {
    196             e.printStackTrace();
    197         } catch (IOException e) {
    198             e.printStackTrace();
    199         }
    200     }
    201 }
    View Code

    在该代码中,还有两个部分:一个属性文件http.properties和一个文件操作类FileUtil。这两部分,请查看下边的这个链接:

    http://www.cnblogs.com/java-zhao/p/5098813.html

    注意:

    • 我们发起的请求可以使http的,也可以是https(相当于http+SSL/TLS+数字证书的组合,是一种安全协议)的,对于https相关的请求而言,我们需要编写一些代码,来做特殊的处理。一般而言,处理https请求有两种方法:

      1)将https服务器端的安全证书导入到客户端的TrustStore文件中去,具体的原理见"《微信公众平台应用开发(方法、技巧与案例)》第5章"或者去查看柳峰的博客

        2)实现自定义的信任管理器(eg.MyX509TrustManager),需要实现X509TrustManager接口,并实现其中的三个方法。注意:这个类的注释一定要看

        3)注意http大多数时候用的是8080端口而不是80

            第一种方法需要手工导入证书,很费事;第二种方法十分灵活

    • 对于HttpClientUtil中,每一块做什么查看注释,这里:解释httpclient.max.conn.per.route(每个路由的最大连接数):这里路由的概念可以理解为"运行环境机器到目标机器"的一条线路。举例来说,我们使用HttpClient的实现来分别请求 www.baidu.com 的资源和 www.bing.com 的资源那么他就会产生两个route(路由),根据如上设置为20,就可以为上边两条route分别设置最大20个并发连接数。
    • 假如只有HttpClientUtil使用MyX509TrustManager,我们也可以将MyX509TrustManager作为HttpClientUtil的一个内部类,代码如下:
    •   1 package com.util;
        2 
        3 import java.io.IOException;
        4 import java.security.KeyManagementException;
        5 import java.security.NoSuchAlgorithmException;
        6 import java.security.NoSuchProviderException;
        7 import java.security.SecureRandom;
        8 import java.security.cert.CertificateException;
        9 import java.security.cert.X509Certificate;
       10 import java.util.ArrayList;
       11 import java.util.List;
       12 import java.util.Map;
       13 import java.util.Properties;
       14 import java.util.Set;
       15 
       16 import javax.net.ssl.SSLContext;
       17 import javax.net.ssl.TrustManager;
       18 import javax.net.ssl.X509TrustManager;
       19 
       20 import org.apache.commons.collections4.MapUtils;
       21 import org.apache.http.HttpEntity;
       22 import org.apache.http.HttpResponse;
       23 import org.apache.http.HttpStatus;
       24 import org.apache.http.HttpVersion;
       25 import org.apache.http.NameValuePair;
       26 import org.apache.http.StatusLine;
       27 import org.apache.http.client.ClientProtocolException;
       28 import org.apache.http.client.HttpClient;
       29 import org.apache.http.client.entity.UrlEncodedFormEntity;
       30 import org.apache.http.client.methods.HttpGet;
       31 import org.apache.http.client.methods.HttpPost;
       32 import org.apache.http.client.utils.URLEncodedUtils;
       33 import org.apache.http.conn.scheme.PlainSocketFactory;
       34 import org.apache.http.conn.scheme.Scheme;
       35 import org.apache.http.conn.scheme.SchemeRegistry;
       36 import org.apache.http.conn.ssl.SSLSocketFactory;
       37 import org.apache.http.impl.client.DefaultHttpClient;
       38 import org.apache.http.impl.conn.PoolingClientConnectionManager;
       39 import org.apache.http.message.BasicNameValuePair;
       40 import org.apache.http.params.BasicHttpParams;
       41 import org.apache.http.params.CoreConnectionPNames;
       42 import org.apache.http.params.CoreProtocolPNames;
       43 import org.apache.http.params.HttpParams;
       44 import org.apache.http.util.EntityUtils;
       45 
       46 /**
       47  * 对HTTPClient的封装
       48  */
       49 public class HttpClientUtilWithMyX509TrustMananer {
       50 
       51     private static final String ENCODING = "UTF-8";
       52 
       53     private static HttpClient client = null;
       54     private static SchemeRegistry schemeRegistry; // 协议控制
       55     private static PoolingClientConnectionManager ccm; // HttpClient连接池(多连接的线程安全的管理器)
       56 
       57     static {
       58         try {
       59             /*
       60              * 与https请求相关的操作
       61              */
       62             SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
       63             sslContext.init(null,
       64                             new TrustManager[] { getMyX509TrustManager() },
       65                             new SecureRandom());
       66             SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext);
       67             /*
       68              * 定义访问协议
       69              */
       70             schemeRegistry = new SchemeRegistry();
       71             schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));// http
       72             schemeRegistry.register(new Scheme("https", 443, socketFactory));// https
       73         } catch (NoSuchAlgorithmException e) {
       74             e.printStackTrace();
       75         } catch (NoSuchProviderException e) {
       76             e.printStackTrace();
       77         } catch (KeyManagementException e) {
       78             e.printStackTrace();
       79         }
       80 
       81         Properties props = FileUtil.loadProps("http.properties");// 加载属性文件
       82 
       83         // 连接池管理
       84         ccm = new PoolingClientConnectionManager(schemeRegistry);
       85         ccm.setDefaultMaxPerRoute(FileUtil.getInt(props,"httpclient.max.conn.per.route", 20));// 每个路由的最大连接数
       86         ccm.setMaxTotal(FileUtil.getInt(props, "httpclient.max.conn.total", 400));// 最大总连接数
       87 
       88         HttpParams httpParams = new BasicHttpParams();
       89         httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,FileUtil.getInt(props, "httpclient.max.conn.timeout", 1000));// 连接超时时间(ms)
       90         httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT,FileUtil.getInt(props, "httpclient.max.socket.timeout", 2000));// 操作超时时间(ms)
       91         httpParams.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1);// 设置http1.1或http1.0
       92 
       93         client = new DefaultHttpClient(ccm, httpParams);// 一个客户端就有一个连接池
       94     }
       95 
       96     /**
       97      * get请求
       98      * @param url       请求URL
       99      * @param paramMap  请求参数
      100      * @param headerMap 请求头信息
      101      */
      102     public static String get(String url, 
      103                              Map<String, String> paramMap,
      104                              Map<String, String> headerMap) throws ClientProtocolException,
      105                                                                     IOException {
      106         /*
      107          * 拼接URL与参数
      108          */
      109         if (MapUtils.isNotEmpty(paramMap)) {
      110             List<NameValuePair> params = new ArrayList<NameValuePair>();
      111             for (String key : paramMap.keySet()) {
      112                 params.add(new BasicNameValuePair(key, paramMap.get(key)));
      113             }
      114             String queryString = URLEncodedUtils.format(params, ENCODING);
      115             if (url.indexOf("?") > -1) {// 存在?,表示这时的URL已经带参数了
      116                 url += "&" + queryString;
      117             } else {
      118                 url += "?" + queryString;
      119             }
      120         }
      121 
      122         HttpGet httpGet = new HttpGet(url);
      123 
      124         /*
      125          * 设置头信息
      126          */
      127         if (MapUtils.isNotEmpty(headerMap)) {
      128             Set<String> keySet = headerMap.keySet();
      129             for (String key : keySet) {
      130                 httpGet.addHeader(key, headerMap.get(key));
      131             }
      132         }
      133 
      134         String result = "";
      135 
      136         HttpResponse response = client.execute(httpGet); // 发出get请求
      137         StatusLine status = response.getStatusLine(); // 获取返回的状态码
      138         HttpEntity entity = response.getEntity(); // 获取返回的响应内容
      139         if (status.getStatusCode() == HttpStatus.SC_OK) { // 200
      140             result = EntityUtils.toString(entity, ENCODING);
      141         }
      142 
      143         httpGet.abort();// 中止请求,连接被释放回连接池
      144         return result;
      145     }
      146 
      147     /**
      148      * post请求
      149      * @param url       请求URL
      150      * @param paramMap  请求参数
      151      * @param headerMap 请求头信息
      152      */
      153     public static String post(String url, 
      154                               Map<String, String> paramMap,
      155                               Map<String, String> headerMap) throws ClientProtocolException,
      156                                                                       IOException {
      157         HttpPost httpPost = new HttpPost(url);
      158         /*
      159          * 处理参数
      160          */
      161         List<NameValuePair> params = new ArrayList<NameValuePair>();
      162         if (MapUtils.isNotEmpty(paramMap)) {
      163             Set<String> keySet = paramMap.keySet();
      164             for (String key : keySet) {
      165                 params.add(new BasicNameValuePair(key, paramMap.get(key)));
      166             }
      167         }
      168 
      169         /*
      170          * 设置头信息
      171          */
      172         if (MapUtils.isNotEmpty(headerMap)) {
      173             Set<String> keySet = headerMap.keySet();
      174             for (String key : keySet) {
      175                 httpPost.addHeader(key, headerMap.get(key));
      176             }
      177         }
      178 
      179         String result = "";
      180 
      181         httpPost.setEntity(new UrlEncodedFormEntity(params, ENCODING));// 设置参数
      182         HttpResponse response = client.execute(httpPost); // 发出post请求
      183         StatusLine status = response.getStatusLine(); // 获取返回的状态码
      184         HttpEntity entity = response.getEntity(); // 获取响应内容
      185         if (status.getStatusCode() == HttpStatus.SC_OK) {
      186             result = EntityUtils.toString(entity, ENCODING);
      187         }
      188 
      189         httpPost.abort();// 中止请求,连接被释放回连接池
      190         return result;
      191     }
      192 
      193     /**
      194      * 构建自定义信任管理器内部类
      195      */
      196     private static class MyX509TrustManager implements X509TrustManager {
      197         /**
      198          * 检查客户端证书,若不信任,抛出异常
      199          */
      200         public void checkClientTrusted(X509Certificate[] arg0, String arg1)
      201                 throws CertificateException {
      202         }
      203         /**
      204          * 检查服务端证书,若不信任,抛出异常,反之,若不抛出异常,则表示信任(所以,空方法代表信任所有的服务端证书)
      205          */
      206         public void checkServerTrusted(X509Certificate[] arg0, String arg1)
      207                 throws CertificateException {
      208         }
      209         /**
      210          * 返回受信任的X509证书数组
      211          */
      212         public X509Certificate[] getAcceptedIssuers() {
      213             return null;
      214         }
      215     }
      216 
      217     /**
      218      * 为外部类获取内部类提供方法
      219      */
      220     public static MyX509TrustManager getMyX509TrustManager() {
      221         return new MyX509TrustManager();
      222     }
      223 
      224     /**
      225      * 测试
      226      */
      227     public static void main(String[] args) {
      228         try {
      229             System.out.println(HttpClientUtilWithMyX509TrustMananer.get("https://www.baidu.com/", null, null));
      230             // System.out.println(HttpClientUtil.post("http://www.cppblog.com/iuranus/archive/2010/07/04/119311.html", null, null));
      231         } catch (ClientProtocolException e) {
      232             e.printStackTrace();
      233         } catch (IOException e) {
      234             e.printStackTrace();
      235         }
      236     }
      237 }
      View Code

      注:在这里我定义了一个成员内部类,并提供了一个获取成员内部类的方法getMyX509TrustManager(),用于外部类来获取该内部类的实例。当然,如果对于内部类不熟的话,可以不使用内部类,直接使用上边的方式也好。

      

  • 相关阅读:
    服务器重启后oracle监听无法打开
    Resport 四则运算
    For循环
    do...while循环
    Day03_Class01
    自学JavaDay02_class02
    自学JavaDay02_class01
    自学JavaDay01
    基本的Dos命令
    MarkDown语法
  • 原文地址:https://www.cnblogs.com/java-zhao/p/5099063.html
Copyright © 2011-2022 走看看