一、Jmeter如何进行动态设置请求参数
- Jmeter使用占位符的方式进行动态替换请求参数内容。
HTTPSamplerProxy httpSamplerProxy = new HTTPSamplerProxy();
httpSamplerProxy.addArgument("data", "${data}");
- 那么替换占位符的数据是存放在哪里呢?答案就是替换的数据存放在每个线程的Context中。
当Jmeter创建每个Thread的时候都会创建一个Context,而Thread的Context我们可以通过JMeterContextService的getContext方法获取当前的线程的Context.
二、实现动态配置请求参数方式
CSV
Jmeter在图形化界面提供了CSV的方式进行动态配置请求参数。在Java代码中也可以通过CSV方式来进行实现,但是这种方式存在弊端,因为使用CSV是假设数据全部确定的情况下使用,如果我们所需要的请求参数的数据是不确定况下,我们就不可以使用CSV的方式进行处理。
Monitor
我们可以通过JMeterThread.java类发现,每个Sample都会调用SampleMonitor进行监视每个Sample,那么我们可以通过SampleMonitor来进行动态设置请求的参数。
JMeterThread.java
if (running) {
Sampler sampler = pack.getSampler();
sampler.setThreadContext(threadContext);
// TODO should this set the thread names for all the subsamples?
// might be more efficient than fetching the name elsewhere
sampler.setThreadName(threadName);
TestBeanHelper.prepare(sampler);
// Perform the actual sample
currentSampler = sampler;
if (!sampleMonitors.isEmpty()) {
for (SampleMonitor sampleMonitor : sampleMonitors) {
sampleMonitor.sampleStarting(sampler);
}
}
try {
result = sampler.sample(null);
} finally {
if (!sampleMonitors.isEmpty()) {
for (SampleMonitor sampleMonitor : sampleMonitors) {
sampleMonitor.sampleEnded(sampler);
}
}
}
currentSampler = null;
}
三、时序图
image.png三、代码实现
1. TestPlanLauncher.java
public class TestPlanLauncher {
public static void main(String[] args) {
// jemter 引擎
StandardJMeterEngine standardJMeterEngine = new StandardJMeterEngine();
// 设置不适用gui的方式调用jmeter
System.setProperty(JMeter.JMETER_NON_GUI, "true");
// 设置jmeter.properties文件,我们将jmeter文件存放在resources中,通过classload
String path = TestPlanLauncher.class.getClassLoader().getResource("jmeter.properties").getPath();
File jmeterPropertiesFile = new File(path);
if (jmeterPropertiesFile.exists()) {
JMeterUtils.loadJMeterProperties(jmeterPropertiesFile.getPath());
HashTree testPlanTree = new HashTree();
// 创建测试计划
TestPlan testPlan = new TestPlan("Create JMeter Script From Java Code");
String variableNames = "data";
// 创建http请求收集器
HTTPSamplerProxy examplecomSampler = createHTTPSamplerProxy(variableNames);
// 创建循环控制器
LoopController loopController = createLoopController();
// 创建线程组
ThreadGroup threadGroup = createThreadGroup();
// 线程组设置循环控制
threadGroup.setSamplerController(loopController);
// 将测试计划添加到测试配置树种
HashTree threadGroupHashTree = testPlanTree.add(testPlan, threadGroup);
// 将http请求采样器添加到线程组下
threadGroupHashTree.add(examplecomSampler);
//增加监视器
threadGroupHashTree.add(createHttpSampleMonitor(variableNames));
//增加结果收集
Summariser summer = null;
String summariserName = JMeterUtils.getPropDefault("summariser.name", "summary");
if (summariserName.length() > 0) {
summer = new Summariser(summariserName);
}
ResultCollector logger = new ResultCollector(summer);
testPlanTree.add(testPlanTree.getArray(), logger);
// 配置jmeter
standardJMeterEngine.configure(testPlanTree);
// 运行
standardJMeterEngine.run();
}
}
/**
* 创建线程组
*
* @return
*/
public static ThreadGroup createThreadGroup() {
ThreadGroup threadGroup = new ThreadGroup();
threadGroup.setName("Example Thread Group");
threadGroup.setNumThreads(1);
threadGroup.setRampUp(0);
threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
threadGroup.setScheduler(true);
threadGroup.setDuration(60);
threadGroup.setDelay(0);
return threadGroup;
}
/**
* 创建循环控制器
*
* @return
*/
public static LoopController createLoopController() {
// Loop Controller
LoopController loopController = new LoopController();
loopController.setLoops(-1);
loopController.setContinueForever(true);
loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
loopController.initialize();
return loopController;
}
/**
* 增加监视器
* @param variableNames
* @return
*/
public static HttpSampleMonitor createHttpSampleMonitor(String variableNames){
HttpSampleMonitor httpSampleMonitor = new HttpSampleMonitor();
if (StringUtils.isNoneBlank(variableNames)) {
httpSampleMonitor.setProperty("variableNames",variableNames);
}
return httpSampleMonitor;
}
/**
* 创建http采样器
*
* @return
*/
public static HTTPSamplerProxy createHTTPSamplerProxy(String variableNames) {
HTTPSamplerProxy httpSamplerProxy = new HTTPSamplerProxy();
httpSamplerProxy.addArgument(variableNames, "${"+variableNames+"}");
httpSamplerProxy.setDomain("www.baidu.com");
httpSamplerProxy.setPort(80);
httpSamplerProxy.setPath("/");
httpSamplerProxy.setMethod("GET");
httpSamplerProxy.setConnectTimeout("5000");
httpSamplerProxy.setUseKeepAlive(true);
httpSamplerProxy.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
return httpSamplerProxy;
}
}
2.HttpSampleMonitor
public class HttpSampleMonitor extends ConfigTestElement implements SampleMonitor {
private static final Logger log = LoggerFactory.getLogger(HttpSampleMonitor.class);
private static final long serialVersionUID = 23221L;
// 请求变量名以逗号分隔
private String variableNames;
// 分隔后的变量名
private String[] vars;
@Override
public void sampleStarting(Sampler sampler) {
final JMeterContext context = getThreadContext();
JMeterVariables threadVars = context.getVariables();
if (StringUtils.isNoneEmpty(getVariableNames())) {
vars = JOrphanUtils.split(getVariableNames(), ",");
trimVarNames(vars);
for (int i = 0; i < vars.length; i++) {
threadVars.put(vars[i], i + "");
}
}
}
@Override
public void sampleEnded(Sampler sampler) {
}
/**
* trim content of array varNames
*
* @param varsNames
*/
private void trimVarNames(String[] varsNames) {
for (int i = 0; i < varsNames.length; i++) {
varsNames[i] = varsNames[i].trim();
}
}
public String getVariableNames() {
this.variableNames = this.getPropertyAsString("variableNames");
return variableNames;
}
}
3.特别说明
- 在HTTPSamplerProxy中的addArgument方法设置的占位符需要使用${}的形式。并且要与HttpSampleMonitor中threadVars对象put的name保持一致。
- HttpSampleMonitor:我们的HttpSampleMonitor是为每一个线程增加一个HttpSampleMonitor,所以Jmeter需要对HttpSampleMonitor进行对象的clone和对clone的对象设置Property. 我们可以通过继承ConfigTestElement来获取对象拷贝和Property设置的能力。
Reference:
https://jmeter.apache.org/api/index.html
网友评论