JMeter關聯之正則表達式提取器

一、 關聯的定義
為什么要關聯
在客戶端與服務器通信過程中,多個請求/響應間的數據會有相互依賴的關系。比如上一個請求返回的某些響應數據在后續的請求中需要用到。
下面是一些典型的例子:
- 比如第一次訪問網站獲取的session id在后續的請求都會將其傳給網站。
- 服務器生成token返回給用戶,在后續的請求中要帶上token。
- 根據條件查詢某記錄,在查詢結果集中選擇記錄進行操作(比如刪除)。
- ...
但是有些通信協議是無狀態的,不存在上下文相關性。多個請求/響應之間的數據不能直接進行傳遞;并且每次服務器返回的數據不是一成不變的,傳遞的數據不能通過硬編碼(寫死)保存來解決。
比如上面三種情況都會產生動態變化的數據:
- session id的生命周期一般在關閉瀏覽器時就結束了,每次打開瀏覽器訪問返回的session id并不相同。
- token也有生命周期,一般也是隨機,無狀態的。
- 若查詢條件參數化了或服務器返回的查詢結果集改變了,后續的操作可能會失敗。在這些情況下,可以考慮將服務器返回的動態變化的數據保存到某個參數中,需要時再從中取出。
關聯原理
舉個例子,看電影,看電影過程有如下步驟:
- 購票
- 驗票
- 觀影
每個步驟可以看做一個請求/響應。觀眾相當于客戶端,影院方相當于服務器。
過程如下圖所示:

觀眾購買的電影票可以看成服務器返回的響應數據,要驗票通過才能入場觀影。
觀眾購票相當于一個請求,驗票是下一個請求,這需要將上一個請求返回的響應數據(電影票)放在下一個請求中發送給服務器處理。
假設這部電影非常精彩,想重新再看一次,因為電影票只能使用一次,觀眾必須重新購票,才能驗票通過入場;使用第一次購買的電影票入場肯定會被拒之門外。
為了解決這個問題,可以考慮做如下假設:
每次將購買的電影票放入隨身攜帶的LV錢包,并且在放入之前將使用過的票丟棄,以防止入場時掏錯票;入場的時候,從錢包中取出票來驗票,這樣就萬無一失了。
將電影票放入錢包中,相當于將服務器返回的數據保存起來了,這里錢包就是保存關聯數據的參數。
- 關聯的定義
將服務器返回的數據包中滿足條件的數據保存到一個參數中的過程。
怎樣將服務器返回的數據保存起啦,JMeter中可以使用后置處理器來處理關聯數據,常見的方法有:
- 正則表達式提取器。
- JSON提取器。
需要關聯數據的特征
怎樣確定哪些數據是需要做關聯的,可以從關聯數據的特征來識別出這些數據。關聯數據有如下三個特征:
- 服務器返回
需要關聯的數據一定是從服務器返回的。
客戶端輸入的數據不需要進行關聯,比如輸入的用戶名與密碼。此特征是必選的。
- 數據會再次發送給服務器處理
保存上一個請求響應的數據,其目的是為了將其用于下一個請求中,否則保存起來沒有意義。此特征是可選特征,也就是說不再次發送也是可以保存數據進行關聯的。
- 數據動態變化
上一個請求響應的數據若不會動態變化,完全可以寫死在腳本中,不需要花力氣額外保存再次取出。正是由于每次返回的數據動態變化,我們需要根據某種規則將這些動態變化的數據找出來保存,然后會取出實際返回的數據。但此特征也是可選的。不動態變化一樣可以保存進行關聯,但意義不大。
二、正則表達式介紹
JMeter通過內嵌的Apache Jakarta ORO軟件來解析處理正則表達式。
Jakarta-ORO是用于處理文本的一組Java類,是目前功能最全性能最好的正則表達式API之一,它提供兼容Perl5類型的正則表達式。
單行模式與多行模式

元字符


擴展正則表達式

四、 正則表達式提取器
配置項
Apply to:
與響應斷言中用法一致,不再贅述。
Field to check:
- Body
Response Body,比如HTTP響應報文的實體主體,不包含狀態行與首部。
- Body(unescaped)
Response Body(轉換了轉義字符),對HTTP響應報文的實體主體中的所有HTML轉義字符進行了轉義處理。由于轉義時沒有參照上下文,在處理時可能會出錯,并且開啟此選項會嚴重影響性能,故不建議使用。
- Body as a Document
通過Apache Tika從各種類型的文檔中提取文本。此選項開啟也會嚴重影響性能,謹慎使用。
- Response Headers
一般用于HTTP請求,HTTP響應報文中的首部。
- Request Headers
一般用于HTTP請求,HTTP請求報文中的首部。
- URL
一般用于HTTP請求。HTTP請求報文中的請求URL地址(未開啟重定向功能);若開啟了重定向功能,則包含原始請求中的請求URL地址與重定向后的URL地址。
比如前面訪問新浪的例子,開啟了重定向后,則包括:http://www.sina.com/,http://www.sina.com.cn/和https://www.sina.com.cn/三個URL地址。
- Response code
一般用于HTTP協議,指的是HTTP響應報文中的狀態碼,比如200、301、404等。
- Response Message
一般用于HTTP協議,指的是HTTP響應報文中的原因短語,比如OK、Moved Permanently、Not Found等。
Name of created variable:
用于存儲結果的JMeter變量的名稱。
Regular Expression:
用于解析響應數據的正則表達式。使用正則表達式中的()來捕獲響應字符串。
Template($i$ where i is capturing group number,starts at 1):
設置捕獲到的字符串以怎樣的格式保存到存儲結果的JMeter變量中。
在此項中,可以用$1$表示引用捕獲組1中的內容,$2$表示引用捕獲組2中的內容,... ,$n$表示引用捕獲 組n中的內容, $0$表示引用正則表達式匹配后的整個字符串。
注意除了使用$n$引用捕獲組的內容外,還可以加入需要的字符,將匹配的內容按照某種格式保存。
Match No.(0 for Random):
匹配序號。從匹配的結果中怎樣挑選匹配項。
若正則表達式每個捕獲組有多個匹配項。
則1表示第一個匹配項,2表示第二個匹配項,... ,依次類推;0表示從多個匹配項中隨機選擇一個;-i(i=1,2,3,... ,N,-i即負整數)表示引用所有的匹配項。
Default Value:
如果正則表達式沒有匹配到內容,則保存結果的JMeter變量將設置為默認值,這樣會對調試JMeter測試帶來便利。如果沒有提供默認值,則很難判斷正則表達式是否匹配失敗,或者RE元素是否未處理或者是否使用了錯誤的變量。
但是,如果您有多個設置相同變量的測試元素,那么如果表達式不匹配,您可能希望保持變量不變。在這種情況下,請在調試完成后刪除默認值。
Use empty default value:
如果選中該復選框則默認值為空,則JMeter會將保存結果的JMeter變量設置為空字符串。
四、應用案例
案例說明
業務操作步驟:
- 登錄ECshop后臺管理系統。
- 設置查詢條件(比如按商品品牌)搜索商品。
- 在返回的查詢結果集中選擇第一個商品刪除。
這里每一步驟對應一個HTTP請求,在第二個請求中每次返回的查詢結果集不一樣(因為每執行一次會刪除一個商品),故向第三個請求傳遞的商品編號參數不能寫死,需要從第二個請求對應的響應數據中提取出來。
操作步驟
這里對第二個步驟一些細節進行說明:
在第二個請求返回的響應數據中觀察:
...
23)\">8<\/span><\/td>\r\n \r\n
href=\"..\/goods.php?id=23\" target=\"_blank\" title=\"\u67e5\u770b\">
src=\"images\/icon_view.gif\" width=\"16\" height=\"16\" border=\"0\"
...
發現返回的goods_id的左邊界為goods.php?id=,右邊界為\",但考慮到.與?以及\為元字符,故需要轉義,則正則表達式可以設置為:
goods\.php\?id=(\d+)\\"

在刪除商品請求中將提取的商品編號替換寫死的數據:


























