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

转自: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);
    }

原文地址:https://www.cnblogs.com/yadongliang/p/9665536.html

时间: 2024-10-10 02:55:10

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

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

这个问题,我前段时间在项目中使用Retrofit遇到过,最后查到的解决办法有两种获取Response Headers的方法,第一种是直接在定义接口是让接口返回Retrofit的Response对象,在Response对象中可以获取到Headers,如: @GET("/****act=****") Response<SomeClass> getSomeData(); 在操作Response对象时,使用response.headers():得到Headers. 这样做需要修改所

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

本文所述为Androdi获取手机应用列表的方法,比如获取到Android应用的软件属性.大小和应用程序路径.应用名称等,获取所有已安装的Android应用列表,包括那些卸载了的,但没有清除数据的应用程序,同时在获取到应用信息的时候,判断是不是系统的应用程序,这是一个应用管理器所必需具备的功能. 具体实现代码如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

获取jar包版本信息的简单方法

今天把一个java项目转换成maven项目的时候,发现有些包信息不明确,在porm中添加中无法确定哪一个才是我们需要对的. 以Gson为例,拿到我们需要的信息. 用解压软件打开后,能看到一个叫META-INF的目录.在META-INF文件夹下,找到 MANIFEST.MF文件,就能找到我们需要的信息. 如上.

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

采用httpClient调用天气预报地址获取出现异常 2018-10-04 15:18:25.815 ERROR 10868 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested

HttpClient获取数据

HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议.如果只是需要向Web站点的某个简单页面提交请求并获取服务器响应,HttpURLConnection完全可以胜任.但在绝大部分情况下,Web站点的网页可能没这么简单,这些页面并不是通过一个简单的URL就可访问的,可能需要用户登录而且具有相应的权限才可访问该页面.在这种情况下,就需要涉及Session

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

在通过java采集网页数据时,我们常常会遇到这样的问题: 站点需要登陆才能访问 而这种网站,一般都会对请求进行账号密码的验证,验证的方式也有多种,需要具体分析. 今天分析其中的一种情况: 站点对登陆密码进行动态加密,作为Cookie响应给客户端,之后的请求需要携带加密后的密码进行访问 登陆成功的响应头如下图: 之后的请求头: 因为每次登陆生成一个新的加密密码,所以之前的密码会失效 所以,需要在每次采集之前,先模拟登陆获取响应的密码,再作为cookie继续请求,我们选择采用HttpClient模拟

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

原文:WMI 获取硬件信息的封装函数与获取联想台式机的出厂编号方法 今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都是可以提取出来的,就自己把那些公共部分提出出来,以后如果要获取 某部分的硬件信息就不用写一个一个的函数,比如获取MAC地址就写一个获取MAC地址的函数,获取CPU 信息就写一个获取CPU信息的 函数,太麻烦了 如下是函数代码: 1 private static string identifier(string wmiClass, string wmiProperty,

AFNetworking 2.0获取响应头信息

转载请注明出处:http://blog.csdn.net/dengbin9009/article/details/43304813 前文有提到在初始化的时候可以设置Http的头信息,这没有任何问题,但是在笔者使用过程中,时常是要获取Http返回的一些头信息,在初次用AFNetworking2.0新特性NSURLSessionDataTask的时候,为了获取返回的头信息,搞了两个晚上,先是度娘,谷歌,StackOverflow,然后各种那个群找人,嘴壶问同事找大神,最后都说没有用过.就在想要放弃,

Jsoup+HttpClient获取新浪新闻数据

package com.test; import java.io.IOException; import java.net.URI; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.cl