Created
February 13, 2014 05:44
-
-
Save vongosling/8970351 to your computer and use it in GitHub Desktop.
Best practice - Httpclient 4.1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 史上最棒的HttpClient4封装,details please see | |
* http://hc.apache.org/httpcomponents-client-ga/tutorial/html/index.html | |
* | |
* @author von gosling 2013-5-7 | |
*/ | |
public class HttpClientManager { | |
//Consider ulimit | |
private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 7500; | |
//notice IE 6,7,8 | |
private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 200; | |
private static final int DEFAULT_CONN_TIMEOUT_MILLISECONDS = 5 * 1000; | |
private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = 60 * 1000; | |
private static final int INIT_DELAY = 5 * 1000; | |
private static final int CHECK_INTERVAL = 5 * 60 * 1000; | |
private static String HTTP_REQUEST_ENCODING = "UTF-8"; | |
private static String LINE_SEPARATOR = "\r\n"; | |
private static final Logger LOG = LoggerFactory | |
.getLogger(HttpClientManager.class); | |
private static ThreadSafeClientConnManager connectionManager; | |
static { | |
SchemeRegistry schemeRegistry = new SchemeRegistry(); | |
schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory())); | |
//schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory())); | |
connectionManager = new ThreadSafeClientConnManager(schemeRegistry); | |
connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS); | |
connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE); | |
//Connection eviction | |
ScheduledExecutorService scheduledExeService = Executors.newScheduledThreadPool(1, | |
new DaemonThreadFactory("Http-client-ConenctionPool-Monitor")); | |
scheduledExeService.scheduleAtFixedRate(new IdleConnectionMonitor(connectionManager), | |
INIT_DELAY, CHECK_INTERVAL, TimeUnit.MILLISECONDS); | |
} | |
public static String doPost(String reqURL, Map<String, String> params, String encoding, | |
Boolean enableSSL) { | |
HttpClient httpClient = getHttpClient(enableSSL); | |
String responseContent = ""; | |
try { | |
HttpPost httpPost = buildHttpPostRequest(reqURL, params, encoding); | |
HttpResponse response = httpClient.execute(httpPost); | |
// validateResponse(response, httpPost); | |
HttpEntity entity = response.getEntity(); | |
if (entity != null) { | |
// responseLength = entity.getContentLength(); | |
responseContent = EntityUtils.toString(entity, encoding); | |
//Ensure that the entity content has been fully consumed and the underlying stream has been closed. | |
EntityUtils.consume(entity); | |
} else { | |
LOG.warn("Http entity is null! request url is {},response status is {}", reqURL, | |
response.getStatusLine()); | |
} | |
} catch (ConnectTimeoutException e) { | |
LOG.warn(e.getMessage()); | |
} catch (SocketTimeoutException e) { | |
LOG.warn("Read time out!"); | |
} catch (SSLPeerUnverifiedException e) { | |
LOG.warn("Peer not authenticated!"); | |
} catch (Exception e) { | |
LOG.error(e.getMessage(), e); | |
} | |
return responseContent; | |
} | |
public static String doPost(String reqURL, final String entities, String encoding) { | |
HttpClient httpClient = getHttpClient(false); | |
String responseContent = ""; | |
try { | |
AbstractHttpEntity printWriterEntity = new AbstractHttpEntity() { | |
public boolean isRepeatable() { | |
return false; | |
} | |
public long getContentLength() { | |
return -1; | |
} | |
public boolean isStreaming() { | |
return false; | |
} | |
public InputStream getContent() throws IOException { | |
// Should be implemented as well but is irrelevant for this case | |
throw new UnsupportedOperationException(); | |
} | |
public void writeTo(final OutputStream outstream) throws IOException { | |
PrintWriter writer = new PrintWriter(new OutputStreamWriter(outstream, | |
HTTP_REQUEST_ENCODING)); | |
writer.print(entities); | |
writer.print(LINE_SEPARATOR); | |
writer.flush(); | |
} | |
}; | |
HttpPost httpPost = new HttpPost(reqURL); | |
//If the data is large enough that you need to stream it, | |
//you can write to a temp file and use FileEntity or possibly set up a pipe and use InputStreamEntity | |
httpPost.setEntity(printWriterEntity); | |
HttpResponse response = httpClient.execute(httpPost); | |
validateResponse(response, httpPost); | |
HttpEntity entity = response.getEntity(); | |
if (entity != null) { | |
responseContent = EntityUtils.toString(entity, encoding); | |
//Ensure that the entity content has been fully consumed and the underlying stream has been closed. | |
EntityUtils.consume(entity); | |
} else { | |
LOG.warn("Http entity is null! request url is {},response status is {}", reqURL, | |
response.getStatusLine()); | |
} | |
} catch (SocketTimeoutException e) { | |
LOG.warn("Read time out!"); | |
} catch (SSLPeerUnverifiedException e) { | |
LOG.warn("Peer not authenticated!"); | |
} catch (Exception e) { | |
LOG.error(e.getMessage(), e); | |
} | |
return responseContent; | |
} | |
private static X509TrustManager customTrustManager(HttpClient httpClient) { | |
//Trusting all certificates | |
X509TrustManager xtm = new X509TrustManager() { | |
public void checkClientTrusted(X509Certificate[] chain, String authType) | |
throws CertificateException { | |
} | |
public void checkServerTrusted(X509Certificate[] chain, String authType) | |
throws CertificateException { | |
} | |
public X509Certificate[] getAcceptedIssuers() { | |
return null; | |
} | |
}; | |
try { | |
SSLContext ctx = SSLContext.getInstance("TLS"); | |
if (null != ctx) { | |
ctx.init(null, new TrustManager[] { xtm }, null); | |
SSLSocketFactory socketFactory = new SSLSocketFactory(ctx, | |
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); | |
httpClient.getConnectionManager().getSchemeRegistry() | |
.register(new Scheme("https", 443, socketFactory)); | |
} | |
} catch (Exception e) { | |
LOG.error(e.getMessage()); | |
} | |
return xtm; | |
} | |
private static HttpClient getHttpClient(Boolean enableSSL) { | |
DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager); | |
httpClient.setRedirectStrategy(new RedirectStrategy() { //设置重定向处理方式为自行处理 | |
@Override | |
public boolean isRedirected(HttpRequest request, HttpResponse response, | |
HttpContext context) throws ProtocolException { | |
return false; | |
} | |
@Override | |
public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, | |
HttpContext context) throws ProtocolException { | |
return null; | |
} | |
}); | |
httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, | |
DEFAULT_READ_TIMEOUT_MILLISECONDS); | |
httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, | |
DEFAULT_CONN_TIMEOUT_MILLISECONDS); | |
//According to http use-case to decide to whether to open TCP_NODELAY option,So does SO_LINGER option | |
httpClient.getParams().setParameter(CoreConnectionPNames.TCP_NODELAY, Boolean.TRUE); | |
httpClient.getParams().setParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, | |
Boolean.FALSE); | |
if (enableSSL) { | |
customTrustManager(httpClient); | |
} | |
return httpClient; | |
} | |
public static Map.Entry<Integer, String> doGetHttpResponse(String url, String encoding) { | |
HttpClient httpClient = getHttpClient(false); | |
HttpGet httpget = new HttpGet(url); | |
try { | |
EncodingResponseHandler responseHandler = new EncodingResponseHandler(); | |
if (StringUtils.isBlank(encoding)) { | |
encoding = HTTP_REQUEST_ENCODING; | |
} | |
responseHandler.setEncoding(encoding); | |
return httpClient.execute(httpget, responseHandler); | |
} catch (Exception e) { | |
LOG.error(e.getMessage(), e); | |
} | |
return null; | |
} | |
public static String doGet(String url, String encoding) { | |
Map.Entry<Integer, String> ret = doGetHttpResponse(url, encoding); | |
if (ret == null) { | |
return ""; | |
} | |
if (ret.getKey() != HttpStatus.SC_OK) { | |
LOG.error( | |
"Did not receive successful HTTP response: status code = {}, request url = {}", | |
ret.getKey(), url); | |
} | |
return ret.getValue(); | |
} | |
public static void doPost(String url, Map<String, String> params) { | |
HttpClient httpClient = getHttpClient(false); | |
try { | |
HttpPost httpPost = buildHttpPostRequest(url, params, HTTP.UTF_8); | |
ResponseHandler<byte[]> handler = new ResponseHandler<byte[]>() { | |
public byte[] handleResponse(HttpResponse response) throws ClientProtocolException, | |
IOException { | |
HttpEntity entity = response.getEntity(); | |
if (entity != null) { | |
return EntityUtils.toByteArray(entity); | |
} else { | |
return null; | |
} | |
} | |
}; | |
httpClient.execute(httpPost, handler); | |
} catch (Exception e) { | |
LOG.error(e.getMessage(), e); | |
} | |
} | |
private static HttpPost buildHttpPostRequest(String url, Map<String, String> params, | |
String encoding) | |
throws UnsupportedEncodingException { | |
HttpPost httpPost = new HttpPost(url); | |
//Encode the form parameters | |
if (!CollectionUtils.isEmpty(params)) { | |
List<NameValuePair> nvps = Lists.newArrayList(); | |
Set<Entry<String, String>> paramEntrys = params.entrySet(); | |
for (Entry<String, String> entry : paramEntrys) { | |
nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); | |
} | |
httpPost.setEntity(new UrlEncodedFormEntity(nvps, encoding)); | |
} | |
return httpPost; | |
} | |
// private static void validateResponse(HttpResponse response, HttpGet get) throws IOException { | |
// StatusLine status = response.getStatusLine(); | |
// if (status.getStatusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { | |
// LOG.warn( | |
// "Did not receive successful HTTP response: status code = {}, status message = {}", | |
// status.getStatusCode(), status.getReasonPhrase()); | |
// get.abort(); | |
// return; | |
// } | |
// } | |
private static void validateResponse(HttpResponse response, HttpPost post) throws IOException { | |
StatusLine status = response.getStatusLine(); | |
if (status.getStatusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { | |
LOG.warn( | |
"Did not receive successful HTTP response: status code = {}, status message = {}", | |
status.getStatusCode(), status.getReasonPhrase()); | |
post.abort(); | |
return; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment