编写JMeter扩展(1)编写采样器代码

Apache JMeter自带了许多的采样器供我们使用,而且能够满足大部分的测试需求。但是在实际使用过程中,难免需要针对项目自身的特点和需求对Apache JMeter进行扩展。虽然直接继承AbstractJavaSamplerClient即可编写Java采样器,但是其相对应的GUI界面不是很友好,或者我们想编写一个类似HTTP Request那样的sampler,该如何做呢?比如我们需要编写一个TLS的采样器,该采样器允许用户在发送TLS请求的时候制定TLS的版本,以及客户端证书等信息。请参考如下代码及注释:

package kg.apc.jmeter.samplers;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.net.Socket;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.Interruptible;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;

// FIXME: actually keep-alive does not work!
/**
 *
 * @author undera
 */
public class TLSRawSampler extends AbstractSampler implements Serializable, Cloneable, Interruptible{
    private static final Logger log = LoggingManager.getLoggerForClass();
    
    //following static final String are property keys in JMeter
    private static final String HOST_NAME = "TLS_hostName";
    private static final String PORT = "TLS_port";
    private static final String TLS_VERSON = "TLS_tlsversion";
    private static final String CIPHER_LIST = "TLS_cipherlist";
    private static final String DATA = "TLS_data";
    private static final String CLIENT_CERT = "TLS_client_cert";
    private static final String CLIENT_CERT_PASSWORD = "TLS_client_cert_password";
 
    public TLSRawSampler() {
    }
    
    /**
     * Process sample here
     */
    @Override
    public SampleResult sample(Entry entry) {
       SampleResult sr = new SampleResult();
       sr.sampleStart();
       sr.setSuccessful(true);
       sr.setSampleLabel(getName());
       sr.setResponseCode("200");
       
       //do the sample here
       try{
    	   Socket socket = getTLSSocket();
    	   socket.getOutputStream().write(getData().getBytes());
    	   StringBuilder headerSB = new StringBuilder();
    	   StringBuilder contentSB = new StringBuilder();
    	   BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    	   String line = null;
    	   boolean header = true;
    	   while((line = reader.readLine()) != null){
    		   if(line.length() == 0){
    			   header = false;
    			   continue;
    		   }
    		   if(header){
	    		   headerSB.append(line);
	    		   headerSB.append("\n");
    		   }
    		   else{
    			   contentSB.append(line);
    			   contentSB.append("\n");
    		   }
    	   }
    	   sr.setResponseHeaders(headerSB.toString());
    	   sr.setResponseData(contentSB.toString(), "");
    	   socket.close();
       }catch(Exception e){
    	   sr.setSuccessful(false);
    	   sr.setResponseCode("500");
    	   sr.setResponseMessage(e.getMessage());
       }
       
       sr.sampleEnd();
       return sr;
    }

	@Override
	public boolean interrupt() {
		// TODO Auto-generated method stub
		return false;
	}

	//following get and set methods are used for get and set properties in JMeter
    
    public String getHostName(){
    	return getPropertyAsString(TLSRawSampler.HOST_NAME);
    }
    
    public void setHostName(String hostName){
    	setProperty(TLSRawSampler.HOST_NAME, hostName);
    }
    
    public String getPort(){
    	return getPropertyAsString(TLSRawSampler.PORT);
    }
    
    public void setPort(String port){
    	setProperty(TLSRawSampler.PORT, port);
    }
    
    public String getTLSVersion(){
    	return getPropertyAsString(TLSRawSampler.TLS_VERSON);
    }
    
    public void setTLSVersion(String version){
    	setProperty(TLSRawSampler.TLS_VERSON, version);
    }
    
    public String getClientCert(){
    	return getPropertyAsString(TLSRawSampler.CLIENT_CERT);
    }
    
    public void setClientCert(String clientCert){
    	setProperty(TLSRawSampler.CLIENT_CERT, clientCert);
    }
    
    public String getCipherList(){
    	return getPropertyAsString(TLSRawSampler.CIPHER_LIST);
    }
    
    public void setCipherList(String list){
    	setProperty(TLSRawSampler.CIPHER_LIST, list);
    }
    
    public String getData(){
    	return getPropertyAsString(TLSRawSampler.DATA);
    }
    
    public void setData(String data){
    	setProperty(TLSRawSampler.DATA, data);
    }
    
    public String getClientCertPassword(){
    	return getPropertyAsString(TLSRawSampler.CLIENT_CERT_PASSWORD);
    }
    
    public void setClientCertPassword(String password){
    	setProperty(TLSRawSampler.CLIENT_CERT_PASSWORD, password);
    }
    
    private Socket getTLSSocket() throws Exception{
		TrustManager[] allTrusted = {new X509TrustManager(){

			@Override
			public void checkClientTrusted(X509Certificate[] chain,
					String authType) throws CertificateException {
				// TODO Auto-generated method stub

			}

			@Override
			public void checkServerTrusted(X509Certificate[] chain,
					String authType) throws CertificateException {
				// TODO Auto-generated method stub

			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				// TODO Auto-generated method stub
				return null;
			}

		}};

		SSLContext ctx = SSLContext.getInstance(getTLSVersion(), "SunJSSE");//use 1.2

		//get client cert
		String clientCert = getClientCert();
		if(clientCert != null && clientCert.length() > 0){
			String clientCertPassword = getClientCertPassword();
			KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
			KeyStore keyStore = KeyStore.getInstance("PKCS12");

			InputStream keyInput = new FileInputStream(clientCert);
			keyStore.load(keyInput, clientCertPassword.toCharArray());
			keyInput.close();

			keyManagerFactory.init(keyStore, clientCertPassword.toCharArray());

			ctx.init(keyManagerFactory.getKeyManagers(), allTrusted, null);
		}
		else{
			ctx.init(null, allTrusted, null);
		}
		SSLParameters parameters = ctx.getDefaultSSLParameters();
		String cipherList = getCipherList();
		if(cipherList != null && cipherList.length() > 0){
			parameters.setCipherSuites(cipherList.trim().split(","));
		}
		for(String cipher : parameters.getCipherSuites()){
			log.info(cipher);
		}

		SSLSocket socket = (SSLSocket)ctx.getSocketFactory().createSocket(getHostName(), Integer.valueOf(getPort()));
		socket.setTcpNoDelay(true);
		socket.setSSLParameters(parameters);

		return socket;
	}
}
时间: 2024-10-20 11:28:24

编写JMeter扩展(1)编写采样器代码的相关文章

编写JMeter扩展(2)编写采样器代码对应的GUI

请参考如下的代码及注释: package kg.apc.jmeter.samplers; import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.

手动使用C/C++编写Lua扩展插件

最近在研究如何在Windows 下嵌入Lua来完成业务模块编写的时候 发现Lua的一些问题,首先Lua作为一门脚本语言,其灵活性和可扩展性是很高的,要不然Cocos2d-x中也不会嵌入他来编写业务逻辑,但是由于国内资料相当的少,很少有人去正八经研究完了之后 写一篇文章 来分享自己的成果,想要去深入理解应用一些东西得时候,显得很无力,很多Lua扩展都是直接写扩展库来完成,如果不理解原理甚至你都不会灵活运用,这就是本文写作的目的. 第一 我需要Lua嵌入我的应用程序,这一点很容易的做到. 第二 我需

怎样编写scrapy扩展

原创文章,链接:http://blog.csdn.net/u012150179/article/details/38226477 在scrapy使用过程中,很多情况下需要根据实际需求定制自己的扩展,小到实现自己的pipelines,大到用新的scheduler替换默认的scheduler. 扩展可以按照是否需要读取crawler大致分为两种,对于不需要读取的,比如pipelines的编写,只需要实现默认的方法porcess_item.需要读取的,如scheduler的编写又存在另外的方式. 1.

用Java为Hyperledger Fabric(超级账本)编写区块链智能合约链代码

编写第一个 Java 链代码程序 在上一节中,您已经熟悉了如何构建.运行.部署和调用链代码,但尚未编写任何 Java 代码. 在本节中,将会使用 Eclipse IDE.一个用于 Eclipse 的 Gradle 插件,以及一个名为 ChaincodeTutorial 的 Java 链代码框架项目,编写第一个 Java 链代码程序.您将从我为此教程创建的 GitHub 存储库中获取框架代码,将该代码导入 Eclipse 中,添加代码来让链代码智慧合同按要求生效,然后在 Eclipse IDE 内

一步步入门编写PHP扩展

1.写在最前 随着互联网飞速发展,lamp架构的流行,php支持的扩展也越来越多,这样直接促进了php的发展. 但是php也有脚本语言不可避免的问题,性能比例如C等编译型语言相差甚多,所以在考虑性能问题的时候最好还是通过php扩展来解决. 那么,怎么去做一个php扩展呢.下面从一个例子开始(本文章需要C基础). 2.解决一个问题 在一个系统中,如果经常要求一个数组的平方和,我们可以这么写. <?php function array_square_sum($data){ $sum = 0; for

编程精粹--编写高质量的C语言代码(2):自己设计并使用断言(一)

上一篇文章<<编程精粹--编写高质量C语言代码(1):假想编译程序>>中讲述了如何利用编译程序的所有警告设施以及lint程序等来更加容易地自动发现程序中的错误.但是即使使用编译程序提供的所有警告设施,编译程序所发现的错误,也只是程序错误中的一小部分.例如以下一行代码: strCopy=memecpy(malloc(length),str,length)); 当malloc 调用失败时,返回一个空指针,而memcpy如果没有处理空指针,程序就会出现错误.编译程序是无法查出这种或其他类

如何编写可维护的面向对象JavaScript代码

能够写出可维护的面向对象JavaScript代 码不仅可以节约金钱,还能让你很受欢迎.不信?有可能你自己或者其他什么人有一天会回来重用你的代码.如果能尽量让这个经历不那么痛苦,就可以节省不少时 间.地球人都知道,时间就是金钱.同样的,你也会因为帮某人省去了头疼的过程而获得他的偏爱.但是,在开始探索如何编写可维护的面向对象JavaScript代码之前,我们先来快速看看什么是面向对象.如果已经了解面向对象的概念了,就可以直接跳过下一节. 什么是面向对象?  面向对象编程主要通过代码代表现实世界中的实

js学习笔记-编写高效、规范的js代码-Tom

编写高效.规范的js代码: 1.变量命名空间问题,尽量使用局部变量,防止命名冲突(污染作用域中的全局变量):全局空间命名的变量可以在对应的文档域任意位置中使用window调用. 2.尽量使用单var定义变量(作用域开始先申明并赋值变量,便于后边使用),使用var定义的变量只作用于对应的作用域中,如定义的全局变量作用于全局作用域,函数中定义的变量作用于该局部作用域中.未用var定义的变量相当于一个全局变量,在函数中出现的该类变量作用域全局域.(但是var定义的全局变量不能用delete删除,而未定

使用OpenCV编写的LDA程序----C++ LDA代码

改写自OpenCV中的lda.cpp程序,通过改写的程序可以返回自己所需的信息(LDA算法过程中产生的我们感兴趣的中间值),实现算法的独立编译,也可以通过阅读程序,加深对LDA算法的理解. // main.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <cxcore.hpp> #include <vector> #include <iostream> #include "lda.h