最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文搞懂JMeter engine中HashTree的配置問(wèn)題

 更新時(shí)間:2021年09月03日 15:53:01   作者:HenryXiao8080  
本文主要介紹了JMeter engine中HashTree的配置,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、前言

  • 之前介紹了JMeter engine啟動(dòng)原理,但是里面涉及到HashTree這個(gè)類結(jié)構(gòu)沒(méi)有給大家詳細(xì)介紹,這邊文章就詳細(xì)介紹JMeter engine里面的HashTree結(jié)構(gòu)具體用來(lái)做什么
  • 大家看到下面是JMeter控制臺(tái)配置截圖,是一個(gè)標(biāo)準(zhǔn)的菜單形式;菜單形式其實(shí)就類似于“樹(shù)型”的數(shù)據(jù)結(jié)構(gòu),而HashTree其實(shí)就是一個(gè)樹(shù)型數(shù)據(jù)結(jié)構(gòu)

在這里插入圖片描述

我們?cè)贘Meter控制臺(tái)導(dǎo)出的jmx文件,是一個(gè)xml結(jié)構(gòu)的數(shù)據(jù),他其實(shí)就是由HashTree生成的,后面我們會(huì)講到

在這里插入圖片描述 

二、HashTree的用法

首先通過(guò)HashTree類介紹,它一個(gè)集合類;具備Map結(jié)構(gòu)的功能,而且是一種樹(shù)型結(jié)構(gòu)

/**
 * This class is used to create a tree structure of objects. Each element in the
 * tree is also a key to the next node down in the tree. It provides many ways
 * to add objects and branches, as well as many ways to retrieve.
 * <p>
 * HashTree implements the Map interface for convenience reasons. The main
 * difference between a Map and a HashTree is that the HashTree organizes the
 * data into a recursive tree structure, and provides the means to manipulate
 * that structure.
 * <p>
 * Of special interest is the {@link #traverse(HashTreeTraverser)} method, which
 * provides an expedient way to traverse any HashTree by implementing the
 * {@link HashTreeTraverser} interface in order to perform some operation on the
 * tree, or to extract information from the tree.
 *
 * @see HashTreeTraverser
 * @see SearchByClass
 */
public class HashTree implements Serializable, Map<Object, HashTree>, Cloneable {
}

JMeter常用的HashTree方法(以下圖配置為例)

在這里插入圖片描述

//ListedHashTree是HashTree的繼承類,可以保證HashTree的順序性
HashTree tree = new ListedHashTree();
//TestPlan對(duì)象,測(cè)試計(jì)劃
TestPlan plan = new TestPlan();
//ThreadGroup對(duì)象,線程組
ThreadGroup group = new ThreadGroup();
//創(chuàng)建線程組數(shù)結(jié)構(gòu)的對(duì)象groupTree
HashTree groupTree = new ListedHashTree();
//表示取樣器中的HTTP請(qǐng)求
HTTPSamplerProxy sampler = new HTTPSamplerProxy();
//創(chuàng)建HTTP請(qǐng)求的數(shù)結(jié)構(gòu)對(duì)象samplerTree
//調(diào)用put方法相當(dāng)于在plan(測(cè)試計(jì)劃)菜單對(duì)象下添加group(線程組)子菜單,這樣就形成了一種樹(shù)型結(jié)構(gòu)
HashTree samplerTree = new ListedHashTree();
samplerTree.put(sampler,new ListedHashTree())
//groupTree樹(shù)結(jié)構(gòu)添加子樹(shù)samplerTree
groupTree.put(group,samplerTree)
//tree樹(shù)結(jié)構(gòu)為測(cè)試計(jì)劃對(duì)象,添加子樹(shù)groupTree,這樣就形成了上圖的層級(jí)形式
tree.put(plan, groupTree)
//調(diào)用add方法相當(dāng)于在tree菜單對(duì)象下添加同級(jí)菜單
tree.add(Object key)

三、JMeter源碼導(dǎo)出jmx腳本文件介紹

首先在JMeter控制臺(tái)所有點(diǎn)擊事件,都會(huì)被ActionRouter中performaAction方法進(jìn)行監(jiān)聽(tīng)執(zhí)行,點(diǎn)擊導(dǎo)出按鈕,會(huì)進(jìn)入到如圖方法通過(guò)反射由Save類執(zhí)行

在這里插入圖片描述

在Save類中執(zhí)行doAction主要是獲取到配置的HashTree

在這里插入圖片描述

當(dāng)你點(diǎn)擊保存的時(shí)候,它會(huì)創(chuàng)建一個(gè)空文件,此時(shí)文件沒(méi)有任何內(nèi)容

在這里插入圖片描述Save

類的doAction方法最后會(huì)調(diào)用backupAndSave(e, subTree, fullSave, updateFile)這個(gè)是來(lái)將創(chuàng)建的空文件寫入xml內(nèi)容的

在這里插入圖片描述

SaveService中saveTree方法,其中JMXSAVERXStream對(duì)象,對(duì)應(yīng)的maven坐標(biāo)如下

<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.15</version>
</dependency>

在這里插入圖片描述

四、自定義HashTree生成JMeter腳本

首先maven引入以下幾個(gè)坐標(biāo)<jmeter.version>5.3</jmeter.version>

        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_http</artifactId>
            <version>${jmeter.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-slf4j-impl</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_functions</artifactId>
            <version>${jmeter.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_jdbc</artifactId>
            <version>${jmeter.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_tcp</artifactId>
            <version>${jmeter.version}</version>
        </dependency>

先創(chuàng)建一個(gè)取樣器,然后寫成HashTree的數(shù)據(jù)結(jié)構(gòu)

public static ThreadGroup threadGroup;
//創(chuàng)建一個(gè)標(biāo)準(zhǔn)的線程組
private static void initThreadGroup(){
    LoopController loopController = new LoopController();
    loopController.setName("LoopController");
    loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
    loopController.setProperty(TestElement.GUI_CLASS, JMeterUtil.readSaveProperties("LoopControlPanel"));
    loopController.setEnabled(true);
    loopController.setLoops(1);
    ThreadGroup group = new ThreadGroup();
    group.setEnabled(true);
    group.setName("ThreadGroup");
    group.setProperty(TestElement.TEST_CLASS, JMeterUtil.readSaveProperties("ThreadGroup"));
    group.setProperty(TestElement.GUI_CLASS, JMeterUtil.readSaveProperties("ThreadGroupGui"));
    group.setProperty(ThreadGroup.ON_SAMPLE_ERROR,"continue");
    group.setProperty(ThreadGroup.IS_SAME_USER_ON_NEXT_ITERATION,true);
    group.setProperty(TestElement.COMMENTS,"");
    group.setNumThreads(1);
    group.setRampUp(1);
    group.setDelay(0);
    group.setDuration(0);
    group.setProperty(ThreadGroup.ON_SAMPLE_ERROR, ThreadGroup.ON_SAMPLE_ERROR_CONTINUE);
    group.setScheduler(false);
    group.setSamplerController(loopController);
    threadGroup = group;
}

創(chuàng)建一個(gè)標(biāo)準(zhǔn)的線程組

public static ThreadGroup threadGroup;
//創(chuàng)建一個(gè)標(biāo)準(zhǔn)的線程組
private static void initThreadGroup(){
    LoopController loopController = new LoopController();
    loopController.setName("LoopController");
    loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
    loopController.setProperty(TestElement.GUI_CLASS, JMeterUtil.readSaveProperties("LoopControlPanel"));
    loopController.setEnabled(true);
    loopController.setLoops(1);
    ThreadGroup group = new ThreadGroup();
    group.setEnabled(true);
    group.setName("ThreadGroup");
    group.setProperty(TestElement.TEST_CLASS, JMeterUtil.readSaveProperties("ThreadGroup"));
    group.setProperty(TestElement.GUI_CLASS, JMeterUtil.readSaveProperties("ThreadGroupGui"));
    group.setProperty(ThreadGroup.ON_SAMPLE_ERROR,"continue");
    group.setProperty(ThreadGroup.IS_SAME_USER_ON_NEXT_ITERATION,true);
    group.setProperty(TestElement.COMMENTS,"");
    group.setNumThreads(1);
    group.setRampUp(1);
    group.setDelay(0);
    group.setDuration(0);
    group.setProperty(ThreadGroup.ON_SAMPLE_ERROR, ThreadGroup.ON_SAMPLE_ERROR_CONTINUE);
    group.setScheduler(false);
    group.setSamplerController(loopController);
    threadGroup = group;
}

創(chuàng)建一個(gè)標(biāo)準(zhǔn)的測(cè)試計(jì)劃

public static TestPlan testPlan;
//創(chuàng)建一個(gè)標(biāo)準(zhǔn)的測(cè)試計(jì)劃
private static void initTestPlan() {
    TestPlan plan = new TestPlan();
    //設(shè)置測(cè)試計(jì)劃屬性及內(nèi)容,最后都會(huì)轉(zhuǎn)為xml標(biāo)簽的屬性及內(nèi)容
    plan.setProperty(TestElement.NAME, "測(cè)試計(jì)劃");
    plan.setProperty(TestElement.TEST_CLASS, JMeterUtil.readSaveProperties("TestPlan"));
    plan.setProperty(TestElement.GUI_CLASS, JMeterUtil.readSaveProperties("TestPlanGui"));
    plan.setEnabled(true);
    plan.setComment("");
    plan.setFunctionalMode(false);
    plan.setTearDownOnShutdown(true);
    plan.setSerialized(false);
    plan.setProperty("TestPlan.user_define_classpath","");
    plan.setProperty("TestPlan.user_defined_variables","");
    plan.setUserDefinedVariables(new Arguments());
    testPlan = plan;
}

開(kāi)始封裝成一個(gè)HashTree的配置

//先創(chuàng)建一個(gè)測(cè)試計(jì)劃hashtree對(duì)象
HashTree hashTree = new ListedHashTree();
//在創(chuàng)建一個(gè)線程組threaddGroupTree對(duì)象
HashTree threadGroupTree = new ListedHashTree();
//HttpRequestConfig為HTTP對(duì)應(yīng)的請(qǐng)求頭、請(qǐng)求體等信息數(shù)據(jù),傳入httpToHashTree靜態(tài)方法獲取到取樣器的HashTree數(shù)據(jù)結(jié)構(gòu),源碼上圖已分享
HashTree httpConfigTree = XXClass.httpToHashTree(HttpRequestConfig httpRequestData)
//threadGroupTree添加子菜單httpConfigTree對(duì)象
threadGroupTree.put(group, httpConfigTree);
//測(cè)試計(jì)劃hashTree添加子菜單threadGroupTree對(duì)象
hashTree.put(JMeterTestPlanConfigService.testPlan, threadGroupTree);

HashTree寫好后,調(diào)用JMeter原生方法SaveService.saveTree(hashTree,outStream);生成對(duì)應(yīng)的xml

如果直接調(diào)用的話生成的xml格式會(huì)形成如下圖所示,而非JMeter原生導(dǎo)出jmx形式,這種文件結(jié)構(gòu)JMeter控制臺(tái)讀取會(huì)報(bào)錯(cuò),識(shí)別不了

在這里插入圖片描述

在這里插入圖片描述

后面閱讀SaveService源碼才明白,生成xml文件之前會(huì)先初始化靜態(tài)代碼塊內(nèi)容,初始化屬性

在這里插入圖片描述
在這里插入圖片描述

過(guò)程中會(huì)調(diào)用JMeterUtils中的findFile方法來(lái)尋找saveservice.properties文件

在這里插入圖片描述

由于SaveService 中都是靜態(tài)方法無(wú)法重寫,所以根據(jù)最后調(diào)用JMeterUtils中的findFile方法來(lái)尋找saveservice.properties有兩種解決方案

方案一 :不推薦,在項(xiàng)目根目錄下存放saveservice.properties,這樣findFile方法就能拿到,但是這樣不好,因?yàn)閙aven打包的時(shí)候該文件會(huì)打不進(jìn)去,至少我springboot項(xiàng)目是遇到這樣的問(wèn)題

方案二:推薦,創(chuàng)建一個(gè)臨時(shí)文件命名為saveservice.properties,然后提前將saveservice.properties配置讀取到臨時(shí)文件中,這樣在調(diào)用JMeterUtils中的findFile方法同樣能夠找到配置,成功解決SaveService初始化屬性導(dǎo)致的問(wèn)題,具體代碼如下

private void hashTreeToXML(HashTree hashTree,PressureConfigInfo configInfo){
    FileOutputStream outStream = null;
    File file = new File("temp.jmx");
    File tempFile = null;
    try {
    	//創(chuàng)建一個(gè)臨時(shí)的saveservice.properties文件
        tempFile = new File("saveservice.properties");
        InputStream is = JMeterUtil.class.getResource("/jmeter/saveservice.properties").openStream();
        //將配置文件寫入臨時(shí)文件中
        FileUtil.writeFromStream(is,tempFile);
        outStream = new FileOutputStream(file);
        //調(diào)用saveTree成功轉(zhuǎn)為xml
        SaveService.saveTree(hashTree,outStream);
        String xmlContent = FileUtil.readUtf8String(file);
        configInfo.setFile(xmlContent.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            FileUtils.forceDelete(file);
            FileUtils.forceDelete(tempFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

最后生成的xml文件結(jié)構(gòu)如下圖,通過(guò)JMeter控制臺(tái)也能成功打開(kāi)識(shí)別

在這里插入圖片描述

到此這篇關(guān)于一文搞懂JMeter engine中HashTree的配置問(wèn)題的文章就介紹到這了,更多相關(guān)JMeter engine中HashTree配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • 使用Java實(shí)現(xiàn)HTTP和HTTPS代理服務(wù)詳解

    使用Java實(shí)現(xiàn)HTTP和HTTPS代理服務(wù)詳解

    這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)HTTP和HTTPS代理服務(wù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-04-04
  • java 重試框架 sisyphus 入門介紹

    java 重試框架 sisyphus 入門介紹

    sisyphus 綜合了 spring-retry 和 gauva-retrying 的優(yōu)勢(shì),使用起來(lái)也非常靈活,本文給大家介紹java 重試框架 sisyphus 入門相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-10-10
  • Eclipse配置python開(kāi)發(fā)環(huán)境過(guò)程圖解

    Eclipse配置python開(kāi)發(fā)環(huán)境過(guò)程圖解

    這篇文章主要介紹了Eclipse配置python開(kāi)發(fā)環(huán)境過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • C++字符串的處理詳解

    C++字符串的處理詳解

    這篇文章主要介紹了C++ string字符串類,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • 使用jdk1.8實(shí)現(xiàn)將list根據(jù)指定的值去分組的操作

    使用jdk1.8實(shí)現(xiàn)將list根據(jù)指定的值去分組的操作

    這篇文章主要介紹了使用jdk1.8實(shí)現(xiàn)將list根據(jù)指定的值去分組的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • java List 排序之冒泡排序?qū)嵗a

    java List 排序之冒泡排序?qū)嵗a

    這篇文章主要介紹了java List 排序之冒泡排序?qū)嵗a的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • java8從list集合中取出某一屬性的值的集合案例

    java8從list集合中取出某一屬性的值的集合案例

    這篇文章主要介紹了java8從list集合中取出某一屬性的值的集合案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • 關(guān)于Java項(xiàng)目讀取resources資源文件路徑的那點(diǎn)事

    關(guān)于Java項(xiàng)目讀取resources資源文件路徑的那點(diǎn)事

    這篇文章主要介紹了關(guān)于Java項(xiàng)目讀取resources資源文件路徑的那點(diǎn)事,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Gradle 創(chuàng)建Task的多種方法

    Gradle 創(chuàng)建Task的多種方法

    本文主要介紹了Gradle 創(chuàng)建Task的多種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Java中結(jié)束循環(huán)的方法

    Java中結(jié)束循環(huán)的方法

    這篇文章主要介紹了Java中結(jié)束循環(huán)的方法,文中有段代碼在return,結(jié)束了整個(gè)main方法,即使輸出hello world的語(yǔ)句位于循環(huán)體外,也不會(huì)被執(zhí)行,對(duì)java結(jié)束循環(huán)方法感興趣的朋友跟隨小編一起看看吧
    2023-06-06

最新評(píng)論

永吉县| 响水县| 靖远县| 玉龙| 安多县| 繁峙县| 宿迁市| 山阳县| 安新县| 乌拉特前旗| 合作市| 龙泉市| 尤溪县| 陆河县| 潮安县| 长阳| 巢湖市| 安泽县| 白城市| 长顺县| 二手房| 乾安县| 洪洞县| 扎赉特旗| 东城区| 洪雅县| 雷山县| 滨州市| 宁波市| 罗甸县| 资中县| 衡山县| 中卫市| 罗定市| 竹山县| 鹤庆县| 镇赉县| 上栗县| 琼海市| 嘉义县| 茶陵县|