欢迎光临
梦想从学习开始!

HttpComponents组件特性探究| 小熊测试

本文主要介绍 HttpComponents组件特性探究| 小熊测试,小熊希望对大家的学习或者工作具有一定的参考学习价值,在测试领域有所提升和发展。

  在Java领域,谈到网络编程,可能大家脑海里第一反应就是MINA,NETTY,GRIZZLY等优秀的开源框架。没错,不过在深入探究这些框架之前,我们需要先从最original的技术探究开始(当然,需要大家先熟悉java.net.*类库)。这里,我要和大家分享一下HttpComponents项目的部分组件特性。HttpClient,想必大家早都接触过了吧。HttpComponents和HttpClient的”血缘“有点像guava和google-collection的关系。目前,HttpComponents已经是Apache的顶级项目了,它旨在为我们提供一个Http协议相关的Java平台工具集。它的代码组织很精妙,主要分两部分,一部分是核心工具集(包括HttpCore-bio,HttpCore-nio,HttpClient,HttpMIme,HttpCookie等),一部分是扩展工具集(目前主要包括ssl)   HttpClient主要包括Connection management,Status management,Authentication Management三部分。下面给出对它的二次封装,经过了线上的接近半年的验证(这里指的是httpClient 3,httpClient 4还有待检验),可以看做是一个高性能的Client封装吧。感兴趣的朋友可以根据apache的MPM IO模型进行部分参数的调整。   先来段httpClient 4的封装,代码如下:   [java] view plaincopyprint?   /**   * @author von gosling 2012-3-2   */   public class HttpComponentsClientExecutor implements DisposableBean {   private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100;   private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 5; //notice IE 6,7,8   private static final int DEFAULT_CONN_TIMEOUT_MILLISECONDS = 5 * 1000;   private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = 60 * 1000;   private static final String HTTP_HEADER_CONTENT_ENCODING = "Content-Encoding";   private static final String ENCODING_GZIP = "gzip";   private HttpClient httpClient;   /**   * Create a new instance of the HttpComponentsClient with a default   * {@link HttpClient} that uses a default   * {@link org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager}.   */   public HttpComponentsClientExecutor() {   SchemeRegistry schemeRegistry = new SchemeRegistry();   schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));   schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));   ThreadSafeClientConnManager connectionManager = new ThreadSafeClientConnManager(   schemeRegistry);   connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS);   connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);   this.httpClient = new DefaultHttpClient(connectionManager);   setConnectTimeout(DEFAULT_CONN_TIMEOUT_MILLISECONDS);   setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);   }   /**   * Create a new instance of the HttpComponentsClient with the given   * {@link HttpClient} instance.   *   * @param httpClient the HttpClient instance to use for this request   */   public HttpComponentsClientExecutor(HttpClient httpClient) {   Validate.notNull(httpClient, "HttpClient must not be null");   //notice: if you want to custom exception recovery mechanism   //you should provide an implementation of the HttpRequestRetryHandler interface.   this.httpClient = httpClient;   }   /**   * Set the {@code HttpClient} used by this request.   */   public void setHttpClient(HttpClient httpClient) {   this.httpClient = httpClient;   }   /**   * Return the {@code HttpClient} used by this request.   */   public HttpClient getHttpClient() {   return this.httpClient;   }   /**   * Set the connection timeout for the underlying HttpClient. A timeout value   * of 0 specifies an infinite timeout.   *   * @param timeout the timeout value in milliseconds   */   public void setConnectTimeout(int timeout) {   Validate.isTrue(timeout >= 0, "Timeout must be a non-negative value");   getHttpClient().getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,   timeout);   }   /**   * Set the socket timeout (SO_TIMEOUT) in milliseconds, which is the timeout   * for waiting for data or, put differently, a maximum period inactivity   * between two consecutive data packets.A timeout value of 0 specifies an   * infinite timeout.   *   * @param timeout the timeout value in milliseconds   */   public void setReadTimeout(int timeout) {   Validate.isTrue(timeout >= 0, "Timeout must be a non-negative value");
  getHttpClient().getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, timeout);   }   /**   * Create a Commons HttpMethodBase object for the given HTTP method and URI   * specification.   *   * @param httpMethod the HTTP method   * @param uri the URI   * @return the Commons HttpMethodBase object   */   protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {   switch (httpMethod) {   case GET:   return new HttpGet(uri);   case DELETE:   return new HttpDelete(uri);   case HEAD:   return new HttpHead(uri);   case OPTIONS:   return new HttpOptions(uri);   case POST:   return new HttpPost(uri);   case PUT:   return new HttpPut(uri);   case TRACE:   return new HttpTrace(uri);   default:   throw new IllegalArgumentException("Invalid HTTP method: " + httpMethod);   }   }   /**   * Execute the given method on the provided URI.   *   * @param method the HTTP method to execute (GET, POST, etc.)   * @param url the fully-expanded URL to connect to   * @param responseHandler httpClient will automatically take care of   * ensuring release of the connection back to the connection   * manager regardless whether the request execution succeeds or   * causes an exception,if using this response handler   * @return an response object's string representation   * @throws IOException   * @throws ClientProtocolException   */   public String doExecuteRequest(HttpMethod httpMethod, URI uri,   ResponseHandler responseHandler)   throws ClientProtocolException, IOException {   return httpClient.execute(createHttpUriRequest(httpMethod, uri), responseHandler);   }   public InputStream doExecuteRequest(HttpMethod httpMethod, URI uri)   throws ClientProtocolException, IOException {   //1.   HttpUriRequest httpUriRequest = createHttpUriRequest(httpMethod, uri);   //2.   HttpResponse response = httpClient.execute(httpUriRequest);   //3.   validateResponse(response);   //4.   return getResponseBody(response);   }   /**   * Validate the given response, throwing an exception if it does not   * correspond to a successful HTTP response.   *   * Default implementation rejects any HTTP status code beyond 2xx, to avoid   * parsing the response body and trying to deserialize from a corrupted   * stream.   *   * @param config the HTTP invoker configuration that specifies the target   * service   * @param response the resulting HttpResponse to validate   * @throws NoHttpResponseException   * @throws java.io.IOException if validation failed   */   protected void validateResponse(HttpResponse response) throws IOException {   StatusLine status = response.getStatusLine();   if (status.getStatusCode() >= 300) {   throw new NoHttpResponseException(   "Did not receive successful HTTP response: status code = "   + status.getStatusCode() + ", status message = ["   + status.getReasonPhrase() + "]");   }   }   /**   * Extract the response body   *   * The default implementation simply fetches the response body stream. If   * the response is recognized as GZIP response, the InputStream will get   * wrapped in a GZIPInputStream.   *   * @param httpResponse the resulting HttpResponse to read the response body   * from   * @return an InputStream for the response body   * @throws java.io.IOException if thrown by I/O methods   * @see #isGzipResponse   * @see java.util.zip.GZIPInputStream   */   protected InputStream getResponseBody(HttpResponse httpResponse) throws IOException {   if (isGzipResponse(httpResponse)) {   return new GZIPInputStream(httpResponse.getEntity().getContent());   } else {   return httpResponse.getEntity().getContent();   }   }   /**   * Determine whether the given response indicates a GZIP response.   *   * The default implementation checks whether the HTTP "Content-Encoding"
   * header contains "gzip" (in any casing).   *   * @param httpResponse the resulting HttpResponse to check   * @return whether the given response indicates a GZIP response   */   protected boolean isGzipResponse(HttpResponse httpResponse) {   Header encodingHeader = httpResponse.getFirstHeader(HTTP_HEADER_CONTENT_ENCODING);   return (encodingHeader != null && encodingHeader.getValue() != null && encodingHeader   .getValue().toLowerCase().contains(ENCODING_GZIP));   }   /**   * Shutdown hook that closes the underlying   * {@link org.apache.http.conn.ClientConnectionManager   * ClientConnectionManager}'s connection pool, if any.   */   public void destroy() {   getHttpClient().getConnectionManager().shutdown();   }   enum HttpMethod {   GET,   POST,   HEAD,   OPTIONS,   PUT,   DELETE,   TRACE   }   }   /**   * @author von gosling 2012-3-2   */   public class HttpComponentsClientExecutor implements DisposableBean {   private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100;   private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 5; //notice IE 6,7,8   private static final int DEFAULT_CONN_TIMEOUT_MILLISECONDS = 5 * 1000;   private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = 60 * 1000;   private static final String HTTP_HEADER_CONTENT_ENCODING = "Content-Encoding";   private static final String ENCODING_GZIP = "gzip";   private HttpClient httpClient;   /**   * Create a new instance of the HttpComponentsClient with a default   * {@link HttpClient} that uses a default   * {@link org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager}.   */   public HttpComponentsClientExecutor() {   SchemeRegistry schemeRegistry = new SchemeRegistry();   schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));   schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));   ThreadSafeClientConnManager connectionManager = new ThreadSafeClientConnManager(   schemeRegistry);   connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS);   connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);   this.httpClient = new DefaultHttpClient(connectionManager);   setConnectTimeout(DEFAULT_CONN_TIMEOUT_MILLISECONDS);   setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);   }   /**   * Create a new instance of the HttpComponentsClient with the given   * {@link HttpClient} instance.   *   * @param httpClient the HttpClient instance to use for this request   */   public HttpComponentsClientExecutor(HttpClient httpClient) {   Validate.notNull(httpClient, "HttpClient must not be null");   //notice: if you want to custom exception recovery mechanism   //you should provide an implementation of the HttpRequestRetryHandler interface.   this.httpClient = httpClient;   }   /**   * Set the {@code HttpClient} used by this request.   */   public void setHttpClient(HttpClient httpClient) {   this.httpClient = httpClient;   }   /**   * Return the{@code HttpClient} used by this request.   */   public HttpClient getHttpClient() {   return this.httpClient;   }   /**   * Set the connection timeout for the underlying HttpClient. A timeout value   * of 0 specifies an infinite timeout.   *   * @param timeout the timeout value in milliseconds   */   public void setConnectTimeout(int timeout) {   Validate.isTrue(timeout >= 0, "Timeout must be a non-negative value");   getHttpClient().getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,   timeout);   }   /**   * Set the socket timeout (SO_TIMEOUT) in milliseconds, which is the timeout   * for waiting for data or, put differently, a maximum period inactivity   * between two consecutive data packets.A timeout value of 0 specifies an   * infinite timeout.   *   * @param timeout the timeout value in milliseconds
  */   public void setReadTimeout(int timeout) {   Validate.isTrue(timeout >= 0, "Timeout must be a non-negative value");   getHttpClient().getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, timeout);   }   /**   * Create a Commons HttpMethodBase object for the given HTTP method and URI   * specification.   *   * @param httpMethod the HTTP method   * @param uri the URI   * @return the Commons HttpMethodBase object   */   protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {   switch (httpMethod) {   case GET:   return new HttpGet(uri);   case DELETE:   return new HttpDelete(uri);   case HEAD:   return new HttpHead(uri);   case OPTIONS:   return new HttpOptions(uri);   case POST:   return new HttpPost(uri);   case PUT:   return new HttpPut(uri);   case TRACE:   return new HttpTrace(uri);   default:   throw new IllegalArgumentException("Invalid HTTP method: " + httpMethod);   }   }   /**   * Execute the given method on the provided URI.   *   * @param method the HTTP method to execute (GET, POST, etc.)   * @param url the fully-expanded URL to connect to   * @param responseHandler httpClient will automatically take care of   * ensuring release of the connection back to the connection   * manager regardless whether the request execution succeeds or   * causes an exception,if using this response handler   * @return an response object's string representation   * @throws IOException   * @throws ClientProtocolException   */   public String doExecuteRequest(HttpMethod httpMethod, URI uri,   ResponseHandler responseHandler)   throws ClientProtocolException, IOException {   return httpClient.execute(createHttpUriRequest(httpMethod, uri), responseHandler);   }   public InputStream doExecuteRequest(HttpMethod httpMethod, URI uri)   throws ClientProtocolException, IOException {   //1.   HttpUriRequest httpUriRequest = createHttpUriRequest(httpMethod, uri);   //2.   HttpResponse response = httpClient.execute(httpUriRequest);   //3.   validateResponse(response);   //4.   return getResponseBody(response);   }   /**   * Validate the given response, throwing an exception if it does not   * correspond to a successful HTTP response.   *   * Default implementation rejects any HTTP status code beyond 2xx, to avoid   * parsing the response body and trying to deserialize from a corrupted   * stream.   *   * @param config the HTTP invoker configuration that specifies the target   * service   * @param response the resulting HttpResponse to validate   * @throws NoHttpResponseException   * @throws java.io.IOException if validation failed   */   protected void validateResponse(HttpResponse response) throws IOException {   StatusLine status = response.getStatusLine();   if (status.getStatusCode() >= 300) {   throw new NoHttpResponseException(   "Did not receive successful HTTP response: status code = "   + status.getStatusCode() + ", status message = ["   + status.getReasonPhrase() + "]");   }   }   /**   * Extract the response body   *   * The default implementation simply fetches the response body stream. If   * the response is recognized as GZIP response, the InputStream will get   * wrapped in a GZIPInputStream.   *   * @param httpResponse the resulting HttpResponse to read the response body   * from   * @return an InputStream for the response body   * @throws java.io.IOException if thrown by I/O methods   * @see #isGzipResponse   * @see java.util.zip.GZIPInputStream   */   protected InputStream getResponseBody(HttpResponse httpResponse) throws IOException {   if (isGzipResponse(httpResponse)) {   return new GZIPInputStream(httpResponse.getEntity().getContent());   } else {   return httpResponse.getEntity().getContent();   }
  }   /**   * Determine whether the given response indicates a GZIP response.   *   * The default implementation checks whether the HTTP "Content-Encoding"   * header contains "gzip" (in any casing).   *   * @param httpResponse the resulting HttpResponse to check   * @return whether the given response indicates a GZIP response   */   protected boolean isGzipResponse(HttpResponse httpResponse) {   Header encodingHeader = httpResponse.getFirstHeader(HTTP_HEADER_CONTENT_ENCODING);   return (encodingHeader != null && encodingHeader.getValue() != null && encodingHeader   .getValue().toLowerCase().contains(ENCODING_GZIP));   }   /**   * Shutdown hook that closes the underlying   *{@link }org.apache.http.conn.ClientConnectionManager   * ClientConnectionManager}'s connection pool, if any.   */   public void destroy() {   getHttpClient().getConnectionManager().shutdown();   }   enum HttpMethod {   GET,   POST,   HEAD,   OPTIONS,   PUT,   DELETE,   TRACE   }   }   下面是久经考验的httpClient 3的二次封装,如下:   [java] view plaincopyprint?   /**   * @author von gosling 2011-12-12   */   public class HttpClientUtils {   private static final Logger log = LoggerFactory   .getLogger(HttpClientUtils.class);   private static int timeOut = 100;   private static int retryCount = 1;   private static int connectionTimeout = 100;   private static int maxHostConnections = 32; //根据apache work MPM设置此值   private static int maxTotalConnections = 512; //同上   private static String charsetName = "UTF-8";   public static JSONObject executeMethod(HttpClient httpClient, HttpMethod method) {   JSONObject result = new JSONObject();   StopWatch watch = new StopWatch();   int status = -1;   try {   log.info("Execute method({}) begin…", method.getURI());   watch.start();   status = httpClient.executeMethod(method);   watch.stop();   if (status == HttpStatus.SC_OK) {   InputStream inputStream = method.getResponseBodyAsStream();   ByteArrayOutputStream baos = new ByteArrayOutputStream();   IOUtils.copy(inputStream, baos);   String response = new String(baos.toByteArray(), charsetName);   log.info("Response is:{}", response);   result = JSONObject.parseObject(response);   } else {   log.error("Http request failure! status is {}", status);   }   } catch (SocketTimeoutException e) {   log.error("Request time out!");//只关注请求超时,对于其它两类超时,使用通用异常捕获   } catch (Exception e) {   log.error("Error occur!", e);   } finally {   method.releaseConnection();   log.info("Method {},statusCode {},consuming {} ms", new Object[] { method.getName(),   status, watch.getTime() });   }   return result;   }   /**   * @param uri   * @param nameValuePairs   * @return   */   public static PostMethod createPostMethod(String uri, NameValuePair[] nameValuePairs) {   PostMethod method = new PostMethod(uri);   method.addParameters(nameValuePairs);   method.getParams().setContentCharset(charsetName);   return method;   }   /**   * @param uri   * @param nameValuePairs   * @return   */   public static GetMethod createGetMethod(String uri, NameValuePair[] nameValuePairs) {   GetMethod method = new GetMethod(uri);   List list = Lists.newArrayList();   if (nameValuePairs != null) {   Collections.addAll(list, nameValuePairs);   method.setQueryString(list.toArray(new NameValuePair[nameValuePairs.length]));   }   method.getParams().setContentCharset(charsetName);   return method;   }   public static HttpClient createHttpClient() {   //1.   HttpClient httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());   //2.   HttpConnectionManagerParams httpConnectionManagerParams = httpClient
  .getHttpConnectionManager().getParams();   httpConnectionManagerParams.setConnectionTimeout(connectionTimeout);   httpConnectionManagerParams.setTcpNoDelay(true);//Nagle's algorithm   httpConnectionManagerParams.setSoTimeout(timeOut);   httpConnectionManagerParams.setDefaultMaxConnectionsPerHost(maxHostConnections);   httpConnectionManagerParams.setMaxTotalConnections(maxTotalConnections);   //3.   HttpClientParams httpClientParam = httpClient.getParams();   //httpClientParam.setConnectionManagerTimeout(connectionTimeout);//暂且不关注这个超时设置,后面根据性能酌情考虑   httpClientParam.setParameter(HttpMethodParams.RETRY_HANDLER,   new DefaultHttpMethodRetryHandler(retryCount, false));   httpClientParam.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);   return httpClient;   }   public static JSONObject doGet(String url, NameValuePair[] params) {   return executeMethod(createHttpClient(), createGetMethod(url, params));   }   public static JSONObject doPost(String url, NameValuePair[] params) {   return executeMethod(createHttpClient(), createPostMethod(url, params));   }   protected HttpClientUtils() {   }   public void setTimeOut(int timeOut) {   HttpClientUtils.timeOut = timeOut;   }   public static int getTimeOut() {   return timeOut;   }   public static int getRetryCount() {   return retryCount;   }   public void setRetryCount(int retryCount) {   HttpClientUtils.retryCount = retryCount;   }   public static int getConnectionTimeout() {   return connectionTimeout;   }   public void setConnectionTimeout(int connectionTimeout) {   HttpClientUtils.connectionTimeout = connectionTimeout;   }   public static int getMaxHostConnections() {   return maxHostConnections;   }   public void setMaxHostConnections(int maxHostConnections) {   HttpClientUtils.maxHostConnections = maxHostConnections;   }   public static int getMaxTotalConnections() {   return maxTotalConnections;   }   public void setMaxTotalConnections(int maxTotalConnections) {   HttpClientUtils.maxTotalConnections = maxTotalConnections;   }   public static String getCharsetName() {   return charsetName;   }   public void setCharsetName(String charsetName) {   HttpClientUtils.charsetName = charsetName;   }   }   /**   * @author von gosling 2011-12-12   */   public class HttpClientUtils {   private static final Logger log = LoggerFactory   .getLogger(HttpClientUtils.class);   private static int timeOut = 100;   private static int retryCount = 1;   private static int connectionTimeout = 100;   private static int maxHostConnections = 32; //根据apache work MPM设置此值   private static int maxTotalConnections = 512; //同上   private static String charsetName = "UTF-8";   public static JSONObject executeMethod(HttpClient httpClient, HttpMethod method) {   JSONObject result = new JSONObject();   StopWatch watch = new StopWatch();   int status = -1;   try {   log.info("Execute method({}) begin…", method.getURI());   watch.start();   status = httpClient.executeMethod(method);   watch.stop();   if (status == HttpStatus.SC_OK) {   InputStream inputStream = method.getResponseBodyAsStream();   ByteArrayOutputStream baos = new ByteArrayOutputStream();   IOUtils.copy(inputStream, baos);   String response = new String(baos.toByteArray(), charsetName);   log.info("Response is:{}", response);   result = JSONObject.parseObject(response);   } else {   log.error("Http request failure! status is {}", status);   }   } catch (SocketTimeoutException e) {   log.error("Request time out!");//只关注请求超时,对于其它两类超时,使用通用异常捕获   } catch (Exception e) {   log.error("Error occur!", e);   } finally {   method.releaseConnection();   log.info("Method {},statusCode {},consuming {} ms", new Object[] { method.getName(),   status, watch.getTime() });   }
  return result;   }   /**   * @param uri   * @param nameValuePairs   * @return   */   public static PostMethod createPostMethod(String uri, NameValuePair[] nameValuePairs) {   PostMethod method = new PostMethod(uri);   method.addParameters(nameValuePairs);   method.getParams().setContentCharset(charsetName);   return method;   }   /**   * @param uri   * @param nameValuePairs   * @return   */   public static GetMethod createGetMethod(String uri, NameValuePair[] nameValuePairs) {   GetMethod method = new GetMethod(uri);   List list = Lists.newArrayList();   if (nameValuePairs != null) {   Collections.addAll(list, nameValuePairs);   method.setQueryString(list.toArray(new NameValuePair[nameValuePairs.length]));   }   method.getParams().setContentCharset(charsetName);   return method;   }   public static HttpClient createHttpClient() {   //1.   HttpClient httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());   //2.   HttpConnectionManagerParams httpConnectionManagerParams = httpClient   .getHttpConnectionManager().getParams();   httpConnectionManagerParams.setConnectionTimeout(connectionTimeout);   httpConnectionManagerParams.setTcpNoDelay(true);//Nagle's algorithm   httpConnectionManagerParams.setSoTimeout(timeOut);   httpConnectionManagerParams.setDefaultMaxConnectionsPerHost(maxHostConnections);   httpConnectionManagerParams.setMaxTotalConnections(maxTotalConnections);   //3.   HttpClientParams httpClientParam = httpClient.getParams();   //httpClientParam.setConnectionManagerTimeout(connectionTimeout);//暂且不关注这个超时设置,后面根据性能酌情考虑   httpClientParam.setParameter(HttpMethodParams.RETRY_HANDLER,   new DefaultHttpMethodRetryHandler(retryCount, false));   httpClientParam.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);   return httpClient;   }   public static JSONObject doGet(String url, NameValuePair[] params) {   return executeMethod(createHttpClient(), createGetMethod(url, params));   }   public static JSONObject doPost(String url, NameValuePair[] params) {   return executeMethod(createHttpClient(), createPostMethod(url, params));   }   protected HttpClientUtils() {   }   public void setTimeOut(int timeOut) {   HttpClientUtils.timeOut = timeOut;   }   public static int getTimeOut() {   return timeOut;   }   public static int getRetryCount() {   return retryCount;   }   public void setRetryCount(int retryCount) {   HttpClientUtils.retryCount = retryCount;   }   public static int getConnectionTimeout() {   return connectionTimeout;   }   public void setConnectionTimeout(int connectionTimeout) {   HttpClientUtils.connectionTimeout = connectionTimeout;   }   public static int getMaxHostConnections() {   return maxHostConnections;   }   public void setMaxHostConnections(int maxHostConnections) {   HttpClientUtils.maxHostConnections = maxHostConnections;   }   public static int getMaxTotalConnections() {   return maxTotalConnections;   }   public void setMaxTotalConnections(int maxTotalConnections) {   HttpClientUtils.maxTotalConnections = maxTotalConnections;   }   public static String getCharsetName() {   return charsetName;   }   public void setCharsetName(String charsetName) {   HttpClientUtils.charsetName = charsetName;   }   }   好了,有了活生生的代码,我们来总结一下httpClient封装过程中需要注意的一些事项吧。恩,其实更多的是体现在安全,性能上面:   (1)多线程模型,尤其注意finally中collection的释放问题。除此之外,需要考虑池化连接的异常处理,这是我文中提到特别注意的三大异常之一;   (2)Retry机制中对幂等性的处理。尤其是在httpClient4中,put和post操作,未按照http规范行事,需要我们额外注意;   (3)SSL、TLS的定制化处理;   (4)并发标记的处理,这里使用了Concurrency in practice中的并发annotation,有什么用?感兴趣的朋友可以了解下SureLogic,别问我要license,因为俺也不是apache开源社区的developer呀;   (5)拦截器对header的处理;   (6)collection stale check机制;   (7)Cookie specification choose或者是自定义实现;    

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小熊分享邦(www.xxfxb.com),希望大家能坚持软件测试之路,谢谢。

赞(0) 打赏
未经允许不得转载:小熊分享邦 » HttpComponents组件特性探究| 小熊测试

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏