Java 进阶 & 实现读取Excel中的Http请求及检查点、关联API (一)

一、项目场景

1、excel中存储各个http请求的 类型、url,参数,头部信息,检查点,关联参数


image.png

2、从excel中读取并发送各类http请求,并校验检查点
3、将各请求中关联的参数,引入对应需要关联的请求链接中

二、实现以上需求,需要使用到框架
   <!--用于读取excel-->
        <dependency>
            <groupId>com.github.crab2died</groupId>
            <artifactId>Excel4J</artifactId>
            <version>2.1.2</version>
        </dependency>
        <!--用于读取文件-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <!--用于httpclient发送get,post请求-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.4</version>
        </dependency>
        <!--用于表达式判断-->
        <dependency>
            <groupId>com.googlecode.aviator</groupId>
            <artifactId>aviator</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!--用于获取json数据-->
        <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path</artifactId>
            <version>2.4.0</version>
        </dependency>
三、需要用到的Utils工具类

1、将字符串转化成Map存储。
如:excel中的头部信息、检查点有多个时,需要拆分

import java.util.HashMap;
import java.util.Map;
public class MapUtil {
    public static Map StringToMap(String str, String regx){

        Map<String,Object> map = null;
        if(str!=null) {
            String[] strs = str.split(regx);
            map = new HashMap<String,Object>();
            for (String s : strs) {
                String[] ss = s.split("=");
                map.put(ss[0], ss[1]);
            }
        }
        return  map;
    }
    public static Map StringToMap(String str){
        return StringToMap(str,";");
    }
}

2、将参数存储到Map中。
如:excel中的关联参数,若有多个时需要拆分,且需要得到具体关联的值。

import com.jayway.jsonpath.JsonPath;
import java.util.HashMap;
import java.util.Map;

public class SaveParamsUtil {
    private  static  Map<String,Object> paramsMap = new HashMap<String,Object>();
    public static void saveParamsToMap(String json,String params){
        Map<String,Object> map = MapUtil.StringToMap(params);
        if(map!=null) {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String key = entry.getKey();
                String val = entry.getValue().toString();
//这里需要用到JsonPath表达式获取具体json中的值
                Object obj = JsonPath.read(json, val);
                paramsMap.put(key, obj.toString());
            }
        }
    }

    public static Object get(String key){
        return  paramsMap.get(key);
    }
}

3、正则表达式匹配工具类
如:excel中第三个请求url中用到关联的参数

import com.sc.bean.TestCase;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PatternUtil {
    private static Pattern patternRule = Pattern.compile("\\$\\{(.*?)\\}");//${id}
    public static void matcherParams(TestCase testCase){
        Matcher matcher = patternRule.matcher(testCase.getUrl());
        while (matcher.find()){
            System.out.println(matcher.group());
            String key = matcher.group(1);
            String value = SaveParamsUtil.get(key).toString();
            String url = testCase.getUrl().replace(matcher.group(),value);
            testCase.setUrl(url);
            System.out.println("newurl--->"+testCase.getUrl());
        }
    }
}

4、实际json返回的结果与excel中检查点是否一致工具类
如:excel中 $.code的实际值与期望值 1的比较

import com.googlecode.aviator.AviatorEvaluator;
import com.jayway.jsonpath.JsonPath;
import java.util.HashMap;
import java.util.Map;

public class CheckPointUtil {
    public static Boolean checkPoint(String json,String checkParam){
        if(checkParam!=null && !"".equals(checkParam) && !"null".equals(checkParam)){
            Map<String,Object> map = new HashMap<String,Object>();
            String[] cParams =  checkParam.split(";");
            for(String params:cParams){
                String[] pars = params.split("=|>|<|>=|<=|==");
                checkParam = checkParam.replace(pars[0],"data");
                Object obj = JsonPath.read(json,pars[0]);
                if(obj instanceof  String){
                    checkParam =  checkParam.replace(pars[1],StrToAviatorString(pars[1]));
                    checkParam = checkParam.replace("=","==");
                }
                map.put("data",obj);
                Boolean bool = (Boolean) AviatorEvaluator.execute(checkParam,map);
                return  bool;
            }
        }
        return true;
    }
    public static String StrToAviatorString(String str){
        return  "'"+str+"'";
    }
}

5、HttpClient发送get、post请求工具类

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

public class HttpUtils {

    private static CloseableHttpClient httpclient;

    static {
        PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager();
        manager.setMaxTotal(200); //连接池最大并发连接数
        manager.setDefaultMaxPerRoute(200);//单路由最大并发数,路由是对maxTotal的细分
        httpclient = HttpClients.custom().setConnectionManager(manager).build();
    }

    /* ConnectionRequestTimeout httpclient使用连接池来管理连接,这个时间就是从连接池获取连接的超时时间,可以想象下数据库连接池
       ConnectTimeout 建立连接最大时间
       SocketTimeout 数据传输过程中数据包之间间隔的最大时间
       HttpHost 代理
     */
    private static RequestConfig config = RequestConfig.copy(RequestConfig.DEFAULT)
             .setSocketTimeout(10000)
             .setConnectTimeout(5000)
             .setConnectionRequestTimeout(100).build();
            //.setProxy(new HttpHost("127.0.0.1", 8888, "http")).build();

    public static String doGet(String url) throws HttpClientException {
        return doGet(url, null);
    }

    public static String doGet(String url, Map<String, Object> header) throws HttpClientException {
        String ret = "";
        HttpGet get = new HttpGet(url);
        get.setConfig(config);
        get.addHeader(HTTP.CONTENT_ENCODING, "UTF-8");
        CloseableHttpResponse closeableHttpResponse = null;
        try {
            if (header != null) {
                for (Map.Entry<String, Object> entry : header.entrySet()) {
                    get.setHeader(entry.getKey(), entry.getValue().toString());
                }
            }
            closeableHttpResponse = httpclient.execute(get);
            if (closeableHttpResponse.getStatusLine().getStatusCode() == 200) {
                ret = EntityUtils.toString(closeableHttpResponse.getEntity(), "UTF-8");
            } else {
                throw new HttpClientException(
                        "System level error, Code=[" + closeableHttpResponse.getStatusLine().getStatusCode() + "].");
            }
        } catch (ClientProtocolException e) {
            throw new HttpClientException("HttpClient error," + e.getMessage());
        } catch (IOException e) {
            throw new HttpClientException("IO error," + e.getMessage());
        } finally {
            if (closeableHttpResponse != null) {
                try {
                    closeableHttpResponse.close();
                } catch (IOException e) {
                }
            }
        }
        return ret;
    }

    public static String doPostString(String url, String params, String regx) throws HttpClientException {
        Map<String, Object> paramsMp =null;
        if(params!=null) {
            paramsMp = new HashMap<String, Object>();
            String[] strp = params.split(regx);
            for (int i = 0; i < strp.length; i++) {
                String singleparms = strp[i];
                String[] key_values = singleparms.split("=");
                paramsMp.put(key_values[0], key_values[1]);
            }
        }
        return doPost(url, paramsMp);
    }
    
    public static String doPost(String url, Map<String, Object> params) throws HttpClientException {
        return doPost(url, params, null);
    }

    public static String doPost(String url, Map<String, Object> params, Map<String, Object> header)
            throws HttpClientException {
        String ret = "";
        HttpPost post = new HttpPost(url);
        post.setConfig(config);
        post.addHeader(HTTP.CONTENT_ENCODING, "UTF-8");
        CloseableHttpResponse closeableHttpResponse = null;
        HttpEntity postEntity = null;
        try {
            if (params != null) {
                List<NameValuePair> list = new ArrayList<NameValuePair>();
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    list.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                }
                postEntity = new UrlEncodedFormEntity(list,"UTF-8");
                post.setEntity(postEntity);
            }

            if (header != null) {
                for (Map.Entry<String, Object> entry : header.entrySet()) {
                    post.setHeader(entry.getKey(), entry.getValue().toString());
                }
            }
            closeableHttpResponse = httpclient.execute(post);
            if (closeableHttpResponse.getStatusLine().getStatusCode() == 200) {
                ret = EntityUtils.toString(closeableHttpResponse.getEntity(), "UTF-8");
            } else {
                throw new HttpClientException(
                        "System level error, Code=[" + closeableHttpResponse.getStatusLine().getStatusCode() + "].");
            }
        } catch (ClientProtocolException e) {
            throw new HttpClientException("HttpClient error," + e.getMessage());
        } catch (IOException e) {
            throw new HttpClientException("IO error," + e.getMessage());
        } finally {
            if (postEntity != null) {
                try {
                    EntityUtils.consume(postEntity);
                } catch (IOException e) {
                }
            }
            if (closeableHttpResponse != null) {
                try {
                    closeableHttpResponse.close();
                } catch (IOException e) {
                }
            }
        }
        return ret;
    }

    public static String doPostJson(String url, String jsonParam) throws HttpClientException {
        return doPostJson(url, jsonParam, null);
    }

    public static String doPostJson(String url, String jsonParam, Map<String, Object> header)
            throws HttpClientException {
        String ret = "";
        HttpPost post = new HttpPost(url);
        post.setConfig(config);
        post.addHeader(HTTP.CONTENT_ENCODING, "UTF-8");
        CloseableHttpResponse closeableHttpResponse = null;
        StringEntity postEntity = null;
        try {
            if (jsonParam != null) {
                postEntity = new StringEntity(jsonParam, "utf-8"); 
                postEntity.setContentEncoding("UTF-8");
                postEntity.setContentType("application/json");
                post.setEntity(postEntity);
            }

            if (header != null) {
                for (Map.Entry<String, Object> entry : header.entrySet()) {
                    post.setHeader(entry.getKey(), entry.getValue().toString());
                }
            }
            closeableHttpResponse = httpclient.execute(post);
            if (closeableHttpResponse.getStatusLine().getStatusCode() == 200) {
                ret = EntityUtils.toString(closeableHttpResponse.getEntity(), "UTF-8");
            } else {
                throw new HttpClientException(
                        "System level error, Code=[" + closeableHttpResponse.getStatusLine().getStatusCode() + "].");
            }
        } catch (ClientProtocolException e) {
            throw new HttpClientException("HttpClient error," + e.getMessage());
        } catch (IOException e) {
            throw new HttpClientException("IO error," + e.getMessage());
        } finally {
            if (postEntity != null) {
                try {
                    EntityUtils.consume(postEntity);
                } catch (IOException e) {
                }
            }
            if (closeableHttpResponse != null) {
                try {
                    closeableHttpResponse.close();
                } catch (IOException e) {
                }
            }
        }
        return ret;
    }
}
定义自己的异常类:
public class HttpClientException extends Exception{
    private static final long serialVersionUID = 2206587260745140347L;
    public HttpClientException(String msg) {
        super(msg);
    }
}
四、excel中的各参数转化成javabean
import com.github.crab2died.annotation.ExcelField;

public class TestCase {
    
    @ExcelField(title = "类型")
    private String type;
    
    @ExcelField(title = "地址")
    private String url;
    
    @ExcelField(title = "参数")
    private String params;
    
    @ExcelField(title = "头部",order=2)
    private String header;
    
    @ExcelField(title = "测试结果", order=1)
    private String result;
    
    @ExcelField(title = "检查点")
    private String checkP;
    
    @ExcelField(title = "关联")
    private String correlation;


    public String getCheckP() {
        return checkP;
    }

    public void setCheckP(String checkP) {
        this.checkP = checkP;
    }

    public String getCorrelation() {
        return correlation;
    }

    public void setCorrelation(String correlation) {
        this.correlation = correlation;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getParams() {
        return params;
    }

    public void setParams(String params) {
        this.params = params;
    }

    public String getHeader() {
        return header;
    }

    public void setHeader(String header) {
        this.header = header;
    }

    @Override
    public String toString() {
        return "TestCase{" +
                "type='" + type + '\'' +
                ", url='" + url + '\'' +
                ", params='" + params + '\'' +
                ", header='" + header + '\'' +
                ", result='" + result + '\'' +
                ", checkP='" + checkP + '\'' +
                ", correlation='" + correlation + '\'' +
                '}';
    }
}
五、测试类

1、通过github.Excel4J包中的ExcelUtils 读取excel,返回List
遍历List集合,集合中的每一个对象都是 TestCase bean
2、遍历List的过程中,判断读取excel中type请求是get还是post
如果是get,就调用已封装好的HttpUtils中的doGet方法,需要传get请求需要的url,头部信息
如果是post,就调用已封装好的HttpUtils中的doPost方法,需要传get请求需要的url,参数,头部信息
因为在Excel中参数、头部信息都是以字符串的形式存储的,所以需要将参数,头部信息字符串转化成Map对象才行。
所以,这里封装了字符串转Map的工具类MapUtil,方法名为:StringToMap,这里需要传一个分割符的参数,为了方便后续使用,重载StringToMap方法,传递了默认的分割符“;”。
3、将get/post的请求返回结果,存储在某个变量中responseJson。
4、检查responseJson返回的code的值,是否与excel中检查点中code的值是否一致。
excel中“.code=1”,先要得到excel中检查点的值,如果是多个,需要分割一下,结果为一个数组1。 因为数组1中的每个元素,=号左侧是Jsonpath表达式,=号右侧是具体的值,所以需要继续分隔,结果为一个数组2 分隔完成后,数组2中,第一个元素即为jsonpath表达式,这里需要将整个参数字符串中的第一个元素替化成 data 用JsonPath.read(responseJson,数组2的第一个元素),返回一个具体的值 判断上述返回的值是否为String类型,如果是,则需要将数组2的第二个值转化成字符串,且字符串相比较要用==,所以需要将参数中=替换成== 将data作为key,JsonPath.read返回的值作为 value,放入Map中 使用AviatorEvaluator.exec(params,map),返回结果为bool类型。 5、关联: 首先,需要查看遍历的List集合的结果中,是否存在需要接受关联参数的请求。 这里要用到Pattern正规匹配{(.*?)}作为一个匹配的规则,这里同jmeter中正则表达式匹配
在excel的url中通过上述匹配规则循环查看是否有需要匹配的url
如果有匹配,则返回一个group,这里group得到的是${id}
通过group(n)得到具体要关联的参数为id
将excel中关联的参数id的值已转存到map中
这里直接可调用该map,key为group(n),即可得到对应的id的value
将url中的参数替换成该id对应的value,得到一个新的url
重新为TestCase设置url,后续http发送请求时,即可得到一个完整url

import com.github.crab2died.ExcelUtils;
import com.sc.bean.TestCase;
import com.sc.http.HttpUtils;
import com.sc.util.CheckPointUtil;
import com.sc.util.MapUtil;
import com.sc.util.PatternUtil;
import com.sc.util.SaveParamsUtil;
import java.io.File;
import java.util.List;

public class ApiTest {
    public static void main(String[] args) throws Exception {
        String path = System.getProperty("user.dir")+ File.separator+"data"+File.separator+"apitest.xlsx";
//通过github.Excel4J包中的ExcelUtils 读取excel,返回List
        List<TestCase> list = ExcelUtils.getInstance().readExcel2Objects(path,TestCase.class);
        if(list!=null){
            for(TestCase testCase : list){
                PatternUtil.matcherParams(testCase);
                String responseJson =null;
                if("get".equals(testCase.getType())){
                    responseJson = HttpUtils.doGet(testCase.getUrl(), MapUtil.StringToMap(testCase.getHeader()));
                }else if("post".equals(testCase.getType())){
                    responseJson = HttpUtils.doPost(testCase.getUrl(), MapUtil.StringToMap(testCase.getParams(),"&"),MapUtil.StringToMap(testCase.getHeader()));
                }
               Boolean checkFlag =  CheckPointUtil.checkPoint(responseJson,testCase.getCheckP());
                System.out.println("checkFlag="+checkFlag);
                if(checkFlag){
                    SaveParamsUtil.saveParamsToMap(responseJson,testCase.getCorrelation());
                }
                System.out.println(responseJson);
            }
        }

    }
}
六、输出结果
checkFlag=true
{"msg":"登录成功","uid":"E2BBEDC09FAA4406B8D85C96DF6281CF","code":"1"}
checkFlag=true
{"msg":"登录成功","uid":"E2BBEDC09FAA4406B8D85C96DF6281CF","code":"1"}
${id}
newurl--->http://www.baidu.com?pid=E2BBEDC09FAA4406B8D85C96DF6281CF
checkFlag=true
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta ......
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容