运行 src->core->apache.jmeter->NewDriver
public static void main(String[] args) {
Thread.currentThread().setContextClassLoader(loader);
if (System.getProperty("log4j.configuration") == null) {// $NON-NLS-1$ $NON-NLS-2$
File conf = new File(jmDir, "bin" + File.separator + "log4j.conf");// $NON-NLS-1$ $NON-NLS-2$
System.setProperty("log4j.configuration", "file:" + conf);
}
try {
Class<?> initialClass = loader.loadClass("org.apache.jmeter.JMeter");// $NON-NLS-1$
Object instance = initialClass.newInstance();
Method startup = initialClass.getMethod("start", new Class[] { new String[0].getClass() });// $NON-NLS-1$
startup.invoke(instance, new Object[] { args });
} catch(Throwable e){
e.printStackTrace();
System.err.println("JMeter home directory was detected as: "+jmDir);
}
}
从上述代码中我们可以看出,其实之际上调用的是 src->core->apache.jmeter->Jmeter 的 start() 方法。而当我们打开 Jmeter 的 Gui 时,实际上调用的用的是 src->core->apache.jmeter->Jmeter 的 startGui() 方法
private void startGui(String testFile) {
String jMeterLaf = LookAndFeelCommand.getJMeterLaf();
try {
UIManager.setLookAndFeel(jMeterLaf);
} catch (Exception ex) {
log.warn("Could not set LAF to:"+jMeterLaf, ex);
}
PluginManager.install(this, true);
JMeterTreeModel treeModel = new JMeterTreeModel();
JMeterTreeListener treeLis = new JMeterTreeListener(treeModel);
final ActionRouter instance = ActionRouter.getInstance();
instance.populateCommandMap(); //这个方法会去寻找<your project>/lib/ext 下所有的jar
treeLis.setActionHandler(instance);
// NOTUSED: GuiPackage guiPack =
GuiPackage.getInstance(treeLis, treeModel);
MainFrame main = new MainFrame(treeModel, treeLis);
ComponentUtil.centerComponentInWindow(main, 80);
main.setVisible(true);
instance.actionPerformed(new ActionEvent(main, 1, ActionNames.ADD_ALL));
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());
}
} else {
JTree jTree = GuiPackage.getInstance().getMainFrame().getTree();
TreePath path = jTree.getPathForRow(0);
jTree.setSelectionPath(path);
FocusRequester.requestFocus(jTree);
}
}
JMeter 加载插件的机制比较简单,扫描扩展下的的所有实现了 JMeterGUIComponent 和 TestBean 接口的类,然后进行初始化。
ClassFinder.findClassesThatExtend(
JMeterUtils.getSearchPaths(),
new Class[] {JMeterGUIComponent.class, TestBean.class }
在 getSearchPaths() 在这个方法中,它寻找的路径是/lib/ext,所以要确保你开发的插件的 jar 存在与这个路径中。
public static String[] getSearchPaths() {
String p = JMeterUtils.getPropDefault("search_paths", null); // $NON-NLS-1$
String[] result = new String[1];
if (p != null) {
String[] paths = p.split(";"); // $NON-NLS-1$
result = new String[paths.length + 1];
System.arraycopy(paths, 0, result, 1, paths.length);
}
result[0] = getJMeterHome() + "/lib/ext"; // $NON-NLS-1$
return result;
}
jmeter 提供了 example。src/examples,所以在写之前 可以多参考一下
import com.btcc.fix.TestUser;
import net.sourceforge.jdatepicker.JDateComponentFactory;
import net.sourceforge.jdatepicker.JDatePanel;
import net.sourceforge.jdatepicker.impl.UtilDateModel;
import org.apache.jmeter.gui.util.HorizontalPanel;
import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.sampler.FixSmapler;
import org.apache.jmeter.sampler.MessageProvider;
import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import quickfix.btcc.Message;
import javax.swing.;
import java.awt.;
import java.awt.event.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import static javax.swing.BorderFactory.createTitledBorder;
/**
Created by sara on 12/10/2016.
*/
public class FixSmaplerGui extends AbstractSamplerGui {
private static final Logger log = LoggingManager.getLoggerForClass();
// 布局定义
private JTextField requestNameText = null;
private JTextField hostText = null;
private JTextField portText = null;
private JCheckBox sslCheckBox = null;
public FixSmaplerGui(){
super();
init();
}
//用这个方法将 fixSmapler 的数据设置到你的 gui 中
@Override
public void configure(TestElement element) {
super.configure(element);
FixSmapler fixSmapler = (FixSmapler) element;
hostText.setText(fixSmapler.getHost());
portText.setText(fixSmapler.getPort());
sslCheckBox.setSelected(fixSmapler.getSsl());
}
private void init() {
setLayout(new BorderLayout(0, 5));
setBorder(makeBorder());
add(createDataPanel(),BorderLayout.CENTER);
}
// 这个方法是用来创建你自己的元素布局的
private JPanel createDataPanel(){
final JPanel settingPanel = new VerticalPanel(5, 0);
settingPanel.setBorder(makeBorder());
settingPanel.add(makeTitlePanel());
// host
JPanel hostPanel = new HorizontalPanel();
hostPanel.setBorder(createTitledBorder("Host/port"));
JLabel hostLable = new JLabel("Host:");
this.hostText = new JTextField(15);
hostLable.setLabelFor(hostText);
hostPanel.add(hostLable);
hostPanel.add(hostText);
JLabel portLable = new JLabel("Port:");
portText = new JTextField(15);
portLable.setLabelFor(portText);
hostPanel.add(portLable);
hostPanel.add(portText);
JLabel sslLabel = new JLabel("SSL");
sslCheckBox = new JCheckBox();
sslLabel.setLabelFor(sslCheckBox);
hostPanel.add(sslLabel);
hostPanel.add(sslCheckBox);
settingPanel.add(hostPanel);
return settingPanel;
}
// 创建新的 sampler。并且将它传给你创建的 modifyTestElement(TestElement) 方法。
@Override
public TestElement createTestElement() {
TestElement sampler = new FixSmapler();
modifyTestElement(sampler);
return sampler;
}
// 这个方法应该返回代表的 component 的 title/name 的名字。fix_sampler_title 必须被写进 jmeter 的 messages.properties 文件中。
@Override
public String getLabelResource() {
// TODO Auto-generated method stub
return "fix_sampler_title"; // $NON-NLS-1$
}
// 这个方法是用来将数据从你的 gui 传到 TestElement.这个方法和 configure() 方法在逻辑上是相反的
@Override
public void modifyTestElement(TestElement element) {
super.configureTestElement(element);
FixSmapler smapler = (FixSmapler) element;
smapler.setHost(hostText.getText());
smapler.setPort(portText.getText());
smapler.setSsl(sslCheckBox.isSelected());
}
// 这个方法是用来在你创建新的 sampler 时,清除数据的。
@Override
public void clearGui() {
super.clearGui();
hostText.setText("");
portText.setText("");
sslCheckBox.setSelected(false);
}
}
当是在gui上创建一个sampler,其调用的顺序是**clearGui()->createTestElement()->modifyTestElement()->configure()**
2. 在src/components/sampler 下新建Smapler,继承AbstractSampler 类。
```java
import com.btcc.fix.FixClient;
import com.btcc.fix.TestClient;
import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.property.BooleanProperty;
import org.apache.jmeter.testelement.property.IntegerProperty;
import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by sara on 12/10/2016.
*/
public class FixSmapler extends AbstractSampler {
private static final Logger log = LoggingManager.getLoggerForClass();
private static final String HOST = "Fix.host"; //$NON-NLS-1$
private static final String PORT = "Fix.port"; //$NON-NLS-1$
private static final String SSL = "Fix.ssl"; //$NON-NLS-1$
private static TestClient client = null;
private static Message request = null;
private static AtomicInteger classCount = new AtomicInteger(0); // keep track of classes created
public FixSmapler() {
classCount.incrementAndGet();
trace("FixSmapler()");
}
// 这个方法主要是用来执行和收集执行后的result数据的
@Override
public SampleResult sample(Entry entry) {
trace("sample()");
SampleResult res = new SampleResult();
boolean isOK = false;
TestClient c = getClient();
// 设置结果的名称
res.setSampleLabel(getTitle());
// 设置request数据
res.setSamplerData(request.toString());
res.sampleStart();
final CountDownLatch responseLatch = new CountDownLatch(1);
StringBuffer sb = new StringBuffer();
FixClient.Callback callback = new FixClient.Callback() {
@Override
public void onMessage(quickfix.Message message) {
String[] fds = message.toString().split("\\001");
for(String fd:fds){
sb.append(fd).append("\r\n");
}
responseLatch.countDown();
}
};
try{
int count = 0;
while (!c.connect()){
Thread.sleep(1000);
count++;
if(count >=10){
throw new Exception("Fix server can't connect");
}
}
c.send(request,callback);
responseLatch.await();
//设置response数据
res.setResponseMessage(sb.toString());
byte[] bytes = sb.toString().getBytes();
res.setResponseData(bytes);
res.setDataType(SampleResult.TEXT);
res.setResponseCodeOK();
res.setResponseMessage("OK");
isOK = true;
}catch (Exception e){
log.error("send fail: ".concat(e.toString()));
res.setResponseCode("500");// $NON-NLS-1$
res.setResponseData(e.toString());
}finally {
c.removeCallback(callback);
c.disconnect();
}
res.sampleEnd();
res.setSuccessful(isOK);
return res;
}
执行 ant install
安装过后,你直接运行 NewDriver 和 /bin/jmeter 都是可以的。
截图