JMeter自定义采样器插件开发
JMeter自定义采样器插件开发
1. 简介
JMeter支持插件机制,只需要将打包好的jar包放到lib/ext/下面,JMeter就会动态的加载符合要求的插件。
- 要扩展UI的话,扩展的Java类的包名必须是.gui.
- 同样的扩展函数的Java类的包名必须是.function.
2. 需求简介
本文演示的是如何自定义一个https	的采样器。
ssl的配置以参数的形式传给JMeter。
3.成品展示

成功展示

失败展示





4. 准备开发环境
新建Maven项目。
4.1 准备pom文件
<?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>org.example</groupId>
    <artifactId>httpsSampler</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jmeter-version>3.0</jmeter-version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_core</artifactId>
            <version>${jmeter-version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_java</artifactId>
            <version>${jmeter-version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <defaultGoal>install</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>assemble-all</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
4.2 新建Java的GUI类
新建 org.apache.jmeter.protocol.https.control.gui 类,并继承org.apache.jmeter.samplers.gui.AbstractSamplerGui
需要重写几个函数。
/**gui显示的sample的名称**/
public String getStaticLabel()
public String getLabelResource()
//这个方法用于把界面的数据移到Sampler中。
public void modifyTestElement(TestElement testElement)
//界面与Sampler之间的数据交换
public void configure(TestElement el)
//该方法会在reset新界面的时候调用,这里可以填入界面控件中需要显示的一些缺省的值(就是默认显示值)
public void clearGui()
//该方法创建一个新的Sampler,然后将界面中的数据设置到这个新的Sampler实例中。
public TestElement createTestElement()
全代码
package org.apache.jmeter.protocol.https.control.gui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.apache.jmeter.gui.util.JSyntaxTextArea;
import org.apache.jmeter.gui.util.JTextScrollPane;
import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.protocol.https.sampler.HttpsSampler;
import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.gui.JLabeledTextField;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
//这个注解必须要有
@SuppressWarnings("deprecation")
public class HttpsSamplerUI extends AbstractSamplerGui {
    private static final long serialVersionUID = 1L;
    private static Logger log = LoggingManager.getLoggerForClass();
    private final JLabeledTextField sslVersionField = new JLabeledTextField("SSL版本");
    private final JLabeledTextField cipherField = new JLabeledTextField("密码套件");
    private final JLabeledTextField twoWayField = new JLabeledTextField("双向");
    private final JLabeledTextField caCertField = new JLabeledTextField("CA证书");
    private final JLabeledTextField clientCertField = new JLabeledTextField("客户端证书");
    private final JLabeledTextField clientP12Field = new JLabeledTextField("客户端私钥");
    private final JLabeledTextField requestsStringField = new JLabeledTextField("请求信息");
    private final JSyntaxTextArea textMessage = new JSyntaxTextArea(10, 50);
    // private final JLabel textArea = new JLabel(JMeterUtils.getResString("kafka.message", "Message"));
    private final JLabel textArea = new JLabel("Message");
    private final JTextScrollPane textPanel = new JTextScrollPane(textMessage);
    public HttpsSamplerUI(){
        super();
        this.init();
    }
    private void init(){
        log.info("Initializing the UI.");
        setLayout(new BorderLayout());
        setBorder(makeBorder());
        add(makeTitlePanel(), BorderLayout.NORTH);
        JPanel mainPanel = new VerticalPanel();
        add(mainPanel, BorderLayout.CENTER);
        JPanel DPanel = new JPanel();
        DPanel.setLayout(new GridLayout(4, 2));
        DPanel.add(sslVersionField);
        DPanel.add(cipherField);
        DPanel.add(twoWayField);
        DPanel.add(caCertField);
        DPanel.add(clientCertField);
        DPanel.add(clientP12Field);
        DPanel.add(requestsStringField);
        JPanel ControlPanel = new VerticalPanel();
        ControlPanel.add(DPanel);
        ControlPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray), "参数"));
        mainPanel.add(ControlPanel);
        /**这是是输出**/
        JPanel ContentPanel = new VerticalPanel();
        JPanel messageContentPanel = new JPanel(new BorderLayout());
        messageContentPanel.add(this.textArea, BorderLayout.NORTH);
        messageContentPanel.add(this.textPanel, BorderLayout.CENTER);
        ContentPanel.add(messageContentPanel);
        ContentPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray), "Content"));
        mainPanel.add(ContentPanel);
    }
    /**
     * 该方法创建一个新的Sampler,然后将界面中的数据设置到这个新的Sampler实例中。
     * **/
    @Override
    public TestElement createTestElement() {
        HttpsSampler sampler = new HttpsSampler();
        this.setupSamplerProperties(sampler);
        return sampler;
    }
    /**
     * 该方法会在reset新界面的时候调用,这里可以填入界面控件中需要显示的一些缺省的值。
     * **/
    @Override
    public void clearGui(){
        super.clearGui();
        this.sslVersionField.setText("TLSv1.2");
        this.cipherField.setText("ECDHE-AES256-SHA384");
        this.twoWayField.setText("y");
        this.caCertField.setText("xxx/xxx/ca.cert");
        this.clientCertField.setText("xxx/xxx/client.cert");
        this.clientP12Field.setText("xxx/xxx/client.key");
        this.requestsStringField.setText("GET /1k.html HTTP1.0\r\n");
    }
    /**
     * 界面与Sampler之间的数据交换
     * 该方法用于把Sampler中的数据加载到界面中。
     * 在实现自己的逻辑之前,先调用一下父类的方法super.configure(el),这样可以确保框架自动为你加载一些缺省数据,比如Sampler的名字。
     * **/
    @Override
    public void configure(TestElement el){
        super.configure(el);
        HttpsSampler sampler = (HttpsSampler) el;
        this.sslVersionField.setText(sampler.getHttpsSslVersion());
        this.cipherField.setText(sampler.getHttpsCipher());
        this.twoWayField.setText(sampler.getHttpsTwoWay());
        this.caCertField.setText(sampler.getHttpsCa());
        this.clientCertField.setText(sampler.getHttpsClientCert());
        this.clientP12Field.setText(sampler.getHttpsClientP12());
        this.requestsStringField.setText(sampler.getHttpsRequest());
    }
    private void setupSamplerProperties(HttpsSampler sampler) {
        this.configureTestElement(sampler);
        sampler.setSslVersion(this.sslVersionField.getText());
        sampler.setCipher(this.cipherField.getText());
        sampler.setHttpsTwoWay(this.twoWayField.getText());
        sampler.setHttpsCa(this.caCertField.getText());
        sampler.setHttpsClientCert(this.clientCertField.getText());
        sampler.setHttpsClientP12(this.clientP12Field.getText());
        sampler.setHttpsRequest(this.requestsStringField.getText());
    }
    /**gui显示sample的名称**/
    @Override
    public String getStaticLabel() {
        return "Https Sampler";
    }
    @Override
    public String getLabelResource() {
        throw new IllegalStateException("This shouldn't be called");
    }
    /**
     * 这个方法用于把界面的数据移到Sampler中,刚好与上面的方法相反。
     * 在调用自己的实现方法之前,请先调用一下super.configureTestElement(e),这个会帮助移到一些缺省的数据。
     * **/
    @Override
    public void modifyTestElement(TestElement testElement) {
        HttpsSampler sampler = (HttpsSampler) testElement;
        this.setupSamplerProperties(sampler);
    }
}
4.3 准备Java的采样器
新建org.apache.jmeter.protocol.https.sampler 继承 org.apache.jmeter.samplers.AbstractSampler 实现 org.apache.jmeter.testelement.TestStateListener接口
重写函数
//该方法是JMeter实现对目标系统发起请求实际工作的地方
public SampleResult sample(Entry entry)
这个4个方法必须覆写,否则无法识别
@Override
public void testStarted() {
}
@Override
public void testStarted(String s) {
}
@Override
public void testEnded() {
    this.testEnded("local");
}
@Override
public void testEnded(String s) {
}
全代码
package org.apache.jmeter.protocol.https.sampler;
import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.TestStateListener;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
public class HttpsSampler extends AbstractSampler implements TestStateListener {
    private static final long serialVersionUID = 1L;
    private static final String HTTPS_SSL_VERSION = "https.sslVersion";
    private static final String HTTPS_CIPHER = "https.cipher";
    private static final String HTTPS_TWO_WAY= "https.twoWay";
    private static final String HTTPS_CA = "https.caCert";
    private static final String HTTPS_CLIENT_CERT = "https.clientCert";
    private static final String HTTPS_CLIENT_P12 = "https.clientP12";
    private static final String HTTPS_REQUEST = "https.requestsString";
    private static final Logger log = LoggingManager.getLoggerForClass();
    // 构造函数要为pubilc
    public HttpsSampler(){
        setName("Https Sampler");
    }
    /**
     * 该方法是JMeter实现对目标系统发起请求实际工作的地方
     * **/
    @Override
    public SampleResult sample(Entry entry) {
        SampleResult result = new SampleResult();
        result.setSampleLabel(getName());
        result.sampleStart();
        try {
            /**
             * 采样器执行code处
             * **/
            result.setRequestHeaders("请求头---请求头展示数据");
            result.setSamplerData("设置采样器数据");
            if (!getHttpsSslVersion().startsWith("TLS")) {
                // stop stopwatch
                result.sampleEnd();
                result.setSuccessful(false);
                // 设置取样器结果里面响应信息
                result.setResponseMessage("ssl不为TLS开头,采样失败(示例)");
                result.setDataType(org.apache.jmeter.samplers.SampleResult.TEXT);
                result.setResponseCode("FAILED");
                // 设置响应数据的响应body
                result.setResponseData("响应信息---响应体展示数据", null);
                // 设置响应数据的响应header
                result.setResponseHeaders("响应头信息---响应头展示数据");
            }else {
                result.sampleEnd();
                result.setSuccessful(true);
                result.setResponseCodeOK();
            }
        } catch (Exception e) {
            result.sampleEnd(); // stop stopwatch
            result.setSuccessful(false);
            result.setResponseMessage("Exception: " + e);
            // get stack trace as a String to return as document data
            java.io.StringWriter stringWriter = new java.io.StringWriter();
            e.printStackTrace(new java.io.PrintWriter(stringWriter));
            result.setResponseData(stringWriter.toString(), null);
            result.setDataType(org.apache.jmeter.samplers.SampleResult.TEXT);
            result.setResponseCode("FAILED");
        }
        return result;
    }
    public void setSslVersion(String sslVersion){
        setProperty(HTTPS_SSL_VERSION, sslVersion);
    }
    public void setCipher(String cipher){
        setProperty(HTTPS_CIPHER, cipher);
    }
    public void setHttpsTwoWay(String twoWay){
        setProperty(HTTPS_TWO_WAY, twoWay);
    }
    public void setHttpsCa(String ca){
        setProperty(HTTPS_CA, ca);
    }
    public void setHttpsClientCert(String clientCert){
        setProperty(HTTPS_CLIENT_CERT, clientCert);
    }
    public void setHttpsClientP12(String clientP12){
        setProperty(HTTPS_CLIENT_P12, clientP12);
    }
    public void setHttpsRequest(String requestsString){
        setProperty(HTTPS_REQUEST, requestsString);
    }
    public String getHttpsSslVersion(){
        return getPropertyAsString(HTTPS_SSL_VERSION);
    }
    public String getHttpsCipher(){
        return getPropertyAsString(HTTPS_CIPHER);
    }
    public String getHttpsTwoWay(){
        return getPropertyAsString(HTTPS_TWO_WAY);
    }
    public String getHttpsCa(){
        return getPropertyAsString(HTTPS_CA);
    }
    public String getHttpsClientCert(){
        return getPropertyAsString(HTTPS_CLIENT_CERT);
    }
    public String getHttpsClientP12(){
        return getPropertyAsString(HTTPS_CLIENT_P12);
    }
    public String getHttpsRequest(){
        return getPropertyAsString(HTTPS_REQUEST);
    }
    @Override
    public void testStarted() {
    }
    @Override
    public void testStarted(String s) {
    }
    @Override
    public void testEnded() {
        this.testEnded("local");
    }
    @Override
    public void testEnded(String s) {
    }
}
5. 打包&部署
maven install后会在target/下会有打包好的jar包。

然后将jar包拷贝到lib/ext/下,启动JMeter。选取新增的取样器即可。

6. 参考文章
JMeter自定义采样器插件开发的更多相关文章
- elasticsearch 自定义similarity 插件开发
		转自:http://www.chepoo.com/elasticsearch-similarity-custom-plug-in-development.html 在搜索开发中,我们要修改打分机制,就 ... 
- JMeter自定义HTTP组件
		JMeter是一个优秀的开源项目,我们可以在jmeter的官网了解到如何使用和如何二次开发:https://jmeter.apache.org/ 因工作需要,最近做了一个JMeter自定义的http组 ... 
- Jmeter自定义编写Java代码调用socket通信
		一.前言 最近需要测试一款手机游戏的性能,找不到啥录制脚本的工具,然后,另外想办法.性能测试实际上就是对服务器的承载能力的测试,和各种类型的手机客户端没有啥多大关系,手机再好,服务器负载不了,也不能够 ... 
- jmeter自定义并发用户数图形插件介绍
		Stepping Thread Group马上要被废弃了,废弃原因不知道,官方推荐使用 BlazeMeter Inc.公司贡献的插件Concurrency Thread Group,配合 Throug ... 
- Jmeter自定义Java请求开发
		一.本次实验目的 IDEA新建maven项目,使用java开发自定义jmeter的请求. 本次开发使用的代码,会百度云分享给大家. 二.本次实验环境 Idea 2017.02 Jmeter 5.1.1 ... 
- 9.Jmeter自定义Sample(自定义测试内容)完成测试
		问题:在某些场景下我们会发现Jmeter里面提供的各种Sample不能满足自己的需求,应为这个世界上的压力测试的逻辑本来就是千变万化的,所以这个时候我们如果自己实现一套测试逻辑(当Jmeter的基本e ... 
- ionic2 自定义cordova插件开发以及使用 (Android)
		如何写一个cordova 用于ionic2项目中呢,在搜索了一番之后,千篇一律,我都怀疑那些文章是不是全部都是复制来复制去的,而且都不是很详细.我自己也捣鼓了一下午,踩了很多坑.所以特此写这下这篇,记 ... 
- Jmeter自定义Java请求,继承AbstractJavaSamplerClient
		首先,使用Eclipse新建一个项目,然后从Jmeter的lib/ext目录下中拷贝ApacheJMeter_java.jar和ApacheJMeter_core.jar两个文件,然后引入这两个JAR ... 
- [转]jmeter 自定义测试脚本
		http://blog.csdn.net/kash_chen007/article/details/37690411 http://wangym.iteye.com/blog/731729 1.创建一 ... 
随机推荐
- 从崩溃的选课系统,论为什么更安全的 HTTPS 协议没有被全面采用
			尽人事,听天命.博主东南大学研究生在读,热爱健身和篮球,正在为两年后的秋招准备中,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 C ... 
- Power Query 合并数据
			1 导入数据 合并数据 筛选字段 关闭并上载 
- 24_MySQL插入insert语句
			本节涉及SQL语句: -- MYSQL 基础操作 1.插入insert语句 INSERT INTO t_dept(deptno,dname,loc) VALUES(70,"后勤部" ... 
- WPF 关于ComboBox在前台绑定XML数据的一些方法,使用XML数据提供器 XmlDataProvider
			关于使用 数据提供器:XmlDataProvider 的一些问题,以及在WPF中是如何使用的一些介绍,还有踩到的一些坑,希望其他和我碰到一样问题的,可以更快的解决. 首先,要求是 在WPF 的前台代码 ... 
- PacketStream 和 honeygain 推荐一款可以通过分享带宽赚钱的APP
			方法很简单,只需打开网址 PacketStream 或 honeygain 注册,下载客户端登录即可分享带宽.价格0.1美元/G. 绑定paypal账号即可提现.退出客户端即可停止分享带宽. 
- Django框架-cookie和session以及中间件
			目录 一.cookie 和 session 1.为什么会有这些技术 2. cookie 2.1 Django如何设置cookie 2.2 Django如何获取cookie 2.3 Django如何设置 ... 
- 聊一聊JVM
			JVM 什么是JVM?  JVM是java虚拟机的缩写,本质上是一个程序,能识别.class字节码文件(.java文件编译后产生的二进制代码),并且能够解析它的指令,最终调用操作系统上的函数,完成我 ... 
- HDOJ-2896(AC自动机+文本串中出现了哪几个模板串)
			病毒侵袭 HDOJ-2896 主要使用AC自动机解决,其次在query函数中改变一下,用来记录每个模板串出现的次数,还有insert函数中记录模板串的编号 需要注意最好使用结构体,而且不能一次性使用m ... 
- 过多if - else 的问题, 以及策略模式 + 反射解决方法
			策略模式解决if - else 的代码 业务场景: 外包企业的审批人需要审批打卡的场景: 审批人分为多种不同的级别,多种级别中具有方式相同但是内容不同的操作:审批. 原来场景: 有前端传来审批人参数, ... 
- POJ_1797 Heavy Transportation 【最大生成树的最小边】
			一.题目 POJ1797 二.分析 题意就是让你找到从1到n的一条路,由于边的最大称重限制,你需要确定限制的最小值,也就是能运输的最大值. 可以结合最小生成树想,利用并查集,然后不断更新答案即可,需要 ... 
