在编写任何JMeter组件时,必须注意某些特定的约定——如果JMeter环境中正确地运行JMeter组件,那么它将会运行。本部分描述了组件的GUI部分必须满足的约定。

JMeter中的GUI代码严格地与测试元件代码(这里指逻辑控制代码,下同)分离。因此,当编写一个组件时,将会有一个用于测试元件的类,另一个用于GUI表示。GUI类是无状态的,因此它不应该挂在对测试元件的引用上(尽管有例外)。

GUI元素应该继承适当的抽象类:

  • AbstractSamplerGui
  • AbstractAssertionGui
  • AbstractConfigGui
  • AbstractControllerGui
  • AbstractPostProcessorGui
  • AbstractPreProcessorGui
  • AbstractVisualizer
  • AbstractTimerGui
  • ……

这些抽象类提供了大量的管道工作,不用扩展,用来代替直接实现接口。

已经继承了适当的GUI类,剩下要遵循以下步骤:

1、实现getResourceLabel() 
该方法返回资源的标题/名称。 
2、创建GUI。无论使用什么样式,都要布局GUI。类最终要继承JPanel,因此布局必须在的类自己的ContentPane中。不要通过动作和事件将·GUI元素连接到测试元件类。让swing的内部模型尽可能多地挂在所有数据上。 
(1)一些标准的GUI内容应该添加到所有JMeter GUI组件中: 
a、调用setBorder(makeBorder())。这将给它提供标准的JMeter边框。 
b、通过makeTitlePanel()添加标题窗格。通常这是添加到GUI中的第一件事,应该在一个垂直布局方案中完成,或者使用JMeter的VerticalLayout类。下面是一个示例init()方法:

private void init() {
setLayout(new BorderLayout());
setBorder(makeBorder());
Box box = Box.createVerticalBox();
box.add(makeTitlePanel());
box.add(makeSourcePanel());
add(box,BorderLayout.NORTH);
add(makeParameterPanel(),BorderLayout.CENTER);
}

3、实现public void configure(TestElement el) 
(1)一定调用super.configure(e),这将填充一些数据,比如元素的名称 
(2)使用此方法将数据设置为GUI元素。例子

public void configure(TestElement el) {
super.configure(el);
useHeaders.setSelected(el.getPropertyAsBoolean(RegexExtractor.USEHEADERS));
useBody.setSelected(!el.getPropertyAsBoolean(RegexExtractor.USEHEADERS));
regexField.setText(el.getPropertyAsString(RegexExtractor.REGEX));
templateField.setText(el.getPropertyAsString(RegexExtractor.TEMPLATE));
defaultField.setText(el.getPropertyAsString(RegexExtractor.DEFAULT));
matchNumberField.setText(el.getPropertyAsString(RegexExtractor.MATCH_NUM));
refNameField.setText(el.getPropertyAsString(RegexExtractor.REFNAME));
}

(3)实现public void modifyTestElement(TestElement e),这是将数据从GUI元素移动到TestElement的地方。这是前一种方法的逻辑逆操作 
a、调用super.configureTestElement(e),处理一些默认数据 
b、例子

public void modifyTestElement(TestElement e) {
super.configureTestElement(e);
e.setProperty(new BooleanProperty(
RegexExtractor.USEHEADERS,
useHeaders.isSelected()));
e.setProperty(RegexExtractor.MATCH_NUMBER,
matchNumberField.getText());
if (e instanceof RegexExtractor) {
RegexExtractor regex = (RegexExtractor)e;
regex.setRefName(refNameField.getText());
regex.setRegex(regexField.getText());
regex.setTemplate(templateField.getText());
regex.setDefaultValue(defaultField.getText());
}
}

(4)实现public TestElement createTestElement(),该方法应该创建TestElement类的一个新实例,然后将其传递modifyTestElement(TestElement)方法

public TestElement createTestElement() {
RegexExtractor extractor = new RegexExtractor();
modifyTestElement(extractor);
return extractor;
}

不能保留对测试元件的引用的原因是因为JMeter的测试元件重用了多个GUI类对象的实例。这样可以节省很多内存。它还使得编写新组件的GUI部分变得非常容易。您仍然需要与Swing中的布局进行斗争,但是不必担心如何创建正确的事件和从GUI元素中获取数据放入测试元件中。JMeter知道什么时候调用自定义配置,以及可以用一种非常简单的方式来完成它的修改。

总结:

GUI与测试元件分离:GUI部分通过继承各种组件GUI抽象类,测试元件部分通过继承组件抽象类和实现各种接口方式从而实现不同组件的内部逻辑控制;
GUI与测试元件不分离:与分离方法的区别在于不单独实现GUI部分,在测试元件部分通过实现TestBean接口方法从而实现对GUI界面的配置。(TestBean是一个空接口:Marker interface to tell JMeter to make a Test Bean Gui for the class)

jmeter插件分类

GUI的组件主要包括10大组件

  • ThreadGroup(线程组)
  • Test Fragment(测试片段)
  • logic Controller(逻辑控制器)
  • Config element(配置元件)
  • Timer(定时器)
  • pre processor(前置处理器)
  • post processor(后置处理器)
  • Sampler(测试抽样器)
  • Assertion(断言)
  • Listener(监听器);

非GUI组件

  • Function(函数)

JMeter插件式组件实现

TestElement是所有组件的最基本单元,组件类都是TestElement类的子类 
依据上面介绍,组件的实现分两部分:GUI和TestElement

GUI部分的实现

继承实现对应的抽象类

抽象类 继承的类 对应组件备注
AbstractAssertionGui AbstractScopedJMeterGuiComponent 断言
AbstractConfigGui AbstractJMeterGuiComponent 配置
AbstractControllerGui AbstractJMeterGuiComponent 控制
AbstractPostProcessorGui AbstractScopedJMeterGuiComponent 后置处理器
AbstractPreProcessorGui AbstractJMeterGuiComponent 前置处理器
AbstractSamplerGui AbstractJMeterGuiComponent 取样器
AbstractThreadGroupGui AbstractJMeterGuiComponent 线程组
AbstractTimerGui AbstractJMeterGuiComponent 定时器
AbstractListenerGui AbstractJMeterGuiComponent 监听器
AbstractVisualizer AbstractListenerGui 组件依赖
AbstractScopedJMeterGuiComponent AbstractJMeterGuiComponent 组件依赖
AbstractJMeterGuiComponent JPanel 组件依赖
AbstractFunction Function 组件依赖
AbstractJMeterGuiComponent JPanel 组件依赖

逻辑控制实现

Assertion(断言)组件

Assertion(断言)组件通过继承AbstractTestElement抽象类(或者AbstractTestElement子类),实现Assertion接口的getResult(SampleResult result)方法对结果内容进行判断,从而实现断言方法,用于对Sampler组件所产生的抽样采集结果内容进行断言。

比如:

public class XMLSchemaAssertion extends AbstractTestElement implements Serializable, Assertion {
……
@Override
public AssertionResult getResult(SampleResult response) {
AssertionResult result = new AssertionResult(getName());
……
return result;
}
……
}

再比如:

public abstract class AbstractScopedTestElement extends AbstractTestElement {...}
public abstract class AbstractScopedAssertion extends AbstractScopedTestElement{...} public class DurationAssertion extends AbstractScopedAssertion implements Serializable, Assertion {
public static final String DURATION_KEY = "DurationAssertion.duration";
@Override
public AssertionResult getResult(SampleResult response) {
……
return result;
}
private long getAllowedDuration() {
return getPropertyAsLong(DURATION_KEY);
}
public void setAllowedDuration(long duration) {
setProperty(DURATION_KEY, duration);
}
}

Config(配置元件)组件

Config(配置元件)组件相对其他组件比较特殊,通过继承ConfigTestElement类或只需要GUI部分的实现即可完成本体任务

public class CSVDataSet extends ConfigTestElement
implements TestBean, LoopIterationListener, NoConfigMerge {
private static final Logger log = LoggerFactory.getLogger(CSVDataSet.class);
……
}

ThreadGroup(线程组)组件

ThreadGroup(线程组)组件继承AbstractThreadGroup抽象类,通过重写各类控制方法来达到控制和协调各线程(虚拟用户)的行为,线程组是构建一个性能测试模型的最基本组件。

public class ThreadGroupTest extends AbstractThreadGroup {
private static final long serialVersionUID = 1L;
@Override
public void threadFinished(JMeterThread arg0) {}
@Override
public int numberOfActiveThreads() {return 0;}
@Override
public void start(int arg0, ListenerNotifier arg1, ListedHashTree arg2, StandardJMeterEngine arg3) {}
@Override
public void stop() {}
@Override
public boolean stopThread(String arg0, boolean arg1) {return false;}
@Override
public void tellThreadsToStop() {}
@Override
public boolean verifyThreadsStopped() {return false;}
@Override
public void waitThreadsStopped() {}
}

Timer(定时器)组件

Timer(定时器)组件通过继承AbstractTestElement抽象类,实现Timer接口的delay()方法来实现对时间的控制

public class TimerTest extends AbstractTestElement implements Timer{
private static final long serialVersionUID = 1L;
@Override
public long delay() {
return 0;
}
}

控制线程延时,即用来模仿思考时间(ThinkTime)或键盘时间(KeyTime);

控制线程行为,如SyncTimer(同步计时器),就是内部利用CyclicBarrier来控制阻塞和释放全部运行线程的逻辑行为,从而达到“集合点”的目的。

public class SyncTimer extends AbstractTestElement implements Timer, Serializable, TestBean, TestStateListener, ThreadListener {
private static final Logger log = LoggerFactory.getLogger(SyncTimer.class);
private static class BarrierWrapper implements Cloneable {
private CyclicBarrier barrier;
public BarrierWrapper() {
this.barrier = null;
}
public BarrierWrapper(int parties) {
this.barrier = new CyclicBarrier(parties);
}
public synchronized void setup(int parties) {
if(this.barrier== null) {
this.barrier = new CyclicBarrier(parties);
}
}
public int await() throws InterruptedException, BrokenBarrierException{
return barrier.await();
}
public int await(long timeout, TimeUnit timeUnit) throws InterruptedException, BrokenBarrierException, TimeoutException {
return barrier.await(timeout, timeUnit);
}
public void reset() {
barrier.reset();
}
@Override
protected Object clone() {
BarrierWrapper barrierWrapper= null;
try {
barrierWrapper = (BarrierWrapper) super.clone();
barrierWrapper.barrier = this.barrier;
} catch (CloneNotSupportedException e) {
}
return barrierWrapper;
}
}
……
public void threadStarted() {
if(getGroupSize() == 0) {
int numThreadsInGroup = JMeterContextService.getContext().getThreadGroup().getNumThreads();
// Unique Barrier creation ensured by synchronized setup
this.barrier.setup(numThreadsInGroup);
}
}
……
}

pre processor(前置处理器)组件

pre processor(前置处理器)组件通过继承AbstractTestElement抽象类,实现PreProcessor接口的process ()方法控制逻辑

比如:BeanShellPreProcessor

public class BeanShellPreProcessor extends BeanShellTestElement
implements Cloneable, PreProcessor, TestBean
{
private static final Logger log = LoggerFactory.getLogger(BeanShellPreProcessor.class); private static final long serialVersionUID = 5; // can be specified in jmeter.properties
private static final String INIT_FILE = "beanshell.preprocessor.init"; //$NON-NLS-1$ @Override
protected String getInitFileProperty() {
return INIT_FILE;
}
@Override
public void process(){
final BeanShellInterpreter bshInterpreter = getBeanShellInterpreter();
if (bshInterpreter == null) {
log.error("BeanShell not found");
return;
}
JMeterContext jmctx = JMeterContextService.getContext();
Sampler sam = jmctx.getCurrentSampler();
try {
// Add variables for access to context and variables
bshInterpreter.set("sampler", sam);//$NON-NLS-1$
processFileOrScript(bshInterpreter);
} catch (JMeterException e) {
if (log.isWarnEnabled()) {
log.warn("Problem in BeanShell script. {}", e.toString());
}
}
}
@Override
public Object clone() {
return super.clone();
}
}

作用:对线程上下文中的当前Sampler和前一个SampleResult进行识别和判断。

post processor(后置处理器)组件

post processor(后置处理器)组件通过继承AbstractTestElement抽象类,实现PostProcessor接口的process ()方法控制逻辑

public abstract class AbstractScopedTestElement extends AbstractTestElement {……}

public class RegexExtractor extends AbstractScopedTestElement implements PostProcessor, Serializable {
……
@Override
public void process() {}
……
}

作用:对线程上下文中的前一个SampleResult进行识别和判断。

Controller(控制器)组件

Controller(控制器)组件通过继承GenericController类 
比如foreach,重写isDone、next、nextIsNull、getIterCount、reInitialize、initialize、triggerEndOfLoop

public class ForeachController extends GenericController implements Serializable {
public ForeachController() {}
……
@Override
public boolean isDone() {}
@Override
public Sampler next() {}
@Override
protected Sampler nextIsNull() throws NextIsNullException {}
@Override
protected int getIterCount() {return loopCount+1;}
@Override
protected void reInitialize() {}
@Override
public void triggerEndOfLoop() {}
@Override
public void initialize() {}
}

Sampler(测试抽样器)组件

Sampler(测试抽样器)组件继承AbstractSampler抽象类,通过重写SampleResult sample(Entry e)方法,实现测试过程以及测试结果的采集功能。

public class DebugSampler extends AbstractSampler implements TestBean {
……
@Override
public SampleResult sample(Entry e) {}
……
}

Listener(监听器)

直接继承AbstractTestElement,实现sampleListener或Visualizer等接口方法

public class Summariser extends AbstractTestElement
implements Serializable, SampleListener, TestStateListener, NoThreadClone, Remoteable {
……
@Override
@SuppressWarnings("SynchronizeOnNonFinalField")
public void sampleOccurred(SampleEvent e) {
SampleResult s = e.getResult();
if(IGNORE_TC_GENERATED_SAMPLERESULT && TransactionController.isFromTransactionController(s)) {
return;
}
long now = System.currentTimeMillis() / 1000;// in seconds
SummariserRunningSample myDelta = null;
SummariserRunningSample myTotal = null;
boolean reportNow = false;
synchronized (myTotals) {
if (s != null) {
myTotals.delta.addSample(s);
}
if ((now > myTotals.last + INTERVAL_WINDOW) && (now % INTERVAL <= INTERVAL_WINDOW)) {
reportNow = true;
// copy the data to minimise the synch time
myDelta = new SummariserRunningSample(myTotals.delta);
myTotals.moveDelta();
myTotal = new SummariserRunningSample(myTotals.total);
myTotals.last = now; // stop double-reporting
}
}
if (reportNow) {
formatAndWriteToLog(myName, myDelta, "+");
// Only if we have updated them
if (myTotal != null && myDelta != null &&myTotal.getNumSamples() != myDelta.getNumSamples()) { // NOSONAR
formatAndWriteToLog(myName, myTotal, "=");
}
}
}
……
}

可以从实际用途上将其分为两大类Report (报告)和Visualizers(监视器)。 
Report (报告)继承AbstractListenerElement抽象类,通过实现sampleOccurred(SampleEvent e)方法,对所有采集事件中所产生的SampleResult进行处理,从而生成报告;

public class ResultCollector extends AbstractListenerElement implements SampleListener, Clearable, Serializable,
TestStateListener, Remoteable, NoThreadClone {
……
@Override
public void sampleOccurred(SampleEvent event) {
SampleResult result = event.getResult(); if (isSampleWanted(result.isSuccessful())) {
sendToVisualizer(result);
if (out != null && !isResultMarked(result) && !this.isStats) {
SampleSaveConfiguration config = getSaveConfig();
result.setSaveConfig(config);
try {
if (config.saveAsXml()) {
SaveService.saveSampleResult(event, out);
} else { // !saveAsXml
String savee = CSVSaveService.resultToDelimitedString(event);
out.println(savee);
}
} catch (Exception err) {
log.error("Error trying to record a sample", err); // should throw exception back to caller
}
}
}
if(summariser != null) {
summariser.sampleOccurred(event);
}
}
……
}

Visualizers(监视器)主要用于特定的监控任务,比如监控系统资源利用率的组件,与Report的区别在于Visualizers必须继承一个 ResultCollector类,并在收集器中通过开启额外线程方式完成自定义的数据采集。

public class ResultCollector extends AbstractListenerElement implements SampleListener, Clearable, Serializable, TestStateListener, Remoteable, NoThreadClone {……}

比如标准插件中自定义一个JMXMonCollector

public class CorrectedResultCollector extends ResultCollector {}

public class JMXMonCollector extends CorrectedResultCollector implements Runnable, JMXMonSampleGenerator {……}
注意:对于一个需要配置的组件类则需要实现ConfigMergabilityIndicator接口的public boolean applies(ConfigTestElement configElement)方法,用来指明哪些Config组件可以用来对其进行配置

这里参考DebugSampler的源代码如下:

public class DebugSampler extends AbstractSampler implements TestBean {
……
private static final Set<String> APPLIABLE_CONFIG_CLASSES = new HashSet<>(
Arrays.asList("org.apache.jmeter.config.gui.SimpleConfigGui"));
@Override
public boolean applies(ConfigTestElement configElement) {
String guiClass = configElement.getProperty(TestElement.GUI_CLASS).getStringValue();
return APPLIABLE_CONFIG_CLASSES.contains(guiClass);
}
……
}

以上代码指明SimpleConfigGui配置元件可以对DebugSampler组件进行配置。

函数

Function(函数)是非GUI组件,这类组件的实现比较简单,而且功能比较单一,只需要继承相应的抽象类即可~

写一个求字符长度的函数:StrLen

public class StrLen extends AbstractFunction {
private static final List<String> desc = new LinkedList<String>();
private static final String KEY = "__strLen";
static {
desc.add("String to measure length");
desc.add("Name of variable in which to store the result (optional)");
}
private Object[] values;
public StrLen() {
}
@Override
public synchronized String execute(SampleResult previousResult, Sampler currentSampler)
throws InvalidVariableException {
JMeterVariables vars = getVariables();
Integer len = ((CompoundVariable) values[0]).execute().length();
if (vars != null && values.length > 1) {
String varName = ((CompoundVariable) values[1]).execute().trim();
vars.put(varName, len.toString());
}
return len.toString();
}
@Override
public synchronized void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException {
checkMinParameterCount(parameters, 1);
values = parameters.toArray();
}
@Override
public String getReferenceKey() {
return KEY;
}
public List<String> getArgumentDesc() {
return desc;
}
}

附录

jmeter一些GUI类继承关系

GUI类 继承的类
ResultActionGui AbstractPostProcessorGui
ResultSaverGui AbstractListenerGui
SummariserGui AbstractListenerGui
TestBeanGUI AbstractJMeterGuiComponent
ThreadGroupGui AbstractThreadGroupGui
SetupThreadGroupGui ThreadGroupGui
PostThreadGroupGui ThreadGroupGui
WorkBenchGui AbstractJMeterGuiComponent
AssertionGui AbstractAssertionGui
BeanShellAssertionGui AbstractAssertionGui
urationAssertionGui AbstractAssertionGui
HTMLAssertionGui AbstractAssertionGui
MD5HexAssertionGUI AbstractAssertionGui
SizeAssertionGui AbstractAssertionGui
SMIMEAssertionGui AbstractAssertionGui
XMLAssertionGui AbstractAssertionGui
XMLSchemaAssertionGUI AbstractAssertionGui
XPathAssertionGui AbstractAssertionGui
CriticalSectionControllerGui AbstractControllerGui
IncludeControllerGui AbstractControllerGui
InterleaveControlGui AbstractControllerGui
ModuleControllerGui AbstractControllerGui
OnceOnlyControllerGui AbstractControllerGui
RandomControlGui AbstractControllerGui
RandomOrderControllerGui LogicControllerGui
SwitchControllerGui AbstractControllerGui
ThroughputControllerGui AbstractControllerGui
HtmlExtractorGui AbstractPostProcessorGui
RegexExtractorGui AbstractPostProcessorGui
XPathExtractorGui AbstractPostProcessorGui
JSONPostProcessorGui AbstractPostProcessorGui
CounterConfigGui AbstractConfigGui
SampleTimeoutGui AbstractPreProcessorGui
UserParametersGui AbstractPreProcessorGui
TestActionGui AbstractSamplerGui
AbstractRandomTimerGui AbstractTimerGui
ConstantTimerGui AbstractTimerGui
GaussianRandomTimerGui AbstractRandomTimerGui
PoissonRandomTimerGui AbstractRandomTimerGui
UniformRandomTimerGui AbstractRandomTimerGui
AbstractAssertionGui AbstractScopedJMeterGuiComponent
AbstractConfigGui AbstractJMeterGuiComponent
LoginConfigGui AbstractConfigGui
ObsoleteGui AbstractJMeterGuiComponent
SimpleConfigGui AbstractConfigGui
AbstractControllerGui AbstractJMeterGuiComponent
LogicControllerGui AbstractControllerGui
RunTimeGui AbstractControllerGui
TestFragmentControllerGui AbstractControllerGui
TestPlanGui AbstractJMeterGuiComponent
TransactionControllerGui AbstractControllerGui
WhileControllerGui AbstractControllerGui
WorkBenchGui AbstractJMeterGuiComponent
FunctionHelper JDialog
AbstractJMeterGuiComponent JPanel
AbstractScopedJMeterGuiComponent AbstractJMeterGuiComponent
AbstractPostProcessorGui AbstractScopedJMeterGuiComponent
AbstractPreProcessorGui AbstractJMeterGuiComponent
ResultActionGui AbstractPostProcessorGui
ResultSaverGui AbstractListenerGui
SummariserGui AbstractListenerGui
AbstractSamplerGui AbstractJMeterGuiComponent
TestBeanGUI AbstractJMeterGuiComponent
AbstractThreadGroupGui AbstractJMeterGuiComponent
PostThreadGroupGui ThreadGroupGui
SetupThreadGroupGui ThreadGroupGui
ThreadGroupGui AbstractThreadGroupGui
AbstractTimerGui AbstractJMeterGuiComponent
AbstractListenerGui AbstractJMeterGuiComponent
AbstractVisualizer AbstractListenerGui

JMeter Gui – TestElement约定(转自约会言行的博客,链接:http://blog.csdn.net/yue530tomtom/article/details/77649872?locationNum=4&fps=1)的更多相关文章

  1. JMeter Gui – TestElement约定[转]

    转自https://www.cnblogs.com/yigui/p/7615635.html 在编写任何JMeter组件时,必须注意某些特定的约定--如果JMeter环境中正确地运行JMeter组件, ...

  2. 笔记1:jmeter性能测试使用示例(原文:http://blog.csdn.net/zhongweijian/article/details/7619319)

    jmeter是一个简单开源的纯java的性能测试工具.今天学习了jmeter使用了下jmeter,使用起来非常简单. 如果我们要对163的首页性能进行简单测试,我们可以按照以下步骤进行. 1.在测试计 ...

  3. 24. Jmeter GUI 及NON GUI实现分布式

    什么是分布式: Jmeter的集群模式可以让我们将多台机器联合起来一起产生负载,从而弥补单台机器负载生成能力不足的问题. 假设我们的测试计划会产生100个threads,我们使用6台机器进行分布式测试 ...

  4. Jmeter报错之jmeter.gui.action.ActionRouter: Error processing gui.action.Start@1b7c473a java.lang.ArrayIndexOutOfBoundsException

    一个使用了很久的Jmeter脚本,运行时Jmeter的UI界面上点击绿色按钮后,完全无反应,只有log报错,如下: 2017/06/28 14:29:23 ERROR - jmeter.gui.act ...

  5. JMeter博客系列:JMeter BeanShell示例

    1.简介 Apache JMeter是一个基于Java的开源工具,使您可以在应用程序上执行功能,负载,性能和回归测试.应用程序可以在Web服务器上运行,也可以是独立的.它支持在包含静态和动态资源的客户 ...

  6. 一、Jmeter启动报错:Could not initialize class org.apache.jmeter.gui.util.MenuFactory

    1.下载: plugins-manager.jar 包 2.地址:https://jmeter-plugins.org/install/Install/ 3.将jar包放到lib/ext 4.重启jm ...

  7. 【JMeter_03】JMeter GUI操作界面介绍

    JMeter主界面主要分为 标题栏.菜单栏.工具栏.测试计划树形目录.内容展示区 标题栏:主要展示JMeter的程序版本.当前脚本的名称.脚本的储存路径 菜单栏:程序基本上所有功能的所属分类目录,基本 ...

  8. JMeter中各种请求格式--aduocd的博客

    背景:1.在JMeter的HTTP请求的测试中,经常会使用到不同的请求格式.常用的格式如,json,form-data,x-www-form-urlencoded,multipart/form-dat ...

  9. 【技术博客】 利用Postman和Jmeter进行接口性能测试

    利用Postman和Jmeter进行接口性能测试 作者:ZBW 版本:v1.1 在Phylab的开发过程中,对于生成报告接口的性能考量十分重要.原有的Latex接口虽然生成的报告美观,但编译Latex ...

随机推荐

  1. PHP支付宝手机网站支付功能

    1.开通支付宝商家中心里面的手机网站支付 2.再去开放平台-开发者中心-创建移动支付的应用-获取到APPID 3.接着去文档中心下载DEMO 其实demo很简单.如果第一次看的话会存在看不懂的状态. ...

  2. spring.jar是包含有完整发布的单个jar 包,spring.jar中包含除了spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环境下才会用到 spring-mock.jar来进行辅助测试,正式应用系统中是用不得这些类的。

    Spring jar包的描述:针对3.2.2以上版本 org.springframework spring-aop ——Spring的面向切面编程,提供AOP(面向切面编程)实现 org.spring ...

  3. ffmpeg 常用命令汇总

    最近工作常用到ffmpeg 做一些视频数据的处理转换等,用来做测试,今天总结了一下,并参考了网上一些部分朋友的经验,一起在这里汇总了一下,有需要的朋友可以收藏测试一下,有问题可以回帖交流. 1.ffm ...

  4. 034-openstack中虚拟机启动后主机名设置问题

    openstack中虚拟机启动后主机名设置问题,在centos7中设置hostname后怎么都是原来的hostname,根本无效. 方法一: 在centos7中除了修改hosts文件和network文 ...

  5. DevOps书单:调研了101名专家,推荐这39本必读书籍

    任何一个领域都遵循从新人到熟手,从熟手到专家的路径.在成长过程中,DevOps人经常会陷入没人带,没人管,找不到职业方向的迷茫. DevOps是在商业演进与企业协作的进化过程中诞生的一个全新职业,被很 ...

  6. Windows Server2008R2蓝屏,分析dmp文件

    使用Windbp PreView打开dmp文件后,在命令栏输入如下命令: !analyze -v 解析结果中蓝色字体为错误原因分析

  7. SQL插入字段

    //SQL插入字段 String dropTable="drop table if exists test;"; String columnGid ="alter tab ...

  8. C++STL手写版

    手写STL,卡常专用. node为变量类型,可以自由定义,以下不再赘述. 1.stack(栈) 开一个数组,和一个top指针,压栈时++,弹栈时--即可. struct stack{ int tp;n ...

  9. Leetcode 11. Container With Most Water(逼近法)

    11. Container With Most Water Medium Given n non-negative integers a1, a2, ..., an , where each repr ...

  10. apache Internal Server Error 解决方法

    https://blog.csdn.net/qq_33684377/article/details/78536548 https://blog.csdn.net/LJFPHP/article/deta ...