轉自:https://blog.csdn.net/fhaohaizi/article/details/77850302
2018年07月19日更新,主要是解耦之后方法很多地方發生了變化,httpclient用了連接池方式,作為一個靜態變量處理,請求頭和響應頭以及cookies設置都有了相關處理方法,本來這個方法已經快超過100行了,解耦之后分成了幾個小方法,方便修改和調試。分兩部分,一部分是框架,只做了公共處理,另外一部分是每個項目的base類需要重新實現一些這個方法來處理header信息以及需要特殊處理的地方。分享代碼如下:
/** * 獲取響應實體 * * @param request 請求對象 * @return 返回json類型的對象 */ protected static JSONObject getHttpResponse(HttpRequestBase request) { beforeRequest(request); JSONObject jsonObject = new JSONObject(); RequestInfo requestInfo = new RequestInfo(request); CloseableHttpResponse response = null;// 創建響應對象 Date start = getDate();// 記錄開始時間 try { response = ClientManage.httpsClient.execute(request); } catch (Exception e) { new Thread(() -> new AlertOver("接口請求失敗", requestInfo.toString() + Arrays.toString(e.getStackTrace()), requestInfo.getUrl()).sendSystemMessage()).start(); return jsonObject; } Date end = getDate();// 記錄結束時間 double elapsed_time = getTimeDiffer(start, end);// 獲取響應耗時 afterResponse(response); int status = response.getStatusLine().getStatusCode();// 獲取響應狀態 String content = getContent(response); long data_size = content.length(); jsonObject = getResponse(content); int code = checkCode(jsonObject, requestInfo.getUrl()); if (status != HttpStatus.SC_OK) new Thread(() -> new AlertOver("響應狀態碼錯誤", "狀態碼錯誤:" + status, requestInfo.getUrl()).sendSystemMessage()); MySqlTest.saveApiTestDate(requestInfo, data_size, elapsed_time, status, getMark(), code, LOCAL_IP, COMPUTER_USER_NAME); return jsonObject; }
下面是里面封裝方法的依次分享:
/** * 發送請求之前,配置請求管理器,設置IP,user_agent和cookie * * @param request */ private static void beforeRequest(HttpRequestBase request) { request.setConfig(requestConfig);//設置請求配置 request.addHeader(getHeader("X-FORWARDED-FOR", getRandomIP()));//隨機生成ip request.addHeader(HTTP.USER_AGENT, USER_AGENT); if (cookies != null && !Arrays.toString(request.getAllHeaders()).contains(REQUEST_HEADER_COOKIE)) request.addHeader(REQUEST_HEADER_COOKIE, cookies);// 添加cookie }
requestinfo類的方法:
package com.fission.source.httpclient; import com.fission.source.source.SourceCode; import lombok.Data; import org.apache.http.HttpEntity; import org.apache.http.ParseException; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.util.EntityUtils; import java.io.IOException; /** * 請求信息封裝類 */ @Data public class RequestInfo extends SourceCode { /** * 接口地址 */ String apiName; /** * 請求的url */ String url; /** * 請求的uri */ String uri; /** * 方法,get/post */ String method; /** * 域名 */ String host; /** * 協議類型 */ String type; /** * 參數 */ String params; /** * 通過request獲取請求的相關信息,並輸出部分信息 * * @param request */ public RequestInfo(HttpRequestBase request) { getRequestInfo(request); if (!host.contains("alertover") && !host.contains("lonelymind")) output(TAB + TAB + TAB + "請求uri:" + uri + LINE + TAB + TAB + TAB + "請求參數是:" + params); } /** * 封裝獲取請求的各種信息的方法 * * @param request 傳入請求對象 * @return 返回一個map,包含api_name,host_name,type,method,params */ private void getRequestInfo(HttpRequestBase request) { method = request.getMethod();// 獲取method uri = request.getURI().toString();// 獲取uri getRequestUrl(uri); String one = url.substring(url.indexOf("//") + 2);// 刪除掉http:// apiName = one.substring(one.indexOf("/"));// 獲取接口名 host = one.substring(0, one.indexOf("/"));// 獲取host地址 type = url.substring(0, url.indexOf("//") - 1);// 獲取協議類型 if (method.equals(REQUEST_TYPE_GET)) { params = uri.substring(uri.indexOf("?") + 1, uri.length()); } else if (method.equals(REQUEST_TYPE_POST)) { getPostRequestParams(request); } } /** * 獲取請求url,遇到get請求,先截取 * * @param uri */ private void getRequestUrl(String uri) { url = uri; if (uri.contains("?")) url = uri.substring(0, uri.indexOf("?")); } /** * 獲取post請求的參數 * * @param request */ private void getPostRequestParams(HttpRequestBase request) { HttpPost httpPost = (HttpPost) request;// 強轉httppost請求 HttpEntity entity = httpPost.getEntity();// 獲取實體 if (entity == null) return; try { params = EntityUtils.toString(entity);// 解析實體 EntityUtils.consume(entity);// 確保實體消耗 } catch (UnsupportedOperationException e) { params = "entity類型:" + entity.getClass(); } catch (ParseException e) { output("解析響應實體異常!", e); } catch (IOException e) { output("解析響應實體時java IO 異常!", e); } } }
/** * 響應結束之后,處理響應頭信息,如set-cookien內容 * * @param response */ private static void afterResponse(CloseableHttpResponse response) { if (response == null) return; List<Header> headers = Arrays.asList(response.getHeaders("Set-Cookie")); if (!headers.equals(new ArrayList<>())) setCookies(headers); if (cookieSet == false && cookies != null) cookieSet = true; }
/** * 根據響應獲取響應實體 * * @param response * @return */ private static String getContent(CloseableHttpResponse response) { HttpEntity entity = response.getEntity();// 獲取響應實體 String content = EMPTY; try { content = EntityUtils.toString(entity, UTF_8);// 用string接收響應實體 EntityUtils.consume(entity);// 消耗響應實體,並關閉相關資源占用 if (response != null) response.close(); } catch (ParseException e1) { output("解析響應實體異常!", e1); } catch (IOException e1) { output("解析響應實體時java IO 異常!", e1); } return content; }
/** * 根據解析好的content,轉化json對象 * * @param content * @return */ private static JSONObject getResponse(String content) { JSONObject jsonObject = new JSONObject(); try { jsonObject = JSONObject.fromObject(content); } catch (Exception e) { jsonObject.put("content", content); jsonObject.put("code", TEST_ERROR_CODE); } return jsonObject; }
/** * 獲取並檢查code * * @param jsonObject * @param url * @return */ private static int checkCode(JSONObject jsonObject, String url) { int code = TEST_ERROR_CODE; try { code = jsonObject.getInt("code"); if (ERROR_CODE_LIST.contains(code)) new Thread(() -> new AlertOver("responseCode錯誤", jsonObject.toString(), url).sendSystemMessage()); } catch (Exception e) { output("響應非標准響應體!", e); } return code; }
其中數據庫存儲的和發送提醒消息的這里就不說了,數據庫一部存儲還在優化,alertover使用方法在其他文章分享過了。
------------------------------------分割線--------------------------------------
本人在使用httpclient做接口測試的時候,需要統計一下接口的一些信息,在寫用例的過程中為了提高復用,簡化一些結構,所以封裝了一些基本方法,分享一下獲取響應實體和響應信息的方法,共大家參考。
//獲取post響應,暫無header設置 public JSONObject getHttpResponseEntityByJson(CloseableHttpClient httpClient, HttpPost httpPost) throws ClientProtocolException, IOException, SQLException, JSONException { //在請求中明確定義不要進行壓縮 // httpPost.setHeader("Accept-Encoding", "identity"); HttpResponse response = null;//創建響應對象 long date_size = 0;//用於存放數據大小 String api_name = getApiName(httpPost);//獲取接口名稱 String type = getProtocolType(httpPost);//獲取協議類型 String host_name = getHostName(httpPost);//獲取hsot主機名稱 Date start = getDate();//記錄開始時間 response = httpClient.execute(httpPost);//獲取響應 Date end = getDate();//記錄結束時間 double elapsed_time= outputTimeDiffer(start, end, "接口:" + api_name);//獲取響應耗時 int status = response.getStatusLine().getStatusCode();//獲取響應狀態 if (status == HttpStatus.SC_OK) {//判斷一下返回狀態 output("host:" + host_name, "接口:"+ api_name + "請求成功!"); } else { output(response.getStatusLine().getStatusCode() + LINE + "請求失敗!"); } HttpEntity entity = response.getEntity();//獲取響應實體 data_size = entity.getContentLength();//獲取相應數據大小 if (data_size == -1) {//如果為-1,則重置date_size date_size = 0; } String content = EntityUtils.toString(entity);//解析響應 if (date_size == 0) {//如果被重置或者沒有獲取到,則date_size等於解析string大小 date_size = content.length(); } JSONObject jsonObject = new JSONObject(content);//轉換json LocalMySql.getInstance().saveApiTestDate(host_name, api_name, date_size, elapsed_time, status, type); // httpClient.close();//關閉客戶端 return jsonObject; } //獲取get接口響應,暫無header設置 public JSONObject getHttpResponseEntityByJson(CloseableHttpClient httpClient, HttpGet httpGet) throws ClientProtocolException, IOException, JSONException, SQLException { //在請求中明確定義不要進行壓縮 // httpGet.setHeader("Accept-Encoding", "identity"); HttpResponse response = null; long date_size = 0; String api_name = getApiName(httpGet); String type = getProtocolType(httpGet); Date start = getDate(); response = httpClient.execute(httpGet); Date end = getDate(); double elapsed_time= outputTimeDiffer(start, end, "接口:" + api_name); String host_name = getHostName(httpGet); int status = response.getStatusLine().getStatusCode(); if (status == HttpStatus.SC_OK) {//判斷一下返回狀態 output("host:" + host_name, "接口:"+ api_name + "請求成功!"); } else { output(response.getStatusLine().getStatusCode() + LINE + "請求失敗!"); } HttpEntity entity = response.getEntity(); data_size = entity.getContentLength(); if (data_size == -1) { date_size = 0; } String content = EntityUtils.toString(entity); if (date_size == 0) { date_size = content.length(); } JSONObject jsonObject = new JSONObject(content); LocalMySql.getInstance().saveApiTestDate(host_name, api_name, date_size, elapsed_time, status, type); // httpClient.close(); return jsonObject; }
中間使用了本地數據庫,將收集的信息存入本地數據庫里面,以便以后統計。代碼如下:
//保存接口測試數據的方法 public void saveApiTestDate(String host_name, String api_name, long date_size, double elapsed_time, int status, String type) throws SQLException { getConnection(); if (!connection.isClosed()) { outputSuccess(); Statement statement = connection.createStatement(); String sql = "INSERT INTO api_result (host_name,api_name,date_size,elapsed_time,status,type) VALUES ('"+host_name+"','"+api_name+"'," +date_size+","+ elapsed_time + "," + status + ",'" + type +"');"; // output(sql); statement.executeUpdate(sql); } }
中間用到了一些自己封裝的方法:
//獲取json數據中的相應值 public String getJsonValue(String jsonString, String key) throws JSONException { String JsonValue = null; if (jsonString == null || jsonString.trim().length() < 1) {//排除為空和空格 return null; } JSONObject obj1 = new JSONObject(jsonString); JsonValue = (String) obj1.getString(key); return JsonValue;//返回對應值 } //獲取json數據中的相應值 public String getJsonValue(JSONObject jsonObject, String key) { String JsonValue = "··-·"; try { JsonValue = (String) jsonObject.getString(key); } catch (JSONException e) { output("json數據錯誤!"); output(e.toString()); } return JsonValue;//返回對應值 } //把json數據轉化為參數 public String changeJsonToArguments(JSONObject argument) { String one = argument.toString(); String two ="?" + one.substring(1, one.length()-1).replace(",", "&").replace(":", "=").replace("\"", ""); return two; } //獲取接口名稱 public String getApiName(HttpGet httpGet) { String url = getUrl(httpGet); String apiName = url.substring(url.indexOf("m/") + 1); return apiName; } //獲取接口名稱 public String getApiName(HttpPost httpPost) { String url = getUrl(httpPost); String apiName = url.substring(url.indexOf("m/") + 1); return apiName; } //獲取host名稱 public String getHostName(HttpPost httpPost) { String url = getUrl(httpPost); String host = url.substring(url.indexOf("//") + 2, url.indexOf("m/") + 2); return host; } //獲取host名稱 public String getHostName(HttpGet httpGet) { String url = getUrl(httpGet); String host = url.substring(url.indexOf("//") + 2, url.indexOf("m/") + 2); return host; } //獲取url public String getUrl(HttpGet httpGet) { String uri = httpGet.getURI().toString(); String url = uri.substring(0, uri.indexOf("?")); return url; } //獲取url public String getUrl(HttpPost httpPost) { String url = httpPost.getURI().toString(); if (url.contains("?")) { url = url.substring(0, url.indexOf("?")); } return url; } //獲取協議類型 public String getProtocolType(HttpGet httpGet) { String uri = httpGet.getURI().toString(); String type = uri.substring(0, uri.indexOf("//") - 1); return type; } //獲取協議類型 public String getProtocolType(HttpPost httpPost) { String uri = httpPost.getURI().toString(); String type = uri.substring(0, uri.indexOf("//") - 1); return type; } //輸出json public void output(JSONObject jsonObject) { String info = jsonObject.toString().replaceAll(",", LINE); output(info); }
