我们发送http请求或是其它请求,就是在执行一段代码,只不过,执行的代码,布署在服务器上。而java请求,也是在执行一段代码,只不过代码布署在本地,需要我们自己实现代码的逻辑。利用java请求,可以很方便地实现你想要的需求,当然,前提是你要会java。先看看java请求的具体实现吧,打开eclipse,新建一个java Project
这里,我项目名就叫Test了,然后在项目名上右击,选最下面的properties
Java Build Path——Libraries——Add External JARS...
找到jmeter安装目录下lib/ext目录下的ApacheJMeter_core.jar和ApacheJMeter_java.jar两个jar文件,按住Ctrl可以多选,然后点 打开
然后点 OK,这样,jar文件就引用好了,然后就是写java代码,新建包和类。类的代码
package aaa;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
public class Demo extends AbstractJavaSamplerClient {
@Override
public Arguments getDefaultParameters(){
Arguments args = new Arguments();
args.addArgument("param", "");
return args;
}
@Override
public SampleResult runTest(JavaSamplerContext arg0) {
SampleResult sr = new SampleResult();
String param = arg0.getParameter("param");
sr.setResponseData(param.getBytes());
sr.setSuccessful(true);
return sr;
}
}
这段代码的作用非常简单,接收一个参数,然后把这个参数响应回去,类似于代码里的打印语句,可以用来查看jmeter脚本中的变量的值。然后在项目上右击,new——File
File name就是manifest.mf,这个名称不要改,是java打包的默认配置文件
第一行默认写法,固定的。第二行,指定程序的入口。注意,中间的冒号后有一个空格,最后要以一个空行结束。保存,然后就可以打包了,右击项目,选Export...
包类型,选java下的JAR file,点Next
点 Browse... 选择存放jar的路径,可以直接选到jmeter安装目录下/lib/ext/目录下,然后给包取个名称,我这里就叫Test.jar。如果jar已存在,改了之后,再重新打包,要覆盖原先的jar包,最下面的复选框,勾上。看英语就知道意思了
Next
选择下面的,从工作空间选择已存在的配置文件,再点 Browse... 选择之前添加的打包配置文件
选好后,点 OK,然后再点Finish,这样,jar包就打好了
目录下也有了相应的jar包了。接下来,就要在jmeter,添加java请求了,打开jmeter,添加线程组,添加 Java请求
可以看到类名称,已经是我们刚刚写的类了,如果不是,可以点右边向下的三角形,在下拉框中选择我们需要的类。接下来,添加一个察看结果树,然后,在java请求里面,param给一个值:123456,保存脚本,运行,然后看结果
可以看到,把我们输入的123456响应回来了,当然接收的参数也可以是一个变量,我们在测试计划上设置一个全局变量aaa,值是1234
然后,在java请求里
保存,运行,看结果
把变量的值响应回来了。
在做接口集成自动化的时候,可以把脚本中需要用到的数据,全部写到一个配置文件中,脚本开头,先用一个java请求,把脚本中的参数全部更新一下,然后再用java请求,把这些参数读出来给脚本使用。这样就可以实现,脚本每次运行时,用到的参数都不一样。读文件的代码
package king.bbb;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
public class ReadFile extends AbstractJavaSamplerClient{
public Arguments getDefaultParameters(){
Arguments args = new Arguments();
//添加一个参数,名称叫:文件路径
args.addArgument("文件路径","");
//添加一个参数,名称叫:读取的行
args.addArgument("读取的行","4");
args.addArgument("字符编码","GBK");
return args;
}
public SampleResult runTest(JavaSamplerContext arg0) {
SampleResult sr = new SampleResult();
String fileName = arg0.getParameter("文件路径").trim();
String lineStr = arg0.getParameter("读取的行").trim();
String encoding = arg0.getParameter("字符编码").trim();
sr.setDataEncoding(encoding);
File file = new File(fileName);
if(!file.isFile() || !file.exists()){
sr.setResponseData("路径是目录或是文件不存在!!!".getBytes());
sr.setSuccessful(false);
}else if(lineStr==null || "".equals(lineStr)){
sr.setResponseData("没有输入要读取的行数,不能读取文件!!!".getBytes());
sr.setSuccessful(false);
}else if(!lineStr.matches("\\d+")){
sr.setResponseData("“读取的行”参数不合法,请输入数字!!!".getBytes());
sr.setSuccessful(false);
}else{
BufferedReader reader = null;
try{
int line = Integer.parseInt(lineStr);
reader = new BufferedReader(new FileReader(file));
int nowLine = 0;
String content = null;
while((content = reader.readLine())!=null){
++nowLine;
if(nowLine==line){
break;
}
}
if(line>nowLine){
sr.setResponseData("输入的数字大于文件的行数,请核对后再输入!!!".getBytes());
sr.setSuccessful(false);
return sr;
}
if("".equals(content)){
sr.setResponseData("读取的行是空行!!!".getBytes());
sr.setSuccessful(true);
return sr;
}
String[] res = content.split(",");
StringBuffer sb = new StringBuffer();
for(int i=0; i<res.length; ++i){
sb.append("parameter"+(i+1)+":"+res[i]+",");
}
sb.delete(sb.length()-1, sb.length());
sr.setResponseData(sb.toString().getBytes());
sr.setSuccessful(true);
}catch(IOException e){
e.printStackTrace();
sr.setResponseData("打开文件出问题了!!!".getBytes());
sr.setSuccessful(false);
}finally{
if(reader != null){
try{
reader.close();
}catch(IOException e){
e.printStackTrace();
sr.setResponseData("关闭文件出问题了!!!".getBytes());
sr.setSuccessful(false);
}
}
}
}
return sr;
}
}
一次读一行,读取的数据,以英文的逗号分割,响应为parameter1:1234,parameter2:aaa这样的格式
更新文件的代码
package king.aaa;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
public class ModifyFile extends AbstractJavaSamplerClient{
public Arguments getDefaultParameters(){
Arguments args = new Arguments();
//添加一个参数,名称叫:文件路径
args.addArgument("文件路径","");
//添加一个参数,名称叫:修改的行,可以修改多行,以英文的逗号隔开
args.addArgument("修改的行","4,7,10");
//添加一个参数,名称叫:字符编号,主要是解决响应信息中文乱码的问题,默认GBK,一般不用改
args.addArgument("字符编码","GBK");
return args;
}
public SampleResult runTest(JavaSamplerContext arg0){
SampleResult sr = new SampleResult();
//获取三个参数的值
String fileName = arg0.getParameter("文件路径").trim();
String lineStr = arg0.getParameter("修改的行").trim();
String encoding = arg0.getParameter("字符编码").trim();
File file = new File(fileName);
//判断第一个参数的合法性,如果是目录,或是文件不存在,就响应错误
if(!file.isFile() || !file.exists()){
sr.setResponseData("路径是目录或是文件不存在!!!".getBytes());
sr.setSuccessful(false);
//判断第二个参数为空,就返回信息“文件未修改!!!”
}else if(lineStr==null || "".equals(lineStr.trim())){
sr.setResponseData("未添加要修改的行,文件未修改!!!".getBytes());
sr.setSuccessful(true);
//判断第二个参数的合法性,如果含有数字、空格、英文逗号之外的字符,就响应错误
}else if(!lineStr.matches("[\\d\\s,]+")){
sr.setResponseData("“修改的行”参数不合法!请不要输入数字、空格、英文逗号之外的字符!!!".getBytes());
sr.setSuccessful(false);
}else{
//用英文逗号分割“修改的行”,字符串数组
String[] lineStrs = lineStr.split(",");
//定义一个整数类型数组,用来接收上面分割的字符串数组(转化成整数类型数组)
int[] lines = new int[lineStrs.length];
try{
//遍历lineStrs字符串数组,元素都转成整数,放到整数类型数组中
for(int i=0; i<lineStrs.length; ++i){
lines[i] = Integer.parseInt(lineStrs[i].trim());
}
//数组排序
Arrays.sort(lines);
//数组去重
lines = delArray(lines);
//返回值为更改的行数,空行不会更新,大于文件总行数的参数会丢弃
int count = modifyFile(fileName, lines);
sr.setResponseData(("修改成功!!!共修改了 "+count+" 行。").getBytes());
sr.setSuccessful(true);
}catch(Exception e){
e.printStackTrace();
sr.setResponseData("出了点小状况,请联系网管!!!".getBytes());
sr.setSuccessful(false);
}
}
sr.setDataEncoding(encoding);
return sr;
}
//数组去重方法
static int[] delArray(int[] arr){
int count=0;
//找出数组中重复元素的个数
for(int i=0; i<arr.length-1; ++i){
for(int j=i+1; j<arr.length; ++j){
if(arr[i]==arr[j]){
++count;
break;
}
}
}
//定义新数组,长度为原数组的长度减去重复元素的个数
int[] resArr = new int[arr.length-count];
count = 0;
//遍历原数组,如果元素不在新数组中,就放进新数组中
out:for(int i=0; i<arr.length; ++i){
for(int j=0; j<count; ++j){
if(arr[i]==resArr[j]){
continue out;
}
}
resArr[count++] = arr[i];
}
return resArr;
}
//获取字符串中后面的数字出现位置的方法
static int positionNum(String str){
int index;
//从字符串的最后一个元素向前找,第一个非数字元素的下标,即是所要找的
for(index=str.length()-1; index>=0; --index){
char c = str.charAt(index);
if((int)c<48||(int)c>57){
break;
}
}
return index;
}
//将文件中的行更新的方法
static String modifyLine(String str){
//用英文逗号分隔行的内容,结果保存到strs字符串数组中
String[] strs = str.split(",");
//定义字符缓冲类,用来保存更新后的内容
StringBuffer sb = new StringBuffer();
//遍历strs字符串数组
for(String temp:strs){
//获取数字出现的位置
int index = positionNum(temp)+1;
//截取最后一个非数字及其之前的字符串
String word = temp.trim().substring(0, index);
//截取后面的数字部分
String num = temp.trim().substring(index, temp.length());
//记录数字部分的长度
int length = 0;
//如果数字部分为空,则让数字部分为“1”
if("".equals(num)){
num = "1";
}else{
//先把数字部分的长度记录
length = num.length();
//数字部分转成长整型,加上1后,再转成字符串
num = String.valueOf(Long.parseLong(num)+1);
}
//如果数字部分,比原先的短,就在前面补“0”
while(num.length()<length){
num = "0"+num;
}
//把处理过后的非数字和数字部分拼接起来,并在后面加英文逗号分隔,添加进字符缓冲对象
sb.append(word+num+",");
}
//把字符缓冲对象中最后面的逗号删掉
sb.delete(sb.length()-1, sb.length());
return sb.toString();
}
//更新文件的方法
static int modifyFile(String str, int[] line){
File tempFile = null;
File oldFile = new File(str);
BufferedReader reader = null;
BufferedWriter writer = null;
//有效行的数目,传进来的数组中的元素,如果大于文件的总行数,会丢弃
int lines = 0;
//有效行中空行数目
int empty = 0;
//原文件目录下,新建一个临时文件temp
String fTemp = str.substring(0, str.lastIndexOf("\\")+1)+"temp";
tempFile = new File(fTemp);
int count = 0;
//如果temp存在了就新建temp1,如果temp1也存在,就新建temp2。。。
while(tempFile.exists()){
++count;
tempFile = new File(fTemp+count);
}
try{
//读文件流
reader = new BufferedReader(new FileReader(oldFile));
//写文件流,写到临时文件
writer = new BufferedWriter(new FileWriter(tempFile));
//读到多少行
int nowLine = 0;
//读到的内容
String content = null;
while((content=reader.readLine())!=null){
++nowLine;
//如果数组的指针未越界,并且读取文件的行数等于数组的元素
if(lines<line.length&&nowLine==line[lines]){
//数组指针后移
++lines;
//读取文件的行,为空,空行数目加1,否则就更新行的内容
if("".equals(content.trim())){
++empty;
}else{
content = modifyLine(content);
}
}
//读到的行内容写到临时文件
writer.write(content);
writer.newLine();
}
}catch(IOException e){
e.printStackTrace();
System.out.println("出了点小状况,请联系网管!!!");
}finally{
if(writer!=null){
try{
writer.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(reader!=null){
try{
reader.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
//把临时文件的内容复制到原文件
copyFile(tempFile.getAbsolutePath(),str);
//删除临时文件
if(tempFile!=null){
tempFile.delete();
}
return lines-empty;
}
//复制文件的方法,效率高
static void copyFile(String oldFile, String newFile){
FileChannel oldFi = null;
FileChannel newFi = null;
try{
oldFi = new FileInputStream(new File(oldFile)).getChannel();
newFi = new FileOutputStream(new File(newFile)).getChannel();
newFi.transferFrom(oldFi, 0, oldFi.size());
}catch(IOException e){
e.printStackTrace();
}finally{
if(newFi!=null){
try{
newFi.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(oldFi!=null){
try{
oldFi.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}
要更新的行,每个参数之间有英文的逗号分隔开。更新机制,就是在原先的基础上添加数字,比如原先是"张三",更新后,就变为"张三1",但"张三1",更新后是变成"张三2",不是"张三11"。当然,现在的方法还是有漏洞,比如,更新的行,输入连续的两个逗号,就会异常了。