zoukankan      html  css  js  c++  java
  • 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);
        }
  • 相关阅读:
    把Discuz!NT放在虚拟目录下
    表格样式
    页面CSS的问题,不懂中
    临时存储信息
    asp.net2.0事务
    repeater控件分成两列显示
    P2P的NAT研究
    javascript字符串trim的实现
    新浪微博OAUTH2验证
    新浪微博接口在safri下的bug
  • 原文地址:https://www.cnblogs.com/yadongliang/p/9665536.html
Copyright © 2011-2022 走看看