1. 程式人生 > >jmeter教程(六):java請求

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"。當然,現在的方法還是有漏洞,比如,更新的行,輸入連續的兩個逗號,就會異常了。