1. 程式人生 > >Jmeter二次開發——基於Java請求

Jmeter二次開發——基於Java請求

# 簡述 這近幾年,越來越多非http的協議需要進行效能測試,包括不僅限於各類rpc、mq、快取等。對於這些協議,市面上可能沒有現成的工具可以直接使用,這個時候,我們可以自己動手,通過編寫相應的JavaSampler來高效地開展效能測試工作。 # 環境準備 - java環境已搭建ok - jmeter環境已搭建ok - idea開發環境已配置ok java和jmeter環境搭建,可參考[Jmeter——環境搭建](https://www.cnblogs.com/hong-fithing/p/7640014.html) # 二次開發 ## 二次開發前提 - 需要lib/ext中的ApacheJMeter_core.jar - 擴充套件java請求則還需要ApacheJMeter_java.jar - 擴充套件http請求則需要ApacheJMeter_http.jar 匯入jar包,自行匯入,可參考[IDEA的基本操作——匯入匯出jar包](https://www.cnblogs.com/hong-fithing/p/13964449.html) ## Jmeter Java Sampler ### 方法簡介 ``` public Arguments getDefaultParameters(); 可選,定義可用引數及預設值,獲取介面的引數; public void setupTest(JavaSamplerContext arg0); 可選,測試前執行,做一些初始化工作,類似於LR的init和Junit中的setUp(); public SampleResult runTest(JavaSamplerContext arg0); 必選,實現自定義請求,類似於LR的Action; public void teardownTest(JavaSamplerContext arg0); 可選,測試結束時呼叫,類似於LR的end和Junit中的tearDown(); ``` ### 方法執行順序 getDefaultParameters() > setupTest(JavaSamplerContext arg0) > runTest(JavaSamplerContext arg0) > teardownTest(JavaSamplerContext arg0) ### 常用方法 - addArgument("name", "value") 定義引數 - sampleStart() 定義事務的開始,類似於LR的lr_start_transaction,和LR一樣事務間不要放無關程式碼 - sampleEnd() 定義事務的結束,類似於LR的lr_end_transaction - setSuccessful(true、false) 設定執行結果的成功或失敗,Jmeter統計成功失敗的次數,在聚合報告中能夠體現。 ## 類的繼承 在做二次開發的時候,大家都知道,自己定義的類需要繼承AbstractJavaSamplerClient,可為什麼要繼承這個類,而不是其他,想必大家也都知道。為了能看的更明白,我們直接來看程式碼,如下所示: ``` public abstract class AbstractJavaSamplerClient implements JavaSamplerClient { private static final Logger log = LoggerFactory.getLogger(AbstractJavaSamplerClient.class); private static final org.apache.log.Logger oldLogger = LoggingManager.getLoggerForClass(); public AbstractJavaSamplerClient() { } public void setupTest(JavaSamplerContext context) { log.debug(this.getClass().getName() + ": setupTest"); } public void teardownTest(JavaSamplerContext context) { log.debug(this.getClass().getName() + ": teardownTest"); } public Arguments getDefaultParameters() { return null; } /** @deprecated */ @Deprecated protected org.apache.log.Logger getLogger() { return oldLogger; } protected Logger getNewLogger() { return log; } } ``` 我們從上述程式碼看到有構造方法,3個普通方法,這3個方法是不是似曾相識?是的,在前文中就有提到。但發現,還少一個runTest方法,那它在哪呢?想必就是在這個類**JavaSamplerClient**中了。我們繼續來看程式碼,如下所示: ``` public interface JavaSamplerClient { void setupTest(JavaSamplerContext var1); SampleResult runTest(JavaSamplerContext var1); void teardownTest(JavaSamplerContext var1); Arguments getDefaultParameters(); } ``` 好了,現在知道4個方法的來源了,在自己類中,實現功能,其實就是將這4個方法重寫,來實現自己的功能即可。思路有了,我們就來真實來寫個demo吧。 ## getDefaultParameters 編寫getDefaultParameters()方法,使用addArgument方法,設定入參,程式碼示例如下: ``` /** * 這個方法是用來自定義java方法入參的 * params.addArgument("x","");表示入參名字叫x,預設值為空。 * @return */ @Override public Arguments getDefaultParameters() { Arguments params = new Arguments(); params.addArgument("x",""); return params; } ``` 該引數設定,在jmeter介面中會展示,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218204521674-805410389.png) ## setupTest setupTest,做自動化、效能測試都有類似概念,就是在測試前執行,做一些初始化工作。示例程式碼如下所示: ``` /** * 每個執行緒測試前執行一次,做一些初始化工作 * 獲取輸入的引數,賦值給變數,引數也可以在下面的runTest方法中獲取,這裡是為了展示該方法的作用 * @param arg0 */ @Override public void setupTest(JavaSamplerContext arg0) { x = arg0.getParameter("x"); } ``` ## runTest runTest是程式碼邏輯處理部分,示例程式碼實現的功能就是做數字簡單的比較,demo而已,具體如下所示: ``` /** * 真正執行邏輯的方法 * @param arg0 * @return */ @Override public SampleResult runTest(JavaSamplerContext arg0) { SampleResult sr = new SampleResult(); sr.setSamplerData("請求引數x的值為:"+x); try { // jmeter 開始統計響應時間標記 sr.sampleStart(); int sum = Integer.parseInt(x); if (sum<0){ logger.info(sum + "<0的值是"+ "-1"); // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。 sr.setResponseData("結果是:"+"-1", "utf-8"); //設定響應失敗 sr.setSuccessful(false); } else { String str = String.valueOf(x); final StringBuilder builder = new StringBuilder(str); if (builder.reverse().toString().equals(str)) { //reverse 字串反轉,比如輸入66,反轉後為66,再做比較 logger.info(sum + ">
0的值做比較後是"+ "0"); // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。 sr.setResponseData("結果是:"+"0", "utf-8"); sr.setDataType(SampleResult.TEXT); }else { logger.info(sum + ">0的值是"+ "1"); // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。 sr.setResponseData("結果是:"+"1", "utf-8"); } //設定響應執行成功 sr.setSuccessful(true); } } catch (Throwable e) { //有異常,執行失敗 sr.setSuccessful(false); e.printStackTrace(); } finally { // jmeter 結束統計響應時間標記 sr.sampleEnd(); } return sr; } ``` ## teardownTest teardownTest,與setupTest是對應關係,做自動化、效能測試都有類似概念,就是在測試結束後執行,做一些清理工作。示例程式碼如下所示: ``` /** * 測試結束後呼叫 * @param arg0 */ @Override public void teardownTest(JavaSamplerContext arg0) { SampleResult sr = new SampleResult(); logger.info("測試結束"); // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。 sr.setResponseData("測試結束", "utf-8"); } ``` 完成程式碼編寫後,可以先除錯一波,確保正確後,匯出jar包,放到jmeter對應目錄lib/ext下。匯出jar包的操作,可參考[IDEA的基本操作——匯入匯出jar包](https://www.cnblogs.com/hong-fithing/p/13964449.html) ## 實際效果 說了這麼多,我們來執行下程式碼看下實際效果,啟動jmeter,新增java 請求,並選擇剛編寫的java方法,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218212801041-2076968231.png) ### 輸出為-1 先來演示輸出為-1的效果,我們可以從程式碼中看出,結果為-1,輸入值小於0即可。 我們入參-9,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218212957662-1280639581.png) 執行程式碼,通過結果樹檢視請求資料,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218212919276-1247675925.png) 檢視響應資料,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218213210382-1536250784.png) 我們看介面響應情況,響應是失敗的,為啥是失敗的呢?我們從程式碼可知,入參小於0時,強制設定成了響應失敗,執行效果如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218213427291-516628374.png) ### 輸出為1 再來演示輸出為1的效果,我們可以從程式碼中看出,結果為1,輸入值大於0即可。 我們入參78,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218213725226-1297045977.png) 執行程式碼,通過結果樹檢視請求資料,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218213706143-1162738798.png) 檢視響應資料,響應的狀態也是成功的,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218213749671-728293001.png) ### 輸出等於0 最後演示下輸出為0的效果,我們可以從程式碼中看出,結果為0,輸入值轉換後還相等,則輸出為0。 我們入參66,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218215802159-154794346.png) 執行程式碼,通過結果樹檢視請求資料,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218214111443-1074267583.png) 檢視響應資料,響應的狀態也是成功的,如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218214128667-1977677777.png) # 完整程式碼 再貼下今天演示demo的完整程式碼,如下所示: ``` 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.protocol.java.test.JavaTest; import org.apache.jmeter.samplers.SampleResult; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; /** * @author_router:wenyihuqingjiu * @date:2020-12-18 * */ public class PalindromeDemo extends AbstractJavaSamplerClient { private static Logger logger = LogManager.getLogger(PalindromeDemo.class.getName()); private String x; /** * 這個方法是用來自定義java方法入參的 * params.addArgument("x","");表示入參名字叫x,預設值為空。 * @return */ @Override public Arguments getDefaultParameters() { Arguments params = new Arguments(); params.addArgument("x",""); return params; } /** * 每個執行緒測試前執行一次,做一些初始化工作 * 獲取輸入的引數,賦值給變數,引數也可以在下面的runTest方法中獲取,這裡是為了展示該方法的作用 * @param arg0 */ @Override public void setupTest(JavaSamplerContext arg0) { x = arg0.getParameter("x"); } /** * 真正執行邏輯的方法 * @param arg0 * @return */ @Override public SampleResult runTest(JavaSamplerContext arg0) { SampleResult sr = new SampleResult(); sr.setSamplerData("請求引數x的值為:"+x); try { // jmeter 開始統計響應時間標記 sr.sampleStart(); int sum = Integer.parseInt(x); if (sum<0){ logger.info(sum + "<0的值是"+ "-1"); // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。 sr.setResponseData("結果是:"+"-1", "utf-8"); //設定響應失敗 sr.setSuccessful(false); } else { String str = String.valueOf(x); final StringBuilder builder = new StringBuilder(str); if (builder.reverse().toString().equals(str)) { //reverse 字串反轉,比如輸入66,反轉後為66,再做比較 logger.info(sum + ">
0的值做比較後是"+ "0"); // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。 sr.setResponseData("結果是:"+"0", "utf-8"); sr.setDataType(SampleResult.TEXT); }else { logger.info(sum + ">0的值是"+ "1"); // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。 sr.setResponseData("結果是:"+"1", "utf-8"); } //設定響應執行成功 sr.setSuccessful(true); } } catch (Throwable e) { //有異常,執行失敗 sr.setSuccessful(false); e.printStackTrace(); } finally { // jmeter 結束統計響應時間標記 sr.sampleEnd(); } return sr; } /** * 測試結束後呼叫 * @param arg0 */ @Override public void teardownTest(JavaSamplerContext arg0) { SampleResult sr = new SampleResult(); logger.info("測試結束"); // 通過下面的操作就可以將被測方法的響應輸出到Jmeter的察看結果樹中的響應資料裡面了。 sr.setResponseData("測試結束", "utf-8"); } } ``` # 問題總結 執行程式碼,報錯提示沒有LoggerFactory,報錯如下所示: ![](https://img2020.cnblogs.com/blog/1242227/202012/1242227-20201218215143857-1392983937.png) 解決辦法:重新下載slf4j包即可。 以上就是今天的分享內容了,二次開發java請求,小小demo,有誤之處,望批評