在使用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); }