高手的存在,就是让服务10亿人的时候,你感觉只是为你一个人服务......

Jmeter自定义函数

目录
  1. 1. 学习Jmeter自带函数的实现方法
  2. 2. 实现加密函数

Jmeter自带的函数有时满足不了日常压测的需求,需要根据业务情况做定制化的扩展,这时就需要自定义函数。

在编写自己的函数之前,可以先了解Jmeter自带的函数是如何实现的,然后我们模仿的写写就可以了,没什么难度。


学习Jmeter自带函数的实现方法

第一步:下载最新的Jmeter源码,我这里下载的apache-jmeter-5.3_src.tgz
http://jmeter.apache.org/download_jmeter.cgi

第二步:找到函数实现
在源码包中找到functions文件夹,里面放的就是Jmeter自带的函数实现。
\apache-jmeter-5.3\src\functions\src\main\java\org\apache\jmeter\functions

我们找一个简单常用的_Random函数,来看看是如何实现的
Alt text

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package org.apache.jmeter.functions;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.Sampler;
import org.apache.jmeter.threads.JMeterVariables;
import org.apache.jmeter.util.JMeterUtils;

/**
* Provides a Random function which returns a random long integer between a min
* (first argument) and a max (second argument).
* @since 1.9
*/

public class Random extends AbstractFunction {

private static final List<String> desc = new LinkedList<>();
private static final String KEY = "__Random"; //Jmeter函数助手显示的函数名称,以_开头

static {
desc.add(JMeterUtils.getResString("minimum_param")); //入参
desc.add(JMeterUtils.getResString("maximum_param")); //入参
desc.add(JMeterUtils.getResString("function_name_paropt")); //入参
}

private CompoundVariable varName;
private CompoundVariable minimum;
private CompoundVariable maximum;

/**
* No-arg constructor.
*/

public Random() {
}

/** JMeter会将上次运行的SampleResult和当前的Sampler作为参数传入到该方法里,返回值就是在运行该function后得到的值,以String类型返回。
逻辑放在这里面就可以了。
*/

@Override
public String execute(SampleResult previousResult, Sampler currentSampler)
throws InvalidVariableException {


long min = Long.parseLong(minimum.execute().trim());
long max = Long.parseLong(maximum.execute().trim());

long rand = ThreadLocalRandom.current().nextLong(min, max+1);

String randString = Long.toString(rand);

if (varName != null) {
JMeterVariables vars = getVariables();
final String varTrim = varName.execute().trim();
if (vars != null && varTrim.length() > 0){// vars will be null on TestPlan
vars.put(varTrim, randString);
}
}

return randString;

}

/** setParameters函数作用就是获取函数输入框界面输入的值,将输入的值传递给execute */
@Override
public void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException {
checkParameterCount(parameters, 2, 3);
Object[] values = parameters.toArray();

minimum = (CompoundVariable) values[0];
maximum = (CompoundVariable) values[1];
if (values.length>2){
varName = (CompoundVariable) values[2];
} else {
varName = null;
}

}

/** getReferenceKey函数是提供一个在Jmeter函数助手显示的函数名称 */
@Override
public String getReferenceKey() {
return KEY;
}

/** getArgumentDesc函数用来获取对输入参数的描述 */
@Override
public List<String> getArgumentDesc() {
return desc;
}

}

可以看到,Random类中主要实现了4个方法:

1
2
3
4
execute(SampleResult previousResult, Sampler currentSampler)
setParameters(Collection<CompoundVariable> parameters)
getReferenceKey()
getArgumentDesc()

如果我们要实现自己的函数,可以实现这4个方法,另外还需要满足Jmeter自身设计中类加载的一些规则,总体来说满足2点即可:

1、实现function的类的package声明必须包含”.functions”。

1
package org.apache.jmeter.functions;

2、继承AbstractFunction类,然后实现父类的四个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package org.apache.jmeter.functions;

import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.Sampler;
import java.util.Collection;
import java.util.List;

public class Testfunction extends AbstractFunction {
@Override
public String execute(SampleResult previousResult, Sampler currentSampler) throws InvalidVariableException {
return null;
}
@Override
public void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException {
}
@Override
public String getReferenceKey() {
return null;
}
@Override
public List<String> getArgumentDesc() {
return null;
}
}

实现加密函数

业务中需要对http请求中的入参做RSA加密处理,这里实现一个简单的加密函数。两个入参,第一个入参为加密的字符串,第二个入参为公钥key。

第一步:新建maven工程jmeterfunction,依赖如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?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>jmeter-function</groupId>
<artifactId>jmeter-function</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_functions</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_core</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
</project>

第二步:
新建package:org.apache.jmeter.functions

新建函数EncryptionUtils并继承AbstractFunction

Alt text

第三步:实现4个方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//自定义function的描述
private static final List<String> desc = new LinkedList<String>( );

//两个入参
static {
desc.add(JMeterUtils.getResString("submitPwd"));
desc.add(JMeterUtils.getResString("PUBLIC_PWD_RSA"));
}
//function名称
private static final String KEY = "__MyEncryptionFunc";


private static final int MAX_PARA_COUNT = 2;
private static final int MIN_PARA_COUNT = 2;

//传入参数的值
private CompoundVariable[] values;

@Override
public String execute(SampleResult previousResult, Sampler currentSampler) throws InvalidVariableException {
try {
String submitPwd = values[0].execute( );
String PUBLIC_PWD_RSA = values[1].execute( );
return getEncryPwdStr(submitPwd, PUBLIC_PWD_RSA);//getEncryPwdStr() 业务方提供的RSA加解密的算法,涉及公钥秘钥这里不提供源码
} catch (Exception ex) {
throw new InvalidVariableException(ex);
}
}

@Override
public void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException {
checkParameterCount(parameters, MIN_PARA_COUNT, MAX_PARA_COUNT); //检查参数的个数是否正确
values = parameters.toArray(new CompoundVariable[parameters.size( )]); //将值存入类变量中
}

@Override
public String getReferenceKey() {
return KEY;
}

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

第四步: 编译,打包;将jar文件放到jmeter的lib/ext文件夹中,重启Jmeter即可。

打开Jmeter,即可使用我们自己编写的函数。
Alt text