在使用httpclient作接口相關測試的過程當中,遇到過一個障礙:如何處理多用戶同時登錄。以前用戶身份憑證通常都是作公參裏面處理或者在header中單獨定義一個或者幾個字段,cookie都是使用httpclient自帶的管理器自動管理的。 後來用戶憑證存到了cookie裏,這裏就有了一些障礙,通過翻看資料獲得瞭解決。java
設置以下:編程
/** * 獲取請求超時控制器 * <p> * cookieSpec:即cookie策略。參數爲cookiespecs的一些字段。做用: * 一、若是網站header中有set-cookie字段時,採用默認方式可能會被cookie reject,沒法寫入cookie。將此屬性設置成CookieSpecs.STANDARD_STRICT可避免此狀況。 * 二、若是要想忽略cookie訪問,則將此屬性設置成CookieSpecs.IGNORE_COOKIES。 * </p> * * @return */ private static RequestConfig getRequestConfig() { return RequestConfig.custom().setConnectionRequestTimeout(HttpClientConstant.CONNECT_REQUEST_TIMEOUT).setConnectTimeout(HttpClientConstant.CONNECT_TIMEOUT).setSocketTimeout(HttpClientConstant.SOCKET_TIMEOUT).setCookieSpec(CookieSpecs.IGNORE_COOKIES).setRedirectsEnabled(false).build(); }
這裏說明一點,這個requestconfig既能夠在對HTTPrequestbase進行設置,也能夠對CloseableHttpClient進行設置,因爲在各個項目中都採起了單獨處理cookie的設置,因此我是直接放在了鏈接池CloseableHttpClient對象的設置裏面,以下:json
/** * 經過鏈接池獲取https協議請求對象 * <p> * 此處會默認添加一天defaultcookiesstore,會處理響應頭中的set-cookie字段 * 增長默認的請求控制器 * </p> * * @return */ private static CloseableHttpClient getCloseableHttpsClients() { // 建立自定義的httpsclient對象 CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).setRetryHandler(httpRequestRetryHandler).setDefaultRequestConfig(requestConfig).build(); // CloseableHttpClient client = HttpClients.createDefault();//非鏈接池建立 return client; }
個人方案是在處理響應的時候,只用closeablehttpresponse對象接收響應的,而後在單獨在header裏面遍歷set-cookie字段的值,在處理json對象做爲返回體的時候添加進去,以下:cookie
/** * 響應結束以後,處理響應頭信息,如set-cookien內容 * * @param response 響應內容 * @return */ private static JSONObject afterResponse(CloseableHttpResponse response) { JSONObject cookies = new JSONObject(); List<Header> headers = Arrays.asList(response.getHeaders("Set-Cookie")); if (headers.size() == 0) return cookies; headers.forEach(x -> { String[] split = x.getValue().split(";")[0].split("=", 2); cookies.put(split[0], split[1]); }); return cookies; } /** * 根據解析好的content,轉化json對象 * * @param content * @return */ private static JSONObject getJsonResponse(String content, JSONObject cookies) { JSONObject jsonObject = new JSONObject(); try { jsonObject = JSONObject.fromObject(content); } catch (Exception e) { jsonObject.put("content", content); jsonObject.put("code", TEST_ERROR_CODE); logger.warn("響應體非json格式,已經自動轉換成json格式!"); } finally { if (!cookies.isEmpty()) jsonObject.put(HttpClientConstant.COOKIE, cookies); return jsonObject; } }
在每一個項目的base對象接收到響應以後存儲cookie以便子類繼承,在每次發送請求的時候帶上當前對象的cookie,以對象形式存儲每個用戶,達到多用戶同時登陸的目的,以下:多線程
@Override public JSONObject getResponse(HttpRequestBase httpRequestBase) { setHeaders(httpRequestBase); JSONObject response = FanLibrary.getHttpResponse(httpRequestBase); handleResponseHeader(response); return response; } @Override public void setHeaders(HttpRequestBase httpRequestBase) { httpRequestBase.addHeader(Common.REQUEST_ID); httpRequestBase.addHeader(FanLibrary.getHeader("token", token)); if (!cookies.isEmpty()) httpRequestBase.addHeader(FanLibrary.getCookies(cookies)); } @Override public void handleResponseHeader(JSONObject response) { if (!response.containsKey(HttpClientConstant.COOKIE)) return; cookies.putAll(response.getJSONObject(HttpClientConstant.COOKIE)); response.remove(HttpClientConstant.COOKIE); }