java模拟http/https post请求

简介: 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)的方法;


a43a07ab0c7cfa23a5b0f52d724a9bf0.png

发下这个方法会抛出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异常,我们把异常打印出来看到了如下信息。

80d994dd7151ba176ab11e1dc0c79b0b.png

4.解决问题

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

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


等待Oracle/Google/Mozilla等等组织信任CNNIC,算了,洗洗睡吧

使用Java的TrustManager忽略所有的SSL请求的证书,仅仅用于开发测试,限于篇幅不做介绍了

导入目标网站的证书,然后在开始调用之前,指定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);

最后效果如下:


0e7bd215a1e53d7ea2db4d508c84f772.png

目录
相关文章
|
18天前
|
Rust 前端开发 API
Tauri 开发实践 — Tauri HTTP 请求开发
本文介绍了如何在 Tauri 中发起 HTTP 请求。首先通过安装 Tauri 生态中的工具包并配置 `tauri.conf.json` 文件来允许特定域名的 HTTP 通信。接着封装了一个简单的 HTTP 客户端类,并在页面中使用该客户端实现 GET 和 POST 请求。最后提供了完整的源码地址以供参考。此功能使得桌面应用能够与远程服务器进行交互,增强了应用的实用性。
52 1
Tauri 开发实践 — Tauri HTTP 请求开发
|
3天前
|
数据采集 前端开发 算法
Python Requests 的高级使用技巧:应对复杂 HTTP 请求场景
本文介绍了如何使用 Python 的 `requests` 库应对复杂的 HTTP 请求场景,包括 Spider Trap(蜘蛛陷阱)、SESSION 访问限制和请求频率限制。通过代理、CSS 类链接数控制、多账号切换和限流算法等技术手段,提高爬虫的稳定性和效率,增强在反爬虫环境中的生存能力。文中提供了详细的代码示例,帮助读者掌握这些高级用法。
Python Requests 的高级使用技巧:应对复杂 HTTP 请求场景
|
4天前
|
网络协议
Lua中实现异步HTTP请求的方法
Lua中实现异步HTTP请求的方法
|
3天前
|
存储 安全 网络协议
HTTP 请求方法
【10月更文挑战第22天】HTTP 请求方法
6 2
|
3天前
|
缓存 JSON 安全
HTTP请求发送方法
HTTP请求发送方法【10月更文挑战第22天】
8 2
|
20天前
|
存储 JSON API
HTTP 请求与响应处理:C#中的实践
【10月更文挑战第4天】在现代Web开发中,HTTP协议至关重要,无论构建Web应用还是API开发,都需要熟练掌握HTTP请求与响应处理。本文从C#角度出发,介绍HTTP基础知识,包括请求与响应结构,并通过`HttpClient`库演示如何发送GET请求及处理响应,同时分析常见错误并提供解决方案,助你更高效地完成HTTP相关任务。
63 2
|
3天前
|
安全 网络安全 开发者
概述HTTP请求方法
【10月更文挑战第19天】HTTP定义了一组方法,包括GET、HEAD、PUT、POST、TRACE、OPTIONS和DELETE等。GET和HEAD被认为是安全的,不会在服务器上产生结果。GET用于请求资源,HEAD则仅请求资源的头部信息。PUT用于上传文件,POST用于提交数据,TRACE用于诊断请求路径上的修改情况,OPTIONS查询服务器支持的功能,DELETE请求删除资源。此外,HTTP还支持扩展方法,以适应新特性的发展。
|
5月前
|
JSON 安全 Java
JAVA Socket 实现HTTP与HTTPS客户端发送POST与GET方式请求
JAVA Socket 实现HTTP与HTTPS客户端发送POST与GET方式请求
66 0
|
Java 网络安全 数据安全/隐私保护
【Java异常】Unrecognized SSL message, plaintext connection?https请求遇到异常分析
【Java异常】Unrecognized SSL message, plaintext connection?https请求遇到异常分析
1427 0
|
Java Apache Spring
Java发送Http请求(HttpClient)
Java发送Http请求(HttpClient)
9734 1