4.HttpClient 를 사용 하여 사 이 트 를 방문 하고 같은 사이트 의 방문 에 대해 긴 연결 을 유지 하 며 방문 재 활용 을 실현 합 니 다.
44144 단어 SpringBoot소공 구
저희 가 HttpClient 를 사용 하여 한 사 이 트 를 방문 할 때 일반적인 방법 은 연결,방문,연결 을 끊 는 것 입 니 다.만약 에 저희 의 방 문 량 이 매우 많 으 면 상기 절 차 를 수 차례 반복 하지 않 습 니 다.그러나 같은 사이트 의 방문 에 대해 우 리 는 연결 을 계속 열 고 지난번 의 연결 을 계속 사용 할 수 있다.왜냐하면 연결 을 끊 고 다시 연결 하 는 것 은 자원 을 소모 하 는 데 상당 한 시간 이 걸린다.
2.해결 방향
처음에 제 생각 은 차단 대기 열 을 통 해 만 든 HttpClient 인 스 턴 스 를 대기 열 에 넣 어서 하나의 풀 을 만 드 는 것 이 었 습 니 다.방문 이 끝 날 때마다 HttpClient 인 스 턴 스 를 닫 지 않 고 풀 로 되 돌려 주 는 것 이 었 습 니 다. 그러나 이렇게 하면 HttpClient 인 스 턴 스 의 재 활용 만 이 루어 졌 을 뿐 처음부터 문 제 를 해결 하지 못 했 습 니 다.재 방문 은 다시 연결 해 야 합 니 다.『8195』나중에 자 료 를 조회 한 결과 다음 과 같은 해결 방법 을 발견 했다.구체 적 인 코드 는 다음 과 같다.
package com.yuedu.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.*;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.*;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.UnsupportedEncodingException;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
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.Map;
/**
* HttpClient
* @author
* @date 2019-03-18 17:12
*/
@Slf4j
public class HttpClientUtil {
/**
*
*/
private static final int TIMEOUT = 30 * 1000;
/**
*
*/
private static final int MAX_TOTAL = 200;
/**
*
*/
private static final int MAX_PER_ROUTE = 40;
/**
*
*/
private static final int MAX_ROUTE = 100;
/**
*
*/
private static final int MAX_RETRY_TIME = 5;
private static CloseableHttpClient httpClient = null;
private static final Object SYNC_LOCK = new Object();
private static final String DEFAULT_CHARSET = "UTF-8";
private static void config(HttpRequestBase httpRequestBase) {
//
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
.setConnectTimeout(TIMEOUT)
.setSocketTimeout(TIMEOUT)
.build();
httpRequestBase.setConfig(requestConfig);
}
/**
* HttpClient
*/
private static CloseableHttpClient getHttpClient(String url) throws NoSuchAlgorithmException, KeyManagementException {
String hostName = url.split("/")[2];
int port = 80;
if (hostName.contains(":")) {
String[] attr = hostName.split(":");
hostName = attr[0];
port = Integer.parseInt(attr[1]);
}
if (httpClient == null) {
synchronized (SYNC_LOCK) {
if (httpClient == null) {
httpClient = createHttpClient(MAX_TOTAL, MAX_PER_ROUTE, MAX_ROUTE, hostName, port);
}
}
}
return httpClient;
}
/**
* HttpClient
*/
private static CloseableHttpClient createHttpClient(int maxTotal, int maxPerRoute, int maxRoute,
String hostName, int port) throws KeyManagementException, NoSuchAlgorithmException {
PlainConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(createIgnoreVerifySSL());
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", plainsf)
.register("https", sslsf)
.build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
//
cm.setMaxTotal(maxTotal);
//
cm.setDefaultMaxPerRoute(maxPerRoute);
//
cm.setMaxPerRoute(new HttpRoute(new HttpHost(hostName, port)), maxRoute);
//
HttpRequestRetryHandler httpRequestRetryHandler = (exception, executionCount, context) -> {
// 5 ,
if (executionCount >= MAX_RETRY_TIME) {
return false;
}
// ,
if (exception instanceof NoHttpResponseException) {
return true;
}
// SSL
if (exception instanceof SSLHandshakeException) {
return false;
}
//
if (exception instanceof InterruptedIOException) {
return false;
}
//
if (exception instanceof UnknownHostException) {
return false;
}
//SSL
if (exception instanceof SSLException) {
return false;
}
HttpClientContext clientContext = HttpClientContext.adapt(context);
HttpRequest request = clientContext.getRequest();
// ,
return !(request instanceof HttpEntityEnclosingRequest);
};
return HttpClients.custom().setConnectionManager(cm)
.setRetryHandler(httpRequestRetryHandler)
.build();
}
/**
* HttpClient SSL https ( https , https , ,
* , ), https
*/
private static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
SSLContext sslContext = SSLContext.getInstance("SSLv3");
// X509TrustManager , ,
X509TrustManager trustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
sslContext.init(null, new TrustManager[] {trustManager}, null);
return sslContext;
}
private static void setPostParams(HttpPost httpPost, Map<String, Object> params) {
List<NameValuePair> nameValuePairs = new ArrayList<>();
params.forEach((key, value) -> nameValuePairs.add(new BasicNameValuePair(key, value.toString())));
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_CHARSET));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* post , UTF-8
* @param url
* @param params
* @return
*/
public static String doPost(String url, Map<String, Object> params) {
return doPost(url, params, DEFAULT_CHARSET);
}
/**
* post
* @param url
* @param params
* @param charset
* @return
*/
public static String doPost(String url, Map<String, Object> params, String charset) {
HttpPost httpPost = new HttpPost(url);
config(httpPost);
setPostParams(httpPost, params);
return getResponse(url, httpPost, charset);
}
/**
* get , UTF-8
* @param url
* @return
*/
public static String doGet(String url) {
return doGet(url, DEFAULT_CHARSET);
}
/**
* get
* @param url
* @param charset
* @return
*/
public static String doGet(String url, String charset) {
HttpGet httpGet = new HttpGet(url);
config(httpGet);
return getResponse(url, httpGet, charset);
}
/**
* ,
* @param url
* @param httpRequest
* @param charset
* @return
*/
private static String getResponse(String url, HttpRequestBase httpRequest, String charset) {
CloseableHttpResponse response = null;
try {
response = getHttpClient(url).execute(httpRequest, HttpClientContext.create());
HttpEntity httpEntity = response.getEntity();
String result = EntityUtils.toString(httpEntity, charset);
EntityUtils.consume(httpEntity);
return result;
} catch (IOException | NoSuchAlgorithmException | KeyManagementException e) {
log.error(" !", e);
} finally {
try {
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Java・SpringBoot・Thymeleaf】 에러 메세지를 구현(SpringBoot 어플리케이션 실천편 3)로그인하여 사용자 목록을 표시하는 응용 프로그램을 만들고, Spring에서의 개발에 대해 공부하겠습니다 🌟 마지막 데이터 바인딩에 계속 바인딩 실패 시 오류 메시지를 구현합니다. 마지막 기사🌟 src/main/res...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.