实际使用client的过程中,会遇到一种情况,如cookie的Key为空的,此时默认的cookie的策略处理cookie是会报错。
这时咱可以通过重写cookiestore策略来解决如:
/** * @description 自定义Cookie策略 * * @title setCustomCookieSpec * @param builder * @return void */ private static void setCustomCookieSpec(HttpClientBuilder builder) { CookieSpecProvider easySpecProvider = new CookieSpecProvider() { public org.apache.http.cookie.CookieSpec create(HttpContext context) { return new BrowserCompatSpec() { public void validate(Cookie cookie, CookieOrigin origin) throws MalformedCookieException { } protected List<Cookie> parse(final HeaderElement[] elems, final CookieOrigin origin) throws MalformedCookieException { final List<Cookie> cookies = new ArrayList<Cookie>( elems.length); for (final HeaderElement headerelement : elems) { final String name = headerelement.getName(); final String value = headerelement.getValue(); if (value == null) { continue; } if (name == null || name.length() == 0) { throw new MalformedCookieException( "Cookie name may not be empty"); } final BasicClientCookie cookie = new BasicClientCookie( name, value); cookie.setPath(getDefaultPath(origin)); cookie.setDomain(getDefaultDomain(origin)); // cycle through the parameters final NameValuePair[] attribs = headerelement .getParameters(); for (int j = attribs.length - 1; j >= 0; j--) { final NameValuePair attrib = attribs[j]; final String s = attrib.getName().toLowerCase( Locale.ENGLISH); cookie.setAttribute(s, attrib.getValue()); final CookieAttributeHandler handler = findAttribHandler(s); if (handler != null) { handler.parse(cookie, attrib.getValue()); } } cookies.add(cookie); } return cookies; } }; } }; Registry<CookieSpecProvider> r = RegistryBuilder .<CookieSpecProvider> create() .register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory()) .register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory()) .register("easy", easySpecProvider).build(); builder.setDefaultCookieSpecRegistry(r); }
最后上个完整的代码:
package com.lkb.manager.httpclient; import java.io.IOException; import java.io.InterruptedIOException; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import java.util.Locale; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import org.apache.http.HeaderElement; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.config.CookieSpecs; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContextBuilder; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieAttributeHandler; import org.apache.http.cookie.CookieOrigin; import org.apache.http.cookie.CookieSpecProvider; import org.apache.http.cookie.MalformedCookieException; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.impl.cookie.BestMatchSpecFactory; import org.apache.http.impl.cookie.BrowserCompatSpec; import org.apache.http.impl.cookie.BrowserCompatSpecFactory; import org.apache.http.protocol.HttpContext; import com.lkb.manager.util.LogUtil; import com.lkb.manager.util.SpiderUtil; public class HttpClientUtil { /** * @Fields CURRENT_HTTP_CLIENT_CONTEXT : httpclient 上下文 */ private static final String HTTP_CLIENT_CONTEXT = "HttpClientUtil.HtppClientContext"; /** * @Fields CURRENT_HTTP_CLIENT : httpclient */ public static final String HTTP_CLIENT = "HttpClientUtil.HttpClient"; public static CloseableHttpClient HttpClient(){ CloseableHttpClient client = (CloseableHttpClient)SpiderUtil.getSessions().get(HTTP_CLIENT); if(client==null){ client = HttpClientUtil.getHttpClient(); SpiderUtil.getSessions().put(HTTP_CLIENT, client); } return client; } public static HttpClientContext HttpClientContext(){ HttpClientContext context = (HttpClientContext)SpiderUtil.getSessions().get(HTTP_CLIENT_CONTEXT); if(context==null){ context = HttpClientContext.create(); SpiderUtil.getSessions().put(HTTP_CLIENT_CONTEXT, context); } return context; } public static CloseableHttpClient getHttpClient(){ CloseableHttpClient client = null; for (int i = 0; i < 2; i++) { try{ HttpClientBuilder builder = createSSLClientDefault(); setCustomCookieSpec(builder);//cookie 策略 setExecutionCount(builder); setKeepAliveDuration(builder); client = builder.build(); }catch(Exception e){ e.printStackTrace(); } if(client!=null){ return client; } } LogUtil.error(null,"HttpClient初始化失败!"); return null; } /** * https通用策略 * @Title: createSSLClientDefault * @return HttpClientBuilder 返回类型 * @throws */ private static HttpClientBuilder createSSLClientDefault(){ try { SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { //信任所有 public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; } }).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext); return HttpClients.custom().setSSLSocketFactory(sslsf); } catch (KeyManagementException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } return null; } /** * @description 自定义Cookie策略 * * @title setCustomCookieSpec * @param builder * @return void */ private static void setCustomCookieSpec(HttpClientBuilder builder) { CookieSpecProvider easySpecProvider = new CookieSpecProvider() { public org.apache.http.cookie.CookieSpec create(HttpContext context) { return new BrowserCompatSpec() { public void validate(Cookie cookie, CookieOrigin origin) throws MalformedCookieException { } protected List<Cookie> parse(final HeaderElement[] elems, final CookieOrigin origin) throws MalformedCookieException { final List<Cookie> cookies = new ArrayList<Cookie>( elems.length); for (final HeaderElement headerelement : elems) { final String name = headerelement.getName(); final String value = headerelement.getValue(); if (value == null) { continue; } if (name == null || name.length() == 0) { throw new MalformedCookieException( "Cookie name may not be empty"); } final BasicClientCookie cookie = new BasicClientCookie( name, value); cookie.setPath(getDefaultPath(origin)); cookie.setDomain(getDefaultDomain(origin)); // cycle through the parameters final NameValuePair[] attribs = headerelement .getParameters(); for (int j = attribs.length - 1; j >= 0; j--) { final NameValuePair attrib = attribs[j]; final String s = attrib.getName().toLowerCase( Locale.ENGLISH); cookie.setAttribute(s, attrib.getValue()); final CookieAttributeHandler handler = findAttribHandler(s); if (handler != null) { handler.parse(cookie, attrib.getValue()); } } cookies.add(cookie); } return cookies; } }; } }; Registry<CookieSpecProvider> r = RegistryBuilder .<CookieSpecProvider> create() .register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory()) .register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory()) .register("easy", easySpecProvider).build(); builder.setDefaultCookieSpecRegistry(r); } /** * 默认请求次数 * @param builder */ private static void setExecutionCount(HttpClientBuilder builder){ HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() { public boolean retryRequest( IOException exception, int executionCount, HttpContext context) { if (executionCount >= 4) { // 如果已经重试了5次,就放弃 return false; } if (exception instanceof InterruptedIOException) { // 超时 return false; } if (exception instanceof UnknownHostException) { // 目标服务器不可达 return false; } if (exception instanceof ConnectTimeoutException) { // 连接被拒绝 return false; } if (exception instanceof SSLException) { // ssl握手异常 return false; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) { // 如果请求是幂等的,就再次尝试 return true; } return false; } }; builder.setRetryHandler(myRetryHandler); } /**关闭连接*/ public static void colse(){ try { CloseableHttpClient c = (CloseableHttpClient) SpiderUtil.getSessions().get(HttpClientUtil.HTTP_CLIENT); if(c!=null){ c.close(); } } catch (IOException e) { LogUtil.error(e,"HttpClient关闭失败"); } } private static void setKeepAliveDuration(HttpClientBuilder builder){ ConnectionKeepAliveStrategy keepAliveStrat = new DefaultConnectionKeepAliveStrategy() { @Override public long getKeepAliveDuration( HttpResponse response, HttpContext context) { long keepAlive = super.getKeepAliveDuration(response, context); if (keepAlive == -1) { //如果服务器没有设置keep-alive这个参数,我们就把它设置成5秒 keepAlive = 4000; } return keepAlive; } }; //定制我们自己的httpclient builder.setKeepAliveStrategy(keepAliveStrat); } }