当前位置: 首页 > 测试知识 > JMeter中Java请求取样器开发入门与进阶
JMeter中Java请求取样器开发入门与进阶
2026-08-11 作者cwb 浏览次数53

JMeter的Java请求取样器(Java Request Sampler)是性能测试中的一把万能钥匙,当需要的协议、逻辑无法被标准取样器覆盖时,就可以通过它编写定制化代码。

一,第一个 Java 请求


什么时候需要它?

测试自定义 TCP/UDP协议、RPC框架(如 Dubbo、gRPC)、消息队列(Kafka、RabbitMQ);需要复杂加密/解密、签名算法;调用硬件 SDK 或内部库;任何HTTP、JDBC等标准取样器搞不定的场景。


开发环境准备:

JDK 8+(与运行 JMeter 的版本一致);Maven或Gradle(推荐,管理依赖);JMeter 安装目录,依赖在 lib/ext 和 lib 下。


Maven 依赖(最小化):

<dependencies>

<dependency>

<groupId>org.apache.jmeter</groupId>

<artifactId>ApacheJMeter_core</artifactId>

<version>5.6.3</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>org.apache.jmeter</groupId>

<artifactId>ApacheJMeter_java</artifactId>

<version>5.6.3</version>

<scope>provided</scope>

</dependency>

</dependencies>


scope=provided 表示打包时不带走 JMeter 已提供的 jar,避免冲突。

实现接口:

推荐继承 AbstractJavaSamplerClient,需要以下四个方法:

getDefaultParameters():定义在 JMeter UI 中显示的参数,加载类时调用一次。

setupTest(JavaSamplerContext ctx):初始化资源(每个线程独立),每个线程启动前调用一次。

runTest(JavaSamplerContext ctx):执行核心测试逻辑,每次迭代都调用,必须返回 SampleResult。

teardownTest(JavaSamplerContext ctx):清理资源,每个线程结束后调用一次。


一个最简单的例子(生成随机数字作为响应):

代码示例:


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.apache.logging.log4j.LogManager;

import org.apache.logging.log4j.Logger;


public class RandomNumberSampler extends AbstractJavaSamplerClient {


private static final Logger log = LogManager.getLogger(RandomNumberSampler.class);


@Override

public Arguments getDefaultParameters() {

Arguments args = new Arguments();

args.addArgument("min", "1");

args.addArgument("max", "100");

return args;

}


@Override

public void setupTest(JavaSamplerContext context) {

log.info("Thread setup: min={}, max={}",

context.getParameter("min"), context.getParameter("max"));

}


@Override

public SampleResult runTest(JavaSamplerContext context) {

SampleResult result = new SampleResult();

result.sampleStart();


try {

int min = context.getIntParameter("min");

int max = context.getIntParameter("max");

int randomNum = min + (int)(Math.random() * (max - min + 1));

result.setResponseData("Random number: " + randomNum, "UTF-8");

result.setResponseCode("200");

result.setResponseMessage("Success");

result.setSuccessful(true);

} catch (Exception e) {

result.setResponseCode("500");

result.setResponseMessage(e.toString());

result.setSuccessful(false);

} finally {

result.sampleEnd();

}

return result;

}


@Override

public void teardownTest(JavaSamplerContext context) {

log.info("Thread teardown.");

}

}


部署与运行:

用 Maven 打包:mvn clean package,得到 your-jar.jar;将 jar 复制到 JMETER_HOME/lib/ext/;重启 JMeter;在测试计划中添加线程组 → 取样器 → Java 请求,在“类名称”下拉框中选择 RandomNumberSampler;下方会显示定义的参数 min、max,可直接修改;运行测试,查看结果树即可看到响应数据。


二、进阶深度整合复杂场景


与 JMeter 变量交互

通过 JavaSamplerContext 可以拿到 JMeterVariables,实现数据传递:


String userName = context.getJMeterVariables().get("username");

context.getJMeterVariables().put("token", calculateToken(userName));


还可以获取更丰富的上下文:


JMeterContext jmctx = context.getJMeterContext();

jmctx.getPreviousResult();

jmctx.getCurrentSampler();

jmctx.getThreadNum();


精细化控制 SampleResult

代码示例:


SampleResult result = new SampleResult();

result.setSampleLabel("我的Java请求");

result.sampleStart();


// 模拟子步骤

SampleResult sub = new SampleResult();

sub.sampleStart();

// ... 执行子操作

sub.sampleEnd();

sub.setSuccessful(true);

result.addSubResult(sub);


result.setResponseData(data, "UTF-8");

result.setDataType(SampleResult.TEXT); // 或 SampleResult.BINARY

result.setResponseHeaders("..."); // 若模拟HTTP,可设置头

result.setLatency(latency);

result.setSuccessful(true);

result.sampleEnd();


必须配对调用 sampleStart() 和 sampleEnd()。


多线程安全处理

若不勾选线程间共享,每个线程独立实例,setupTest/teardownTest 按线程独立执行,成员变量可安全存储线程私有资源。

若必须共享实例,需自行处理同步,或用 ThreadLocal 管理资源:


private ThreadLocal<MyClient> clientHolder = ThreadLocal.withInitial(MyClient::new);


@Override

public SampleResult runTest(JavaSamplerContext context) {

MyClient client = clientHolder.get();

// ...

}


使用 JMeter 属性与日志


import org.apache.jmeter.util.JMeterUtils;

String timeout = JMeterUtils.getPropDefault("my.timeout", "3000");

log.info("全局超时配置: {}", timeout);


日志输出到 jmeter.log,级别在 log4j2.xml 中调整。


实现复杂协议示例:一个简单的加密签名请求


代码示例:

public SampleResult runTest(JavaSamplerContext ctx) {

SampleResult sr = new SampleResult();

sr.sampleStart();

try (Socket socket = new Socket("127.0.0.1", 9000)) {

String body = ctx.getParameter("body");

String sign = md5(body + "secretKey");

String request = body + "|sign=" + sign;

// 发送与接收...

String response = readFromSocket(socket);

sr.setResponseData(response, "UTF-8");

sr.setSuccessful(true);

} catch (Exception e) {

sr.setSuccessful(false);

sr.setResponseMessage(e.getMessage());

} finally {

sr.sampleEnd();

}

return sr;

}


打断测试:实现 Interruptible 接口

若有阻塞操作,实现 Interruptible,以便 JMeter 停止时能立即中断:


public class MySampler extends AbstractJavaSamplerClient implements Interruptible {

private volatile boolean interrupted = false;


@Override

public boolean interrupt() {

interrupted = true;

return true;

}


@Override

public SampleResult runTest(JavaSamplerContext ctx) {

SampleResult result = new SampleResult();

result.sampleStart();

while (!interrupted) {

// 等待消息...

}

// ...

}

}


调试技巧

IDE 远程调试:启动 JMeter 加参数 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005,然后在 IDE Attach 到 5005 端口。

增加日志:多输出 log.debug/error 关键中间值。

查看 jmeter.log 或控制台启动 JMeter 观察实时输出。


Maven 打包最佳实践

使用 maven-shade-plugin 合并第三方依赖,但排除 JMeter 已有的依赖:


<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.5.0</version> <executions> <execution> <phase>package</phase> <goals><goal>shade</goal></goals> <configuration> <artifactSet> <excludes> <exclude>org.apache.jmeter:*</exclude> <exclude>org.apache.commons:*</exclude> </excludes> </artifactSet> </configuration> </execution> </executions>

</plugin>


 简单做法:直接丢编译后的 class 或 jar 到 lib/ext,配合远程调试验证。


三、Java请求对比JSR223取样器

性能:Java 请求是编译执行,极快;JSR223 (Groovy) 预编译后也很快,但略低于原生 Java。

依赖管理:Java 请求需将依赖打包为 jar 放入 lib/ext;JSR223 可动态加载脚本,但复杂逻辑难以维护。

可复用性:Java 请求可打包为公共 jar,强复用;JSR223 脚本容易复制粘贴,易失控。

适用场景:Java 请求适合固定、复杂、性能敏感的协议;JSR223 适合快速原型、一次性脚本和简单逻辑。


四、总结

继承AbstractJavaSamplerClient,实现runTest,掌握getDefaultParameters和SampleResult的使用。

与 JMeterVariables 交互,处理多线程安全,精细化控制结果,实现Interruptible支持停止。

将自定义Java请求作为JMeter的万能扩展,配合命令行和CI/CD,构建性能测试平台。


文章标签: 软件测试 测试工具
咨询软件测试