zoukankan      html  css  js  c++  java
  • java模拟http/https post请求

    1.Post请求失败的代码

    try {
                 HttpResponse response = httpClient.execute(httpPost);
     
                 HttpEntity entity = response.getEntity();
     
                 result = EntityUtils.toString(entity, "UTF-8");
                 Util.log("API,POST回来的数据是:");
                 Util.log(result);
     
             } catch (ConnectionPoolTimeoutException e) {
                 log.e("http get throw ConnectionPoolTimeoutException(wait time out)");
     
             } catch (ConnectTimeoutException e) {
                 log.e("http get throw ConnectTimeoutException");
     
             } catch (SocketTimeoutException e) {
                 log.e("http get throw SocketTimeoutException");
     
             }  catch (Exception e) {
                 log.e("http get throw Exception");
     
             } finally {
                 httpPost.abort();
             }
    

    之前每次代码执行到上述代码的第二行的时候,会等一段时间然后会捕获到Exception异常。

    2.分析问题

    当然捕获的Exception这个异常太大了我们不便于分析,我们查看一下httpClient.execute(HttpUriRequest uri)的方法;

    发下这个方法会抛出IOException, ClientProtocolException这两个异常,但是在调用方法的时候并没有明确捕获他们两个。

    3.得出结论

    所以很有可能在执行post请求的过程中,遇到了这两个问题,果然我们把代码完善之后

    try {
                httpClient = new SSLClient();
                HttpResponse response = httpClient.execute(httpPost);
    
                HttpEntity entity = response.getEntity();
    
                result = EntityUtils.toString(entity, "UTF-8");
                Util.log("API,POST回来的数据是:");
                Util.log(result);
    
            } catch (ConnectionPoolTimeoutException e) {
                log.e("http get throw ConnectionPoolTimeoutException(wait time out)");
    
            } catch (ConnectTimeoutException e) {
                log.e("http get throw ConnectTimeoutException");
    
            } catch (SocketTimeoutException e) {
                log.e("http get throw SocketTimeoutException");
    
            } catch (ClientProtocolException e) {
                log.e("http get throw ClientProtocolException");
    
            } catch (IOException e) {
                e.printStackTrace();
    
            } catch (Exception e) {
                log.e("http get throw Exception");
    
            } finally {
                httpPost.abort();
            }

    上述,完善完毕代码后捕捉到了IOException异常,我们把异常打印出来看到了如下信息。

     4.解决问题

    通过在网上查询可知,这是缺少安全证书时出现的异常,解决方案如下:

    1. 等待Oracle/Google/Mozilla等等组织信任CNNIC,算了,洗洗睡吧
    2. 使用Java的TrustManager忽略所有的SSL请求的证书,仅仅用于开发测试,限于篇幅不做介绍了
    3. 导入目标网站的证书,然后在开始调用之前,指定keystore就ok了,本文介绍下该方法

    目前我们采用第二种方案:由于请求的URL是HTTPS的,为了避免需要证书,所以用一个类继承DefaultHttpClient类,忽略校验过程。

    编写一个SSLClient类

    package com.phicomm.smarthome.sharedwifi.util;
    
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.apache.http.conn.ClientConnectionManager;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.impl.client.DefaultHttpClient;
    
    public class SSLClient extends DefaultHttpClient {
    
        public SSLClient() throws Exception {
            super();
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
    
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    // TODO Auto-generated method stub
    
                }
    
                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    // TODO Auto-generated method stub
    
                }
    
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    // TODO Auto-generated method stub
                    return null;
                }
            };
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = this.getConnectionManager();
            SchemeRegistry sr = ccm.getSchemeRegistry();
            sr.register(new Scheme("https", 443, ssf));
        }
    }

     对应的实现类:

    public HttpResponse sendPostToService(String url, Object pushData) throws IOException, KeyStoreException,
                UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
    
            if (!hasInit) {
                init();
            }
    
            String result = null;
    
            HttpPost httpPost = new HttpPost(url);
    
            StringEntity postEntity = new StringEntity(pushData.toString(),
                    ContentType.create("application/x-www-form-urlencoded", "UTF-8"));
            // 设置一些Http头信息
            httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
            httpPost.addHeader("connection", "Keep-Alive");
            httpPost.addHeader("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 将发送内容填装
            httpPost.setEntity(postEntity);
    
            // 设置请求器的配置
            httpPost.setConfig(requestConfig);
    
            // 打印待发送的数据
            Util.log("=====API,POST过去的数据是:");
            Util.log("executing request" + httpPost.getRequestLine());
            Util.log("请求头信息===" + httpPost.getAllHeaders().toString());
            Util.log("请求状态行===" + httpPost.getRequestLine());
            Util.log("请求配置===" + httpPost.getConfig());
            Util.log("请求实体===" + httpPost.getEntity().getContentEncoding() + httpPost.getEntity().getContentType()
                    + httpPost.getEntity().getContent());
    
            HttpResponse response = null;
            try {
                // 忽略所有的SSL请求的证书
                httpClient = new SSLClient();
                response = httpClient.execute(httpPost);
    
                HttpEntity entity = response.getEntity();
    
                result = EntityUtils.toString(entity, "UTF-8");
                // 打印得到的响应信息
                Util.log("API,POST回来的数据是:");
                Util.log("=====Entity:" + result);
                Util.log("=====Headers:" + response.getAllHeaders());
                Util.log("=====StatusLine:" + response.getStatusLine());
                Util.log("=====Locale:" + response.getLocale());
    
            } catch (ConnectionPoolTimeoutException e) {
                log.e("http get throw ConnectionPoolTimeoutException(wait time out)");
    
            } catch (ConnectTimeoutException e) {
                log.e("http get throw ConnectTimeoutException");
    
            } catch (SocketTimeoutException e) {
                log.e("http get throw SocketTimeoutException");
    
            } catch (ClientProtocolException e) {
                log.e("http get throw ClientProtocolException");
    
            } catch (IOException e) {
                e.printStackTrace();
    
            } catch (Exception e) {
                log.e("http get throw Exception");
    
            } finally {
                httpPost.abort();
            }
    
            return response;
        }

    在第36行使用自定义的SSLClient来忽略掉验证要求

    另外注意在postMan中模拟调用的时候我们是用的x-www-form-urlencoded格式的数据请求,就是application/x-www-from-urlencoded,会将表单内的数据转换为键值对。

    当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2...),然后把这个字串append到url后面,用?分割,加载这个新的url。 当action为post时候,浏览器把form数据封装到http body中,然后发送到server。 

    所以我们需要对传进来的数据做一下处理:

    // 拼接x-www-form-urlencoded格式的请求参数
            String www_url = "coverimg=" + pushMsgModel.getCoverimg() + "&mode=" + pushMsgModel.getMode() + "&msgcontent="
                    + pushMsgModel.getMsgContent() + "&msgtype=" + pushMsgModel.getMsgtype() + "&outline="
                    + pushMsgModel.getOutline() + "&saveRecord=" + pushMsgModel.getSaveRecord() + "&source="
                    + pushMsgModel.getSource() + "&ticker=" + pushMsgModel.getTicker() + "&timestamp="
                    + pushMsgModel.getTimestamp() + "&title=" + pushMsgModel.getTitle() + "&uid=" + pushMsgModel.getUid()
                    + "&url=" + pushMsgModel.getUrl();
            logger.info("x-www-form-urlencoded格式的请求参数为:" + www_url);

    最后效果如下:

  • 相关阅读:
    diary and html 文本颜色编辑,行距和其它编辑总汇
    bash coding to changeNames
    virtualbox ubuntu 网络连接 以及 连接 secureCRT
    linux 学习6 软件包安装
    linux 学习8 权限管理
    vim 使用2 转载 为了打开方便
    ubuntu
    linux 学习15 16 启动管理,备份和恢复
    linux 学习 14 日志管理
    linux 学习 13 系统管理
  • 原文地址:https://www.cnblogs.com/lingyejun/p/7418268.html
Copyright © 2011-2022 走看看