转自:https://blog.csdn.net/fhaohaizi/article/details/77850302

2018年07月19日更新,主要是解耦之后方法很多地方发生了变化,httpclient用了连接池方式,作为一个静态变量处理,请求头和响应头以及cookies设置都有了相关处理方法,本来这个方法已经快超过100行了,解耦之后分成了几个小方法,方便修改和调试。分两部分,一部分是框架,只做了公共处理,另外一部分是每个项目的base类需要重新实现一些这个方法来处理header信息以及需要特殊处理的地方。分享代码如下:

/**
* 获取响应实体
*
* @param request 请求对象
* @return 返回json类型的对象
*/
protected static JSONObject getHttpResponse(HttpRequestBase request) {
beforeRequest(request);
JSONObject jsonObject = new JSONObject();
RequestInfo requestInfo = new RequestInfo(request);
CloseableHttpResponse response = null;// 创建响应对象
Date start = getDate();// 记录开始时间
try {
response = ClientManage.httpsClient.execute(request);
} catch (Exception e) {
new Thread(() -> new AlertOver("接口请求失败", requestInfo.toString() + Arrays.toString(e.getStackTrace()), requestInfo.getUrl()).sendSystemMessage()).start();
return jsonObject;
}
Date end = getDate();// 记录结束时间
double elapsed_time = getTimeDiffer(start, end);// 获取响应耗时
afterResponse(response);
int status = response.getStatusLine().getStatusCode();// 获取响应状态
String content = getContent(response);
long data_size = content.length();
jsonObject = getResponse(content);
int code = checkCode(jsonObject, requestInfo.getUrl());
if (status != HttpStatus.SC_OK)
new Thread(() -> new AlertOver("响应状态码错误", "状态码错误:" + status, requestInfo.getUrl()).sendSystemMessage());
MySqlTest.saveApiTestDate(requestInfo, data_size, elapsed_time, status, getMark(), code, LOCAL_IP, COMPUTER_USER_NAME);
return jsonObject;
}

下面是里面封装方法的依次分享:

/**
* 发送请求之前,配置请求管理器,设置IP,user_agent和cookie
*
* @param request
*/
private static void beforeRequest(HttpRequestBase request) {
request.setConfig(requestConfig);//设置请求配置
request.addHeader(getHeader("X-FORWARDED-FOR", getRandomIP()));//随机生成ip
request.addHeader(HTTP.USER_AGENT, USER_AGENT);
if (cookies != null && !Arrays.toString(request.getAllHeaders()).contains(REQUEST_HEADER_COOKIE))
request.addHeader(REQUEST_HEADER_COOKIE, cookies);// 添加cookie
}

requestinfo类的方法:

package com.fission.source.httpclient;

import com.fission.source.source.SourceCode;
import lombok.Data;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.util.EntityUtils; import java.io.IOException; /**
* 请求信息封装类
*/
@Data
public class RequestInfo extends SourceCode {
/**
* 接口地址
*/
String apiName;
/**
* 请求的url
*/
String url;
/**
* 请求的uri
*/
String uri;
/**
* 方法,get/post
*/
String method;
/**
* 域名
*/
String host;
/**
* 协议类型
*/
String type;
/**
* 参数
*/
String params; /**
* 通过request获取请求的相关信息,并输出部分信息
*
* @param request
*/
public RequestInfo(HttpRequestBase request) {
getRequestInfo(request);
if (!host.contains("alertover") && !host.contains("lonelymind"))
output(TAB + TAB + TAB + "请求uri:" + uri + LINE + TAB + TAB + TAB + "请求参数是:" + params);
} /**
* 封装获取请求的各种信息的方法
*
* @param request 传入请求对象
* @return 返回一个map,包含api_name,host_name,type,method,params
*/
private void getRequestInfo(HttpRequestBase request) {
method = request.getMethod();// 获取method
uri = request.getURI().toString();// 获取uri
getRequestUrl(uri);
String one = url.substring(url.indexOf("//") + 2);// 删除掉http://
apiName = one.substring(one.indexOf("/"));// 获取接口名
host = one.substring(0, one.indexOf("/"));// 获取host地址
type = url.substring(0, url.indexOf("//") - 1);// 获取协议类型
if (method.equals(REQUEST_TYPE_GET)) {
params = uri.substring(uri.indexOf("?") + 1, uri.length());
} else if (method.equals(REQUEST_TYPE_POST)) {
getPostRequestParams(request);
}
} /**
* 获取请求url,遇到get请求,先截取
*
* @param uri
*/
private void getRequestUrl(String uri) {
url = uri;
if (uri.contains("?")) url = uri.substring(0, uri.indexOf("?"));
} /**
* 获取post请求的参数
*
* @param request
*/
private void getPostRequestParams(HttpRequestBase request) {
HttpPost httpPost = (HttpPost) request;// 强转httppost请求
HttpEntity entity = httpPost.getEntity();// 获取实体
if (entity == null) return;
try {
params = EntityUtils.toString(entity);// 解析实体
EntityUtils.consume(entity);// 确保实体消耗
} catch (UnsupportedOperationException e) {
params = "entity类型:" + entity.getClass();
} catch (ParseException e) {
output("解析响应实体异常!", e);
} catch (IOException e) {
output("解析响应实体时java IO 异常!", e);
}
}
}
/**
* 响应结束之后,处理响应头信息,如set-cookien内容
*
* @param response
*/
private static void afterResponse(CloseableHttpResponse response) {
if (response == null) return;
List<Header> headers = Arrays.asList(response.getHeaders("Set-Cookie"));
if (!headers.equals(new ArrayList<>())) setCookies(headers);
if (cookieSet == false && cookies != null)
cookieSet = true;
}
/**
* 根据响应获取响应实体
*
* @param response
* @return
*/
private static String getContent(CloseableHttpResponse response) {
HttpEntity entity = response.getEntity();// 获取响应实体
String content = EMPTY;
try {
content = EntityUtils.toString(entity, UTF_8);// 用string接收响应实体
EntityUtils.consume(entity);// 消耗响应实体,并关闭相关资源占用
if (response != null) response.close();
} catch (ParseException e1) {
output("解析响应实体异常!", e1);
} catch (IOException e1) {
output("解析响应实体时java IO 异常!", e1);
}
return content;
}
    /**
* 根据解析好的content,转化json对象
*
* @param content
* @return
*/
private static JSONObject getResponse(String content) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject = JSONObject.fromObject(content);
} catch (Exception e) {
jsonObject.put("content", content);
jsonObject.put("code", TEST_ERROR_CODE);
}
return jsonObject;
}
    /**
* 获取并检查code
*
* @param jsonObject
* @param url
* @return
*/
private static int checkCode(JSONObject jsonObject, String url) {
int code = TEST_ERROR_CODE;
try {
code = jsonObject.getInt("code");
if (ERROR_CODE_LIST.contains(code))
new Thread(() -> new AlertOver("responseCode错误", jsonObject.toString(), url).sendSystemMessage());
} catch (Exception e) {
output("响应非标准响应体!", e);
}
return code;
}

其中数据库存储的和发送提醒消息的这里就不说了,数据库一部存储还在优化,alertover使用方法在其他文章分享过了。

------------------------------------分割线--------------------------------------

本人在使用httpclient做接口测试的时候,需要统计一下接口的一些信息,在写用例的过程中为了提高复用,简化一些结构,所以封装了一些基本方法,分享一下获取响应实体和响应信息的方法,共大家参考。

//获取post响应,暂无header设置
public JSONObject getHttpResponseEntityByJson(CloseableHttpClient httpClient, HttpPost httpPost) throws ClientProtocolException, IOException, SQLException, JSONException {
//在请求中明确定义不要进行压缩
// httpPost.setHeader("Accept-Encoding", "identity");
HttpResponse response = null;//创建响应对象
long date_size = 0;//用于存放数据大小
String api_name = getApiName(httpPost);//获取接口名称
String type = getProtocolType(httpPost);//获取协议类型
String host_name = getHostName(httpPost);//获取hsot主机名称
Date start = getDate();//记录开始时间
response = httpClient.execute(httpPost);//获取响应
Date end = getDate();//记录结束时间
double elapsed_time= outputTimeDiffer(start, end, "接口:" + api_name);//获取响应耗时
int status = response.getStatusLine().getStatusCode();//获取响应状态
if (status == HttpStatus.SC_OK) {//判断一下返回状态
output("host:" + host_name, "接口:"+ api_name + "请求成功!");
} else {
output(response.getStatusLine().getStatusCode() + LINE + "请求失败!");
}
HttpEntity entity = response.getEntity();//获取响应实体
data_size = entity.getContentLength();//获取相应数据大小
if (data_size == -1) {//如果为-1,则重置date_size
date_size = 0;
}
String content = EntityUtils.toString(entity);//解析响应
if (date_size == 0) {//如果被重置或者没有获取到,则date_size等于解析string大小
date_size = content.length();
}
JSONObject jsonObject = new JSONObject(content);//转换json
LocalMySql.getInstance().saveApiTestDate(host_name, api_name, date_size, elapsed_time, status, type);
// httpClient.close();//关闭客户端
return jsonObject;
}
//获取get接口响应,暂无header设置
public JSONObject getHttpResponseEntityByJson(CloseableHttpClient httpClient, HttpGet httpGet) throws ClientProtocolException, IOException, JSONException, SQLException {
//在请求中明确定义不要进行压缩
// httpGet.setHeader("Accept-Encoding", "identity");
HttpResponse response = null;
long date_size = 0;
String api_name = getApiName(httpGet);
String type = getProtocolType(httpGet);
Date start = getDate();
response = httpClient.execute(httpGet);
Date end = getDate();
double elapsed_time= outputTimeDiffer(start, end, "接口:" + api_name);
String host_name = getHostName(httpGet);
int status = response.getStatusLine().getStatusCode();
if (status == HttpStatus.SC_OK) {//判断一下返回状态
output("host:" + host_name, "接口:"+ api_name + "请求成功!");
} else {
output(response.getStatusLine().getStatusCode() + LINE + "请求失败!");
}
HttpEntity entity = response.getEntity();
data_size = entity.getContentLength();
if (data_size == -1) {
date_size = 0;
}
String content = EntityUtils.toString(entity);
if (date_size == 0) {
date_size = content.length();
}
JSONObject jsonObject = new JSONObject(content);
LocalMySql.getInstance().saveApiTestDate(host_name, api_name, date_size, elapsed_time, status, type);
// httpClient.close();
return jsonObject;
}

中间使用了本地数据库,将收集的信息存入本地数据库里面,以便以后统计。代码如下:

    //保存接口测试数据的方法
public void saveApiTestDate(String host_name, String api_name, long date_size, double elapsed_time, int status, String type) throws SQLException {
getConnection();
if (!connection.isClosed()) {
outputSuccess();
Statement statement = connection.createStatement();
String sql = "INSERT INTO api_result (host_name,api_name,date_size,elapsed_time,status,type) VALUES ('"+host_name+"','"+api_name+"',"
+date_size+","+ elapsed_time + "," + status + ",'" + type +"');";
// output(sql);
statement.executeUpdate(sql);
}
}

中间用到了一些自己封装的方法:

    //获取json数据中的相应值
public String getJsonValue(String jsonString, String key) throws JSONException {
String JsonValue = null;
if (jsonString == null || jsonString.trim().length() < 1) {//排除为空和空格
return null;
}
JSONObject obj1 = new JSONObject(jsonString);
JsonValue = (String) obj1.getString(key);
return JsonValue;//返回对应值
}
//获取json数据中的相应值
public String getJsonValue(JSONObject jsonObject, String key) {
String JsonValue = "··-·";
try {
JsonValue = (String) jsonObject.getString(key);
} catch (JSONException e) {
output("json数据错误!");
output(e.toString());
}
return JsonValue;//返回对应值
}
//把json数据转化为参数
public String changeJsonToArguments(JSONObject argument) {
String one = argument.toString();
String two ="?" + one.substring(1, one.length()-1).replace(",", "&").replace(":", "=").replace("\"", "");
return two;
}
//获取接口名称
public String getApiName(HttpGet httpGet) {
String url = getUrl(httpGet);
String apiName = url.substring(url.indexOf("m/") + 1);
return apiName;
}
//获取接口名称
public String getApiName(HttpPost httpPost) {
String url = getUrl(httpPost);
String apiName = url.substring(url.indexOf("m/") + 1);
return apiName;
}
//获取host名称
public String getHostName(HttpPost httpPost) {
String url = getUrl(httpPost);
String host = url.substring(url.indexOf("//") + 2, url.indexOf("m/") + 2);
return host;
}
//获取host名称
public String getHostName(HttpGet httpGet) {
String url = getUrl(httpGet);
String host = url.substring(url.indexOf("//") + 2, url.indexOf("m/") + 2);
return host;
}
//获取url
public String getUrl(HttpGet httpGet) {
String uri = httpGet.getURI().toString();
String url = uri.substring(0, uri.indexOf("?"));
return url;
}
//获取url
public String getUrl(HttpPost httpPost) {
String url = httpPost.getURI().toString();
if (url.contains("?")) {
url = url.substring(0, url.indexOf("?"));
}
return url;
}
//获取协议类型
public String getProtocolType(HttpGet httpGet) {
String uri = httpGet.getURI().toString();
String type = uri.substring(0, uri.indexOf("//") - 1);
return type;
}
//获取协议类型
public String getProtocolType(HttpPost httpPost) {
String uri = httpPost.getURI().toString();
String type = uri.substring(0, uri.indexOf("//") - 1);
return type;
}
//输出json
public void output(JSONObject jsonObject) {
String info = jsonObject.toString().replaceAll(",", LINE);
output(info);
}

httpclient获取响应实体和信息的封装方法(解耦更新)的更多相关文章

  1. 获取响应状态Status信息、获取状态码Status Code

    一般服务器的响应状态有以下几种: 200 正常 400 未找到页面 403 拒绝 500 服务器错误 比如我们请求bootstrap中文网, 此时的状态码是200 OK表示正常,后面的from cac ...

  2. Android 使用retrofit时,怎样获取响应的头信息

    这个问题,我前段时间在项目中使用Retrofit遇到过,最后查到的解决办法有两种获取Response Headers的方法,第一种是直接在定义接口是让接口返回Retrofit的Response对象,在 ...

  3. Android实现获取应用程序相关信息列表的方法

    本文所述为Androdi获取手机应用列表的方法,比如获取到Android应用的软件属性.大小和应用程序路径.应用名称等,获取所有已安装的Android应用列表,包括那些卸载了的,但没有清除数据的应用程 ...

  4. springboot 采用HttpClient获取天气预报 异常及原因

    采用httpClient调用天气预报地址获取出现异常 2018-10-04 15:18:25.815 ERROR 10868 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[ ...

  5. HttpClient获取数据

    HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议 ...

  6. JAVA--利用HttpClient模拟浏览器登陆请求获取响应的Cookie

    在通过java采集网页数据时,我们常常会遇到这样的问题: 站点需要登陆才能访问 而这种网站,一般都会对请求进行账号密码的验证,验证的方式也有多种,需要具体分析. 今天分析其中的一种情况: 站点对登陆密 ...

  7. WMI 获取硬件信息的封装函数与获取联想台式机的出厂编号方法

    原文:WMI 获取硬件信息的封装函数与获取联想台式机的出厂编号方法 今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都是可以提取出来的,就自己把那些公共部分提出出来,以后如果要获取 某部分的 ...

  8. 阿里云视频点播获取视频点播的video信息

    背景 因为在项目中需要使用阿里云的视频点播服务,需要获取视频点播的时长信息. 工具类 生成签名串Signature SignatureUtils.java package com.meeno.wzq. ...

  9. .Net基础——程序集与CIL HttpClient封装方法 .Net Core 编码规范 C#中invoke和beginInvoke的使用 WebServeice 动态代理类

    .Net基础——程序集与CIL   1. 程序集和CIL: 程序集是由.NET语言的编译器接受源代码文件产生的输出文件,通常分为 exe和dll两类,其中exe包含Main入口方法可以双击执行,dll ...

随机推荐

  1. JavaScript类的写法

    js类的基本含义 我们知道,在js中,是没有类的概念的.类的所有实例对象都从同一个原型对象上继承属性,因此,原型对象是类的核心. 类是对象的抽象,而对象是类的具体实例.类是抽象的,不占用内存,而对象是 ...

  2. 配置nginx到后端服务器负载均衡

    nginx和haproxy一样也可以做前端请求分发实现负载均衡效果,比如一个tomcat服务如果并发过高会导致处理很慢,新来的请求就会排队,到一定程度时请求就可能会返回错误或者拒绝服务,所以通过负载均 ...

  3. wamp设置自定义域名访问php网站

    wamp是一个在window系统下很不错的php开发套件,一般我都是使用此套件在本地进行开发和测试的 特别是alias功能特别好,可以同时开发N个php网站而不互相影响 但alias有一个问题,它其实 ...

  4. 解决excel日期变成数字的问题

    在Excel中如果单元格的公式是日期格式,那么引用后的数值是错误的[不是日期格式而被转换成数字类型了],这种情况显然不是我们想要的结果 解决办法: 在公式中强制转成文本类型即可(="Date ...

  5. VS2013开发asmx接口返回一个自定义XML

    1:利用XmlDocument生成一个xml文档返回,代码如下 using System;using System.Collections.Generic;using System.Linq;usin ...

  6. HTTP 响应实体主体:XML 及 XML parser

    本文内容 HTTP 响应实体主体:XML XML parser 总结 各编程语言实现的 XML parser   HTTP 响应实体主体:XML 实体主体(entity-body)通常是HTTP响应里 ...

  7. powerdesigner 生成数据库脚本

    PowerDesigner导出所有SQL脚本 操作:Database=>Generate Database PowerDesigner怎么导出建表sql脚本 1 按照数据库类型,切换数据库. D ...

  8. android中RecyclerView控件的列表项横向排列

    本文是在上一篇文章的基础上做的修改:android中RecyclerView控件的使用 1.修改列表项news_item.xml:我这里是把新闻标题挪到了新闻图片的下面显示 <?xml vers ...

  9. LintCode: Binary Tree Postorder Traversal

    C++,递归 /** * Definition of TreeNode: * class TreeNode { * public: * int val; * TreeNode *left, *righ ...

  10. 编程之美 1.1 让cpu占用率曲线听你指挥(多核处理器)

    [目录] 不考虑其他进程,cpu画正弦曲线 获取总体cpu利用率 获取多核处理器单个cpu利用率 考虑其他进程,cpu画正弦曲线 下面的程序针对多核处理器,可以设置让任何一个cpu显示相应的曲线(本文 ...