概述
二次开发JmeterGUI的源码需要有swing基础支持的支撑,不熟悉请自行学习,在此不做赘述
启动加载
src/core中org.apache.jmeter资源包,这是启动jmeter GUI的入口。
jmeter启动的入口类为NewDriver,启动核心为JMeter的start方法,运行完start方法,jmeter的界面就启动完成了。
此包中还有三个类
类名 | 作用 |
---|---|
DynamicClassLoader | 动态加载资源 |
ProxyAuthenticator | 为jmeter设置代理用的 |
SplashScreen | 启动时显示启动界面,在JMeter.startGui中调用 |
NewDriver类中主要完成
1、初始classpath
2、添加标准jar包
3、加载日志配置文件
private static void setLoggingProperties(String[] args) {
String jmLogFile = getCommandLineArgument(args, 'j', "jmeterlogfile");
if (jmLogFile != null && !jmLogFile.isEmpty()) {
jmLogFile = replaceDateFormatInFileName(jmLogFile);
System.setProperty("jmeter.logfile", jmLogFile);
} else if (System.getProperty("jmeter.logfile") == null) {
System.setProperty("jmeter.logfile", "jmeter.log");
}
String jmLogConf = getCommandLineArgument(args, 'i', "jmeterlogconf");
File logConfFile = null;
if (jmLogConf != null && !jmLogConf.isEmpty()) {
logConfFile = new File(jmLogConf);
} else if (System.getProperty("log4j.configurationFile") == null) {
logConfFile = new File("log4j2.xml");
if (!logConfFile.isFile()) {
logConfFile = new File(JMETER_INSTALLATION_DIRECTORY, "bin"+File.separator+"log4j2.xml");
}
}
if (logConfFile != null) {
System.setProperty("log4j.configurationFile", logConfFile.toURI().toString());
}
}
4、实例化org.apache.jmeter.JMeter,执行org.apache.jmeter.JMeter中的start方法
Class<?> initialClass = loader.loadClass("org.apache.jmeter.JMeter");
Object instance = initialClass.newInstance();
Method startup = initialClass.getMethod("start", new Class[] { new String[0].getClass() });
startup.invoke(instance, new Object[] { args });
Jmeter类的作用
1、初始化配置文件
private void initializeProperties(CLArgsParser parser) {……}
2、解析命令行参数
根据解析的命令行参数,执行不同的动作
if (parser.getArgumentById(VERSION_OPT) != null) {
displayAsciiArt();
} else if (parser.getArgumentById(HELP_OPT) != null) {
displayAsciiArt();
System.out.println(JMeterUtils.getResourceFileAsText("org/apache/jmeter/help.txt"));
} else if (parser.getArgumentById(OPTIONS_OPT) != null) {
displayAsciiArt();
System.out.println(CLUtil.describeOptions(options).toString());
} else if (parser.getArgumentById(SERVER_OPT) != null) {
……
} else if (parser.getArgumentById(NONGUI_OPT) == null) { // not non-GUI => GUI
startGui(testFile);
startOptionalServers();
} else { // NON-GUI must be true
extractAndSetReportOutputFolder(parser);
CLOption rem = parser.getArgumentById(REMOTE_OPT_PARAM);
if (rem == null) {
rem = parser.getArgumentById(REMOTE_OPT);
}
CLOption jtl = parser.getArgumentById(LOGFILE_OPT);
String jtlFile = null;
if (jtl != null) {
jtlFile = processLAST(jtl.getArgument(), ".jtl"); // $NON-NLS-1$
}
CLOption reportAtEndOpt = parser.getArgumentById(REPORT_AT_END_OPT);
if(reportAtEndOpt != null && jtlFile == null) {
throw new IllegalUserActionException(
"Option -"+ ((char)REPORT_AT_END_OPT)+" requires -"+((char)LOGFILE_OPT )+ " option");
}
startNonGui(testFile, jtlFile, rem, reportAtEndOpt != null);
startOptionalServers();
……
示例源码中用的最多的部分是startGui和startNonGui、其中NONGUI_OPT在Jmeter中被定义为private static final int NONGUI_OPT= ‘n’; 即对应命令行-n参数
3、设置代理setProxy、启动可选服务器startOptionalServers
4、更新ClassLoader
5、设置一些属性
long now=System.currentTimeMillis();
JMeterUtils.setProperty("START.MS",Long.toString(now));
Date today=new Date(now);
JMeterUtils.setProperty("START.YMD",new SimpleDateFormat("yyyyMMdd").format(today));
JMeterUtils.setProperty("START.HMS",new SimpleDateFormat("HHmmss").format(today));
6、将测试文件(.jmx文件)解析成HashTree
if (testFile != null) {
try {
File f = new File(testFile);
log.info("Loading file: {}", f);
FileServer.getFileServer().setBaseForScript(f);
HashTree tree = SaveService.loadTree(f);
GuiPackage.getInstance().setTestPlanFile(f.getAbsolutePath());
Load.insertLoadedTree(1, tree);
} catch (ConversionException e) {
log.error("Failure loading test file", e);
JMeterUtils.reportErrorToUser(SaveService.CEtoString(e));
} catch (Exception e) {
log.error("Failure loading test file", e);
JMeterUtils.reportErrorToUser(e.toString());
}
7、创建一个StandardJMeterEngine,并把测试的工作交给JMeterEngine
List<JMeterEngine> engines = new LinkedList<>();
tree.add(tree.getArray()[0], new ListenToTest(remoteStart && remoteStop ? engines : null, reportGenerator));
println("Created the tree successfully using "+testFile);
if (!remoteStart) {
JMeterEngine engine = new StandardJMeterEngine();
engine.configure(tree);
long now=System.currentTimeMillis();
println("Starting the test @ "+new Date(now)+" ("+now+")");
engine.runTest();
engines.add(engine);
} else {
java.util.StringTokenizer st = new java.util.StringTokenizer(remoteHostsString, ",");//$NON-NLS-1$
List<String> hosts = new LinkedList<>();
while (st.hasMoreElements()) {
hosts.add((String) st.nextElement());
}
DistributedRunner distributedRunner=new DistributedRunner(this.remoteProps);
distributedRunner.setStdout(System.out); // NOSONAR
distributedRunner.setStdErr(System.err); // NOSONAR
distributedRunner.init(hosts, tree);
engines.addAll(distributedRunner.getEngines());
distributedRunner.start();
}
startUdpDdaemon(engines);
监听所有的JMeterEngine,当接收到GUI的StopTestNow/Shutdown等命令时候来调用JMeterEngine相应的方法
startGui:作用启动常规界面、加载启动界面SplashScreen、绑定监听事件、启动主界面
MainFrame main = new MainFrame(treeModel, treeLis);
ComponentUtil.centerComponentInWindow(main, 80);
main.setVisible(true);
runNonGui
启动非界面测试
jmeter界面和响应事件的函数分别在org.apache.jmeter.gui、org.apache.jmeter.gui.action 后续在研究
原文连接 http://blog.csdn.net/yue530tomtom/article/details/77983284