jmeter教程(六):java請求
我們傳送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"。當然,現在的方法還是有漏洞,比如,更新的行,輸入連續的兩個逗號,就會異常了。