Jmeter(7)----开发自定义函数

本文介绍如何在JMeter中创建自定义函数以处理图片,包括将图片转换为BASE64字符串及字节十进制数组。通过Maven项目结构展示如何引入依赖,并提供了具体的Java代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意:包名不能为Jmeter,天坑!!!

1、POM文件

<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>Plguin.Jmeter</groupId>
	<artifactId>ImageBase64</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<!-- https://mvnrepository.com/artifact/org.apache.jmeter/ApacheJMeter_core -->
	<dependencies>
		<dependency>
			<groupId>org.apache.jmeter</groupId>
			<artifactId>ApacheJMeter_core</artifactId>
			<version>3.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.jmeter</groupId>
			<artifactId>ApacheJMeter_java</artifactId>
			<version>3.0</version>
		</dependency>
	</dependencies>
</project>
2、自定义函数:引入Image图片,进行BASE64加密

package org.apache.functions;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.functions.AbstractFunction;
import org.apache.jmeter.functions.InvalidVariableException;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.Sampler;
import org.apache.jmeter.threads.JMeterVariables;
import sun.misc.BASE64Encoder;

public class ImageBase64 extends AbstractFunction {
	//显示的参数名字
	private static final List<String> desc = new LinkedList();
	//显示的函数名字
	private static final String KEY = "__ImageBase64";
	//参数值
	private Object[] values;
	
	static {
		desc.add("String to calculate Base64 hash");
		desc.add("Name of variable in which to store the result (optional)");
	}
	
	public  String execute(SampleResult paramSampleResult, Sampler paramSampler)
			throws InvalidVariableException {
		StringBuffer stBuffer = new StringBuffer();
		try {
			String url = ((CompoundVariable)this.values[0]).execute();
<span style="white-space:pre">			</span>url = new String(url.getBytes("UTF-8"),"UTF-8");
<span style="white-space:pre">			</span>InputStream input = new FileInputStream(url);
			byte[] by = new byte[3072];
			int status = -1;
			while((status = input.read(by))>-1)
			{
				stBuffer.append(new BASE64Encoder().encode(by));
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return stBuffer.toString();
	}

	//获取参数值
	public synchronized void setParameters(Collection<CompoundVariable> paramCollection)
			throws InvalidVariableException {
		//检查参数,我也搞不懂是毛线意思,NND
		checkMinParameterCount(paramCollection, 1);
		this.values = paramCollection.toArray();
	}

	//返回函数名字
	public String getReferenceKey() {
		return KEY;
	}
	//返回参数名字
	public List<String> getArgumentDesc() {
		return desc;
	}

}

3、自定义函数:加载image图片,保存byte 10进制数组

package org.apache.functions;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.functions.AbstractFunction;
import org.apache.jmeter.functions.InvalidVariableException;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.Sampler;

public class ImageByte extends AbstractFunction {
	private static final List<String> desc = new LinkedList();
	private static final String KEY = "__ImageByte";
	private Object[] values;

	static {
		desc.add("String to calculate Base64 hash");
		desc.add("Name of variable in which to store the result (optional)");
	}

	public String execute(SampleResult paramSampleResult, Sampler paramSampler) throws InvalidVariableException {
		StringBuffer stBuffer = new StringBuffer();
		try {
			String url = ((CompoundVariable)this.values[0]).execute();
<span style="white-space:pre">			</span>url = new String(url.getBytes("UTF-8"),"UTF-8");
<span style="white-space:pre">			</span>InputStream input = new FileInputStream(url);
			byte[] by = new byte[3072];
			int num = -1;
			stBuffer.append("[");
			while ((num = input.read()) > -1) {
				stBuffer.append(num + ",");
			}
			stBuffer.deleteCharAt(stBuffer.lastIndexOf(","));
			stBuffer.append("]");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return stBuffer.toString();
	}

	public synchronized void setParameters(Collection<CompoundVariable> paramCollection)
			throws InvalidVariableException {
		checkMinParameterCount(paramCollection, 1);
		this.values = paramCollection.toArray();
	}

	public String getReferenceKey() {
		return KEY;
	}

	public List<String> getArgumentDesc() {
		return desc;
	}

}



<think>好的,用户现在想了解如何在JMeter开发自定义函数,并且需要教程和示例代码。用户之前已经询问过相关问题,我之前也提供了详细的步骤和代码示例,但用户现在又引用了另一个资料,里面提到两种发送Java请求的方式,其中一种是JMeter函数二次开发,可能希望更详细的指导。 首先,我需要回顾之前的回答,确保不重复但覆盖所有必要点。之前的回答已经包含开发环境准备、核心代码实现、部署使用和调试技巧。用户引用的新资料提到需要继承AbstractFunction类,并且包名以functions结尾,这些在之前的示例中已经涵盖,可能需要强调这些关键点。 用户的新引用还提到依赖包的位置,比如lib和ext目录,这可能需要在环境准备部分进一步说明,确保用户正确添加依赖。此外,用户可能对包命名和类继承的具体要求有疑问,需要明确说明。 另外,用户可能对代码中的参数处理和线程安全有疑问,特别是自定义函数在多线程下的行为。之前的回答提到多线程并发问题在相关问题里,但可能需要更详细地解释如何确保线程安全,比如在execute方法中避免共享变量。 还需要注意示例代码的正确性,比如使用UUID生成随机字符串是否满足需求,或者是否需要更复杂的逻辑。同时,部署步骤中提到的重启JMeter函数助手调用是否正确,是否需要更多细节,比如如何找到函数助手的位置。 用户可能遇到的常见问题包括包结构错误、依赖缺失、未重启JMeter导致函数未加载,或者参数处理不正确。在回答中需要提前预警这些问题,并提供解决方法,比如检查日志、确认JAR位置等。 最后,确保回答结构清晰,分步骤说明,代码示例正确,并且相关问题覆盖用户可能进一步的需求,比如调试、多线程处理、参数转换等。需要参考之前的回答,但根据新的引用内容补充细节,确保信息全面准确。</think>### JMeter自定义函数开发教程(附完整示例代码) 根据Apache JMeter官方扩展规范和实际开发经验[^1][^2],开发自定义函数需重点关注以下核心要素: --- #### 一、开发规范要点 1. **包命名要求**:必须包含`functions`后缀,如:`com.yourcompany.functions` 2. **类继承关系**:需继承`AbstractFunction`抽象类 3. **方法实现要求**:必须重写`execute()`, `setParameters()`, `getReferenceKey()`, `getArgumentDesc()`四个核心方法 4. **线程安全**:函数需支持多线程并发调用(避免使用类成员变量) --- #### 二、完整开发流程(示例:生成范围随机数函数) **1. 创建Maven项目** ```xml <dependencies> <!-- 核心依赖 --> <dependency> <groupId>org.apache.jmeter</groupId> <artifactId>ApacheJMeter_core</artifactId> <version>5.6.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.jmeter</groupId> <artifactId>ApacheJMeter_functions</artifactId> <version>5.6.2</version> <scope>provided</scope> </dependency> </dependencies> ``` **2. 实现函数逻辑(RangeRandom.java)** ```java package com.loadtest.functions; import org.apache.jmeter.engine.util.CompoundVariable; import org.apache.jmeter.functions.AbstractFunction; import org.apache.jmeter.samplers.SampleResult; import org.apache.jmeter.samplers.Sampler; import java.util.*; public class RangeRandom extends AbstractFunction { private static final String KEY = "__RangeRandom"; private static final List<String> DESC = Arrays.asList("最小值", "最大值"); private CompoundVariable minVal, maxVal; @Override public String execute(SampleResult sampleResult, Sampler sampler) { int min = Integer.parseInt(minVal.execute()); int max = Integer.parseInt(maxVal.execute()); return String.valueOf(new Random().nextInt(max - min + 1) + min); } @Override public void setParameters(Collection<CompoundVariable> parameters) { checkParameterCount(parameters, 2); Iterator<CompoundVariable> it = parameters.iterator(); minVal = it.next(); maxVal = it.next(); } @Override public String getReferenceKey() { return KEY; } @Override public List<String> getArgumentDesc() { return DESC; } } ``` **3. 构建与部署** ```bash mvn clean package # 生成target/your-function.jar cp target/your-function.jar ${JMETER_HOME}/lib/ext/ ``` --- #### 三、验证与调用 1. **JMeter重启后**,通过函数助手调用: ``` ${__RangeRandom(100,200)} ``` 2. **调试验证**:使用Debug Sampler查看参数传递 ```java // 调试代码片段 log.info("Generated value: " + vars.get("YOUR_VAR")); ``` --- #### 四、最佳实践建议 1. **参数校验**:在`execute()`方法中添加数值范围验证 ```java if (min >= max) throw new IllegalArgumentException("最小值必须小于最大值"); ``` 2. **性能优化**:使用`ThreadLocal<Random>`替代直接new Random() 3. **异常处理**:捕获`NumberFormatException`并返回友好提示 --- #### 五、常见问题排查 | 现象 | 解决方案 | |-------|----------| | 函数未加载 | 检查JAR文件是否在`lib/ext`目录 | | 参数数量错误 | 确认`setParameters()`中的参数数量检查 | | 类型转换失败 | 使用`CompoundVariable.execute()`获取字符串值后再转换 | | 多线程冲突 | 避免在类成员变量中存储状态数据[^3] |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值