HttpClient — это подпроект Apache Jakarta Common, который используется для предоставления эффективного, современного и многофункционального набора инструментов клиентского программирования, поддерживающего протокол HTTP, а также последнюю версию и рекомендации протокола HTTP. Основная цель использования httpclient в фоновом режиме Java — имитация клиентских запросов.
Реализованы все типы запросов Http, и соответствующие классы: HttpGet, HttpPost, HttpDelete, HttpPut.
1) Пакет гидов
1<dependency>
2 <groupId>org.apache.httpcomponents</groupId>
3 <artifactId>httpclient</artifactId>
4 <version>4.5.5</version>
5</dependency>
6<dependency>
7 <groupId>org.apache.httpcomponents</groupId>
8 <artifactId>httpmime</artifactId>
9 <version>4.5</version>
10</dependency>
2) Информация о конфигурации, необходимая для создания соединения.
1public class HttpClientConfig {
2
3 static int httpConnectTimeout = 10000; //Тайм-аут соединения (единица измерения: миллисекунды)
4 static int httpSocketTimeout = 10000; //Тайм-аут чтения и записи сокета (единица измерения: миллисекунды)
5 static int httpMaxPoolSize = 100;
6 static int httpMonitorInterval = 3000;
7 static int httpIdelTimeout = 2000;
8
9 public static int getHttpIdelTimeout() {
10 return httpIdelTimeout;
11 }
12
13 public static int getHttpSocketTimeout() {
14 return httpSocketTimeout;
15 }
16
17 public static int getHttpMaxPoolSize() {
18 return httpMaxPoolSize;
19 }
20
21 public static int getHttpMonitorInterval() {
22 return httpMonitorInterval;
23 }
24
25 public static int getHttpConnectTimeout() {
26 return httpConnectTimeout;
27 }
28}
3) Инкапсулируйте класс HttpClientUtils, включая информацию о пуле соединений.
1public class HttpClientUtils {
2
3 private final static Logger logger = Logger.getLogger(HttpClientUtils.class);
4 private static CloseableHttpClient httpClient;
5 private static PoolingHttpClientConnectionManager manager; // Класс управления пулом соединений
6 private static ScheduledExecutorService monitorExecutor; // монитор
7 private final static Object syncLock = new Object(); // Эквивалент фиксатора резьбы, используется для безопасности резьбы.
8 private static final int CONNECT_TIMEOUT = HttpClientConfig.getHttpConnectTimeout();// Установите таймаут установления соединения на 10 с.
9 private static final int SOCKET_TIMEOUT = HttpClientConfig.getHttpSocketTimeout();
10 private static final int MAX_CONN = HttpClientConfig.getHttpMaxPoolSize(); // Максимальное количество подключений
11 private static final int Max_PRE_ROUTE = HttpClientConfig.getHttpMaxPoolSize();
12 private static final int MAX_ROUTE = HttpClientConfig.getHttpMaxPoolSize();
13
14 /**
15 * Выполните базовые настройки для http-запросов
16 *
17 * @param httpRequestBase
18 * HTTP-запрос
19 */
20 private static void setRequestConfig(HttpRequestBase httpRequestBase) {
21 RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT)
22 .setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
23 httpRequestBase.setConfig(requestConfig);
24 }
25
26 public static CloseableHttpClient getHttpClient(String url) {
27 String hostName = url.split("/")[2];
28 // System.out.println(hostName);
29 int port = 80;
30 if (hostName.contains(":")) {
31 String[] args = hostName.split(":");
32 hostName = args[0];
33 port = Integer.parseInt(args[1]);
34 }
35 if (httpClient == null) {
36 // Вызов getHttpClient несколькими потоками одновременно в условиях многопоточности может легко привести к проблеме многократного создания объектов httpClient, поэтому добавляется блокировка синхронизации.
37 synchronized (syncLock) {
38 if (httpClient == null) {
39 httpClient = createHttpClient(hostName, port);
40 // Начать ветку монитора,对异常和空闲нить进行关闭
41 monitorExecutor = Executors.newScheduledThreadPool(1);
42 monitorExecutor.scheduleAtFixedRate(new TimerTask() {
43 @Override
44 public void run() {
45 // Закрыть ненормальное соединение
46 manager.closeExpiredConnections();
47 // Закрытие соединений в режиме ожидания в течение 5 секунд
48 manager.closeIdleConnections(HttpClientConfig.getHttpIdelTimeout(), TimeUnit.MILLISECONDS);
49 logger.debug("close expired and idle for over 5s connection");
50 }
51 }, HttpClientConfig.getHttpMonitorInterval(), HttpClientConfig.getHttpMonitorInterval(),
52 TimeUnit.MILLISECONDS);
53 }
54 }
55 }
56 return httpClient;
57 }
58
59 /**
60 * Создайте экземпляр httpclient на основе хоста и порта.
61 *
62 * @param host
63 * доменное имя для доступа
64 * @param port
65 * Порт для доступа
66 * @return
67 */
68 public static CloseableHttpClient createHttpClient(String host, int port) {
69 ConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.getSocketFactory();
70 LayeredConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactory.getSocketFactory();
71 Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
72 .register("http", plainSocketFactory).register("https", sslSocketFactory).build();
73 manager = new PoolingHttpClientConnectionManager(registry);
74 // Установить параметры подключения
75 manager.setMaxTotal(MAX_CONN); // Максимальное количество подключений
76 manager.setDefaultMaxPerRoute(Max_PRE_ROUTE); // 路由Максимальное количество подключений
77 HttpHost httpHost = new HttpHost(host, port);
78 manager.setMaxPerRoute(new HttpRoute(httpHost), MAX_ROUTE);
79 // Если запрос не выполнен, повторите запрос
80 HttpRequestRetryHandler handler = new HttpRequestRetryHandler() {
81 @Override
82 public boolean retryRequest(IOException e, int i, HttpContext httpContext) {
83 if (i > 3) {
84 // Повторите попытку более 3 раз и откажитесь от запроса.
85 logger.error("retry has more than 3 time, give up request");
86 return false;
87 }
88 if (e instanceof NoHttpResponseException) {
89 // Сервер не отвечает. Возможно, сервер отключился, и следует повторить попытку.
90 logger.error("receive no response from server, retry");
91 return true;
92 }
93 if (e instanceof SSLHandshakeException) {
94 // Исключение SSL-подтверждения
95 logger.error("SSL hand shake exception");
96 return false;
97 }
98 if (e instanceof InterruptedIOException) {
99 // тайм-аут
100 logger.error("InterruptedIOException");
101 return false;
102 }
103 if (e instanceof UnknownHostException) {
104 // Сервер недоступен
105 logger.error("server host unknown");
106 return false;
107 }
108 if (e instanceof ConnectTimeoutException) {
109 // соединятьтайм-аут
110 logger.error("Connection Time out");
111 return false;
112 }
113 if (e instanceof SSLException) {
114 logger.error("SSLException");
115 return false;
116 }
117 HttpClientContext context = HttpClientContext.adapt(httpContext);
118 HttpRequest request = context.getRequest();
119 if (!(request instanceof HttpEntityEnclosingRequest)) {
120 // Если запрос не требует закрытия соединения
121 return true;
122 }
123 return false;
124 }
125 };
126 CloseableHttpClient client = HttpClients.custom().setConnectionManager(manager).setRetryHandler(handler)
127 .build();
128 return client;
129 }
130
131 /**
132 * Закрыть пул соединений
133 */
134 public static void closeConnectionPool() {
135 try {
136 httpClient.close();
137 manager.close();
138 monitorExecutor.shutdown();
139 } catch (IOException e) {
140 e.printStackTrace();
141 }
142 }
143
144}
1/**
2 * Выполните базовые настройки для http-запросов
3 *
4 * @param httpRequestBase HTTP-запрос
5 */
6private static void setRequestConfig(HttpRequestBase httpRequestBase) {
7 RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT)
8 .setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
9 httpRequestBase.setConfig(requestConfig);
10}
4) отправка формы
1public static String doPostForm(String url, Map<String, String> params) {
2 HttpPost httpPost = new HttpPost(url);
3 setRequestConfig(httpPost);
4 String resultString = "";
5 CloseableHttpResponse response = null;
6 try {
7
8 MultipartEntityBuilder builder = MultipartEntityBuilder.create();
9
10 if (params != null) {
11 for (String key : params.keySet()) {
12 builder.addPart(key,
13 new StringBody(params.get(key), ContentType.create("text/plain", Consts.UTF_8)));
14 }
15 }
16
17 HttpEntity reqEntity = builder.build();
18 httpPost.setEntity(reqEntity);
19
20 // Сделать запрос и вернуть запрошенный ответ
21 response = getHttpClient(url).execute(httpPost, HttpClientContext.create());
22 resultString = EntityUtils.toString(response.getEntity(), "utf-8");
23
24 } catch (IOException e) {
25 e.printStackTrace();
26 } catch (Exception e) {
27 e.printStackTrace();
28 } finally {
29 try {
30 if (response != null)
31 response.close();
32 } catch (IOException e) {
33 e.printStackTrace();
34 }
35 }
36 return resultString;
37}
5) Загрузка файла файла
1public static String uploadFile(String url, String localFile, String fileParamName, Map<String, String> params) {
2 HttpPost httpPost = new HttpPost(url);
3 setRequestConfig(httpPost);
4 String resultString = "";
5 CloseableHttpResponse response = null;
6 try {
7 // Преобразование файла в объект потока FileBody
8 FileBody bin = new FileBody(new File(localFile));
9
10 MultipartEntityBuilder builder = MultipartEntityBuilder.create();
11
12 // Эквивалентно<input type="file" name="file"/>
13 builder.addPart("files", bin);
14 // Эквивалентно<input type="text" name="userName" value=userName>
15 builder.addPart("filesFileName",
16 new StringBody(fileParamName, ContentType.create("text/plain", Consts.UTF_8)));
17 if (params != null) {
18 for (String key : params.keySet()) {
19 builder.addPart(key,
20 new StringBody(params.get(key), ContentType.create("text/plain", Consts.UTF_8)));
21 }
22 }
23
24 HttpEntity reqEntity = builder.build();
25 httpPost.setEntity(reqEntity);
26
27 // Сделать запрос и вернуть запрошенный ответ
28 response = getHttpClient(url).execute(httpPost, HttpClientContext.create());
29 resultString = EntityUtils.toString(response.getEntity(), "utf-8");
30
31 } catch (IOException e) {
32 e.printStackTrace();
33 } catch (Exception e) {
34 e.printStackTrace();
35 } finally {
36 try {
37 if (response != null)
38 response.close();
39 } catch (IOException e) {
40 e.printStackTrace();
41 }
42 }
43 return resultString;
44}
6) Передача данных Json
1public static String doPostJson(String url, String json) {
2 HttpPost httpPost = new HttpPost(url);
3 setRequestConfig(httpPost);
4 String resultString = "";
5 CloseableHttpResponse response = null;
6 try {
7 // Установите ContentType (Примечание. Если вы передаете только обычные параметры, ContentType не обязательно должен быть application/json)
8 // httpPost.setHeader("Content-Type",
9 // "application/json;charset=utf8");
10 httpPost.setHeader("Content-Type", "application/json");
11
12 // Создать контент запроса
13 StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
14 httpPost.setEntity(entity);
15 // осуществлятьHTTP-запрос
16 response = getHttpClient(url).execute(httpPost, HttpClientContext.create());
17 resultString = EntityUtils.toString(response.getEntity(), "utf-8");
18 } catch (Exception e) {
19 logger.error("Запрос на получение httpclient не выполнен, URL:" + url, e);
20 // e.printStackTrace();
21 } finally {
22 try {
23 if (response != null)
24 response.close();
25 } catch (IOException e) {
26 logger.error("Ошибка IOException", e);
27 // e.printStackTrace();
28 }
29 }
30 return resultString;
31}