使用Java开发Jmeter自定义取样器(Sampler)插件

news2025/1/15 21:07:11

文章目录

    • 1、Jmeter自定义取样器扩展类
    • 2、SpringBoot服务器端http测试例子
    • 3、自定义取样器实现
      • 3.1、默认界面的AbstractJavaSamplerClient扩展实现
      • 3.2、自定义界面的AbstractSamplerGui扩展实现
    • 3、自定义取样器运行效果
      • 3.1、AbstractJavaSamplerClient运行效果
      • 3.2、AbstractSamplerGui运行效果
      • 3.3、监听器-查看结果树
      • 3.4、监听器-聚合报告

1、Jmeter自定义取样器扩展类

Jmeter提供默认界面(AbstractJavaSamplerClient)和自定义界面的(AbstractSamplerGui)两种自定义取样器的插件开发方式,对于复杂的压测任务,可以通过自定义取样器的方式来实现。
本文通过压测SpringBoot的http接口演示两个自定义扩展类的实现方式:

2、SpringBoot服务器端http测试例子

maven项目工程,pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.penngo.example</groupId>
    <artifactId>gateway-service</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>gateway-service</name>
    <description>https://blog.csdn.net/penngo</description>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <java.version>11</java.version>
        <spring-boot.version>2.7.2</spring-boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.penngo.example.service.Service2App</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

http接口示例代码,Service2App.java

package com.penngo.example.service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@SpringBootApplication
public class Service2App {
    public static void main(String[] args) {
        SpringApplication.run(Service2App.class, args);
    }

    @RestController
    public class HelloController {
        @GetMapping("/test")
        public Map test(HttpServletRequest request){
            String page = request.getParameter("page");
            String keyword = request.getParameter("keyword");
            String userid = "";
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for(Cookie cookie:cookies){
                    if(cookie.getName().equals("userid")){
                        userid = cookie.getValue();
                        break;
                    }
                }
            }
            Map<String, String> data = new HashMap<>();
            data.put("page", page);
            data.put("keyword", keyword);
            data.put("userid", userid);
            return data;
        }
    }
}

3、自定义取样器实现

两种扩展的实现代码都在同一个maven工程里面,pom.xml代码:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.test.jmeter</groupId>
    <version>1.0.0</version>
    <artifactId>jmter_test</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.15.2</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.5</version>
        </dependency>
        <!-- 注意与Jmeter的版本一致 -->
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_core</artifactId>
            <version>5.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_java</artifactId>
            <version>5.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.17.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.17.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.36</version>
        </dependency>

    </dependencies>
</project>

3.1、默认界面的AbstractJavaSamplerClient扩展实现

可通过getDefaultParameters()接口,实现在默认界面上配置参数,SampleResult负责记录样本结果,TestHttpSampler.java代码:

package com.test.jmeter;

import cn.hutool.json.JSONUtil;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class TestHttpSampler extends AbstractJavaSamplerClient {
    private static final Logger log = LoggerFactory.getLogger(TestHttpSampler.class);
    @Override
    public SampleResult runTest(JavaSamplerContext javaSamplerContext) {

        String url = javaSamplerContext.getParameter("url");
        String userid = javaSamplerContext.getParameter("userid");

        Map<String, String> cookieMap = new HashMap();
        cookieMap.put("userid", userid);

        SampleResult sampleResult = new SampleResult();
        sampleResult.setSampleLabel("JavaSamplerClient请求查询");
        sampleResult.sampleStart();
        try {
            Map<String, String> data = data();
            sampleResult.setRequestHeaders(JSONUtil.toJsonStr(data));

            var res = Jsoup.connect(url)
                    .header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                    .ignoreContentType(true)
                    .cookies(cookieMap)
                    .data(data)
                    .method(Connection.Method.GET)
                    .execute();
            String body = res.body();
            log.info(body);
            sampleResult.setSuccessful(true);
            sampleResult.setResponseCode("200");
            sampleResult.setResponseData(body, "UTF-8");
            sampleResult.setResponseCodeOK();
        }
        catch(Exception e){
            log.error("runTest error:",e);
            sampleResult.setResponseCode("500");
            sampleResult.setSuccessful(false);
            sampleResult.setResponseData("exception," + e.getMessage(), "UTF-8");
        }
        sampleResult.sampleEnd();
        return sampleResult;
    }
    private Map<String, String> data(){
        Random r = new Random();
        String page = String.valueOf((r.nextInt(5) + 1));
        StringBuffer keyword = new StringBuffer();
        String str = "abcdefghijklmnopqrstuvwxyz";

        for(int i = 0; i < 7; i++){
            keyword.append(str.toCharArray()[r.nextInt(str.length())]);
        }

        Map<String, String> data = new HashMap<>();
        data.put("page",page);
        data.put("keyword",keyword.toString());
        return data;
    }
    public Arguments getDefaultParameters() {
        Arguments arguments = new Arguments();
        arguments.addArgument("url", "");
        arguments.addArgument("userid", "");
        return arguments;
    }
}

3.2、自定义界面的AbstractSamplerGui扩展实现

自定义界面的UI库是基于swing,可以使用所有的swing组件

package com.test.jmeter;

import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
import org.apache.jmeter.testelement.TestElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import java.awt.*;

public class TestGuiHttpSampler extends AbstractSamplerGui {
    private static final Logger log = LoggerFactory.getLogger(TestGuiHttpSampler.class);
    private JTextField urlField = null;
    private JTextField useridField = null;

    public TestGuiHttpSampler(){
        urlField = new JTextField();
        useridField = new JTextField();
        initUI();
    }

    private void initUI(){
        JPanel topPanel = new JPanel(new GridBagLayout());
        topPanel.add(new JLabel("http参数"), new GB(0,0,1,1).setInsets(5));
        topPanel.add(new JLabel("访问地址:"), new GB(0,1,1,1).setInsets(5));
        topPanel.add(urlField, new GB(1,1,1,1).setInsets(5).setFill(GB.BOTH).setWeight(100,0));
        topPanel.add(new JPanel(), new GB(0,2,2,1).setInsets(5).setFill(GB.BOTH).setWeight(100,100));

        JPanel bottomPanel = new JPanel(new GridBagLayout());
        bottomPanel.add(new JLabel("Cookie参数"), new GB(0,0,1,1).setInsets(5));
        bottomPanel.add(new JLabel("用户id:"), new GB(0,1,1,1).setInsets(5));
        bottomPanel.add(useridField, new GB(1,1,1,1).setInsets(5).setFill(GB.BOTH).setWeight(100,0));
        bottomPanel.add(new JPanel(), new GB(0,2,2,1).setInsets(5).setFill(GB.BOTH).setWeight(100,100));

        JSplitPane splitPane = new JSplitPane();
        splitPane.setOneTouchExpandable(true);
        splitPane.setContinuousLayout(true);
        log.info("====TestGuiHttpSampler size:" + this.getSize());
        splitPane.setDividerLocation(50);
        splitPane.setPreferredSize(this.getSize());
        splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
        splitPane.setTopComponent(topPanel);
        splitPane.setBottomComponent(bottomPanel);

        setLayout(new BorderLayout());
        add(splitPane, BorderLayout.CENTER);
    }

    @Override
    public String getLabelResource() {
        return null;
    }

    @Override
    public TestElement createTestElement() {
        TestGuiSampler sample = new TestGuiSampler();
        return sample;
    }

    @Override
    public void modifyTestElement(TestElement testElement) {
        testElement.clear();
        configureTestElement(testElement);
        testElement.setProperty(TestGuiSampler.URL, urlField.getText());
        testElement.setProperty(TestGuiSampler.USERID, useridField.getText());
    }

    @Override
    public boolean canBeAdded() {
        return super.canBeAdded();
    }
    @Override
    public String getStaticLabel() {
        return "TestGuiHttpSampler测试";
    }
    @Override
    public void clearGui() {
        super.clearGui();
        urlField.setText("");
        useridField.setText("");
    }
}

3、自定义取样器运行效果

工程项目打包,把jmter_test-1.0.0.jar、jsoup-1.15.2.jar、hutool-all-5.8.5.jar三个包扔到apache-jmeter-5.4.3\lib\ext目录中,重新启动Jmeter。

3.1、AbstractJavaSamplerClient运行效果

在线程组上鼠标右键,弹出菜单中选择“取样器->Java请求中”,在面板的下拉框中可以看到实现的扩展类名并选择。
在这里插入图片描述

在这里插入图片描述

3.2、AbstractSamplerGui运行效果

在线程组上右键,在取样器的子菜单中,能看到实现的扩展类"TestGuiHttpSampler测试",选择即可
在这里插入图片描述

在这里插入图片描述

3.3、监听器-查看结果树

在这里插入图片描述

3.4、监听器-聚合报告

在这里插入图片描述
源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/914920.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

net start Mysql 启动服务时 ,显示“Mysql服务正在启动 Mysql服务无法启动 服务没有报告任何错误

一、问题 有时候&#xff0c;输入net start Mysql 启动服务时 mysql>net start Mysql 显示 Mysql服务正在启动 Mysql服务无法启动 服务没有报告任何错误 二、原因 由于mysql的默认端口是3306&#xff0c;因此在启动服务的时候&#xff0c;如果此端口被占用&#xff0c;就会出…

Stable Diffusion 系列教程 | 打破模型壁垒

目录 1.模型基本分类 1.1 CheckPoint 大模型/底模型/主模型 1.2 VAE美化模型/变分自编码器 1.3 HyperNetwork 超网络 1.4 embeddings&#xff08;/Textual Inversion&#xff09; 嵌入式向量 1.5 loRa 低秩适应模型 2. 下载途径和渠道 2.1 C站 2.1.1 如何筛选到自己需…

攻防世界-Web_php_include

原题 解题思路 php://被替换了&#xff0c;但是只做了一次比对&#xff0c;改大小写就可以绕过。 用burp抓包&#xff0c;看看有哪些文件 flag明显在第一个PHP文件里&#xff0c;直接看

psycopg2 使用ThreadedConnectionPool 工具封装

psycopg2 介绍 psycopg2库介绍: Psycopg2是一个用于Python编程语言的第三方库&#xff0c;用于访问PostgreSQL数据库系统。它提供了一组工具和方法&#xff0c;可以轻松地在Python程序中进行数据库操作&#xff0c;包括查询、插入、更新、删除等操作。 以下是Psycopg2库的一些…

主程技术分享: 游戏项目帧同步,状态同步如何选

网络游戏开发项目中帧同步,状态同步如何选&#xff1f; 网络游戏的核心技术之一就是玩家的网络同步,主流的网络同步有”帧同步”与”状态同步”。今天我们来分析一下这两种同步模式。同时教大家如何在自己的项目中采用最合适的同步方式。接下来从以下3个方面来阐述: 对啦&…

基于swing的图书借阅管理系统java jsp书馆书籍信息mysql源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 基于swing的图书借阅管理系统 系统有2权限&#xff1…

Qt快速学习(三)--事件,绘图,文件系统

目录 1. Qt消息机制和事件 1.1 事件 1.2 event&#xff08;&#xff09; 1.3 事件过滤器 1.4 总结 2 绘图和绘图设备 2.1 QPainter 2.2 绘图设备 2.2.1 QPixmap、QBitmap、QImage 2.2.2 QPicture 3. 文件系统 3.1 基本文件操作 3.2 二进制文件读写 3.3 文本文件读写…

运维作业7

1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 1&#xff09;拉取mysql5.6和owncloud镜像 2)登录本机ip地址&#xff0c;输入用户名密码 2、安装搭建私有仓库 Harbor 1)安装docker-compose编排工具 2&#xff09;安装harbor [rootserver ~]# tar xf harbor-…

“石头剪刀布”游戏:while、函数自调用实现循环游戏

if…else实现“石头剪刀布”游戏&#xff0c;while、函数自调用实现循环游戏。 (本笔记适合学过if…else的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c…

Leetcode刷题笔记--Hot21-30

1--全排列&#xff08;46&#xff09; 主要思路1&#xff1a; 经典全排列&#xff0c;每次枚举每一位时&#xff0c;重头开始枚举&#xff0c;用一个访问数组记录当前已经被访问过的数字&#xff1b; 这道题不包含重复数字&#xff0c;所以不需要进行树层上的剪枝&#xff1b; …

【机器学习】python基础实现线性回归

手写梯度下降的实现ykxb的线性回归 算法步骤&#xff1a; &#xff08;1&#xff09;构造数据&#xff0c;y3*x5; &#xff08;2&#xff09;随机初始化和&#xff0c;任意数值&#xff0c;例如9,10; &#xff08;3&#xff09;计算&#xff0c;,并计算 &#xff08;4&…

Linux基本指令【上】

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析3 目录 &#x1f449;&#x1f3fb;浅识操作系统&#x1f449;&#x1f3fb;ls.和. .sta…

【C++】STL——map的介绍和使用、map的构造函数、map的迭代器、map的容量和访问函数、map的增删查改函数

文章目录 1.map的介绍2.map的使用2.1map的构造函数2.2map的迭代器2.3map的容量和访问函数2.4map的增删查改函数 1.map的介绍 map的介绍 &#xff08;1&#xff09;map是关联容器&#xff0c;它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。 &#xff…

WPS右键新建没有docx pptx xlsx 修复

解决wps右键没有新建文档的问题 右键没有新建PPT和Excel 1 wps自带的修复直接修复没有用 以上不管咋修复都没用 2 先编辑注册表 找到 HKEY_CLASSES_ROOT CTRLF搜文件扩展名 pptx docx xlsx 新建字符串 三种扩展名都一样操作 注册表编辑之后再次使用wps修复 注册组件&am…

Docker Desktop 笔记

https://blog.csdn.net/qq_39611230/article/details/108641842 https://blog.csdn.net/KgdYsg/article/details/118213499 1、修改配置 {"registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com","https://…

PHP自己的框架session()使用(完善篇六)

1、PHP自己的框架session() 2、session类&#xff08;SessionBase.php&#xff09; <?php class SessionBase {/*** 设置session*/public static function set($name, $data, $expire600){$session_data array();$session_data[data] $data;$session_data[expire] time…

Vue使用Animate.css

说一下Animate.css这个动画库&#xff0c;很多的动画在这个库里面都定义好了&#xff0c;我们用的时候可以直接使用里面的类名就可以了&#xff0c;就是直接目标元素绑定对应的类名就可以实现动画效果&#xff0c;非常方便&#xff0c;库其实也相对简单&#xff0c;使用起来也简…

IDEA 一键清除所有的无效引用

快捷键 // windows版本 CtrlAltO//mac版本 controloptionO 使用方式 1. 清除单个类中的无效的import, 打开具体的类。然后使用快捷键。 2. 清除整个项目的无效引用&#xff0c;左键点击项目名&#xff0c;然后使用快捷键&#xff0c;会出现以下提示。按Run即可。

21.2 CSS 三大特性与页面布局

1. 开发者工具修改样式 使用开发者工具修改样式, 操作步骤如下: * 1. 打开开发者工具: 在浏览器中右键点击页面, 然后选择检查或者使用快捷键(一般是 F12 或者 CtrlShiftI)来打开开发者工具.* 2. 打开样式编辑器: 在开发者工具中, 找到选项卡或面板, 一般是Elements或者Elemen…

2. HBase中文学习手册之如何运行一个单机版的HBase?

HBase中文学习手册之如何运行一个单机版的HBase? 1.1 介绍1.2 快速开始1.2.1 安装 Open JDK 81.2.2 启动 HBase1.2.3 Shell 练习1.2.4 运行停止脚本来停止HBase 1.1 介绍 上篇博文HBase中文学习手册之揭开Hbase的神秘面纱分享了 HBase 的一些理论基础知识的介绍。 本文将会继…