Недавно я, наконец, не смог устоять перед желанием обновиться и обновил версию HttpClient моего проекта с 4 до 5. Процесс был непростым, и многие изменения API затрудняли его запуск.
Apache HttpClient 5 (также известный как HttpClient 5.x) является важным компонентом проекта Apache HttpComponents и используется для отправки HTTP-запросов и обработки HTTP-ответов. Это дает множество преимуществ при общении и обработке данных в сети:
Что касается вышеуказанных преимуществ, я чувствую лишь немного, но стоимость намного выше, чем преимущества. После простой самопроверки общее ощущение качественно не улучшилось. Единственное, что меня привлекает — это поддержка HTTP/2. Однако интерфейс протокола локально не разработан и не тестировался. Текущим мейнстримом по-прежнему является HTTP 1.1.
Это версия зависимостей, обновленная до HttpClient 5 в проекте FunTester.
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3</version>
</dependency>
Зависимые версии остаются без изменений. Если другие библиотеки в вашем проекте зависят от версии HttpClient 4.x, не забудьте исключить их, чтобы избежать помех.
Давайте начнем делиться изменениями API в произвольном порядке, перечисленными сверху вниз, в соответствии с моим проектом FunTester. В следующих вопросах старая версия относится к 4.x, а новая версия — к 5.3.
имя пакет изменен на org.apache.hc.client5.
На начальном этапе требуется много ручной работы.
В старой версии он назывался HttpRequestRetryHandler, а новая версия называется HttpRequestRetryStrategy У китайцев должна быть стратегия повторного тестирования. Существуют также различия в методах реализации. Метод старой версии public boolean retryRequest(IOException exception, int executionCount, HttpContext context)
,В новой версии необходимо реализовать несколько методов.:public boolean retryRequest(HttpRequest httpRequest, IOException e, int i, HttpContext httpContext)
、 public boolean retryRequest(HttpResponse httpResponse, int i, HttpContext httpContext)
、 public TimeValue getRetryInterval(HttpResponse httpResponse, int i, HttpContext httpContext)
Первый метод очень похож на старый интерфейс, и код можно применять напрямую. Второй метод используется для оценки ответной информации. еще раз этот метод довольно хорош и очень востребован. Третий способ получить пробу еще раз интервал, так как я не ставил функцию изменения, то она бесполезна. Но все обращают внимание на введение новых категорий. org.apache.hc.core5.util.TimeValue
, в HttpClient В версии 5 этот класс широко используется в качестве конфигурации времени.
Новая версия отменяет пакет API. Вот мой старый код:
ConnectionConfig connectionConfig = ConnectionConfig.custom().setMalformedInputAction(CodingErrorAction.IGNORE).setUnmappableInputAction(CodingErrorAction.IGNORE).setCharset(Constant.DEFAULT_CHARSET).setMessageConstraints(messageConstraints).build();
Вот новый код:
ConnectionConfig connectionConfig = ConnectionConfig.custom()// настраивать Конфигурация подключения
.setConnectTimeout(Timeout.of(Duration.ofMillis(CONNECT_TIMEOUT))) // Установить таймаут соединения
.setSocketTimeout(Timeout.of(Duration.ofMillis(SOCKET_TIMEOUT))) // настраивать socket тайм-аут
.setTimeToLive(Timeout.of(Duration.ofMillis(MAX_ACCEPT_TIME))) // настройкивремя выживания
.setValidateAfterInactivity(Timeout.of(Duration.ofMillis(MAX_ACCEPT_TIME))) // настройки Подтвердить после неактивности
.build();
В целом особой разницы нет. Последние два пункта Конфигурации не важны для тестирования производительности, ведь у ресурса соединения есть еще менеджер соединения и асинхронное восстановление. отвечает поток ресурсов.
Старый код:
// Обрабатывать https-запросы таким образом, чтобы обходить проверку.
// настраиватьпротоколhttpиhttpsпереписыватьсяизиметь дело сsocketФабрика ссылокизобъект
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE)).build();
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, dnsResolver);
// ограничения сообщений
MessageConstraints messageConstraints = MessageConstraints.custom().setMaxHeaderCount(HttpClientConstant.MAX_HEADER_COUNT).setMaxLineLength(HttpClientConstant.MAX_LINE_LENGTH).build();
Новый код по-прежнему отменяет некоторые API.,Самым большим изменением является создание API.,Хотя существует множество перегруженных методов построения PoolingHttpClientConnectionManager.,Но приказ записан,я просто хочунастраивать Конфигурация подключенияиDNSпарсер,Если вы используете конструктор,Вы должны использовать параметр N,Очень некрасиво. Для завершения рекомендуется использовать Builder.,Давайте посмотрим на исходный код метода build():
PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(RegistryBuilder.create().register(URIScheme.HTTP.id, PlainConnectionSocketFactory.getSocketFactory()).register(URIScheme.HTTPS.id, this.sslSocketFactory != null ? this.sslSocketFactory : (this.systemProperties ? SSLConnectionSocketFactory.getSystemSocketFactory() : SSLConnectionSocketFactory.getSocketFactory())).build(), this.poolConcurrencyPolicy, this.poolReusePolicy, (TimeValue)null, this.schemePortResolver, this.dnsResolver, this.connectionFactory);
По умолчанию для менеджера зарегистрирован фабричный класс HTTP-соединения. пула соединенийсерединаиз,Так что не надо повторятьнастраивать Понятно,И нет никакой бронинастраиватьHTTPизAPI。
асинхронный менеджер пула соединений Почти то же самое,Существует TlsStrategy, которого нет у менеджера синхронизации.,настраиватьметодследующее:
.setTlsStrategy(new BasicClientTlsStrategy(sslContext))
Конструктор использует метод create() для создания нового API, в то время как старый API по-прежнему использует custom().
существовать Запросить В конфигурации многие API до сих пор отменены, главным образом потому, что боятся дублирования соединения. Элементы, я предпочитаю это, одна и та же конфигурация в нескольких местах вызовет дополнительные проблемы и затраты на устранение неполадок. код выглядит следующим образом:
private static RequestConfig getRequestConfig() {
return RequestConfig.custom().setConnectionRequestTimeout(Timeout.ofMilliseconds(CONNECT_REQUEST_TIMEOUT)).setCookieSpec("ignoreCookies").setRedirectsEnabled(false).build();
}
Существует довольно неудобная настройка cookieSpec. API сохраняется, но класс перечисления элемента конфигурации отменяется. Затем он заменяется строкой и включается потерянное содержимое:
@Deprecated
public static final String BROWSER_COMPATIBILITY = "compatibility";
public static final String NETSCAPE = "netscape";
public static final String STANDARD = "standard";
public static final String STANDARD_STRICT = "standard-strict";
/** @deprecated */
@Deprecated
public static final String BEST_MATCH = "best-match";
public static final String DEFAULT = "default";
public static final String IGNORE_COOKIES = "ignoreCookies";
При тестировании производительности нет необходимости CookieStore
для управления файлами cookie, поэтому игнорируйте их.
Я использовал новый API org.apache.hc.client5.http.impl.classic.HttpClientBuilder#disableCookieManagement
Глядя на документ с исходным кодом, кажется, что он отменен. CookieStore
Конфигурация, поскольку я проектировал ее в обоих местах, никаких отклонений пока не обнаружил.
Есть еще один параметр метода, Старый код:
public void process(HttpResponse httpResponse, HttpContext httpContext)
Новый код:
public void process(HttpResponse httpResponse, EntityDetails entityDetails, HttpContext httpContext)
менеджер пула соединений имеет два доступных восстановления Метод ресурсов обычно вызывается асинхронно, чтобы предотвратить исключения ресурсов:
connManager.closeExpiredConnections();
connManager.closeIdleConnections(HttpClientConstant.IDLE_TIMEOUT, TimeUnit.SECONDS);
Новый код выглядит следующим образом:
connManager.closeExpired();
connManager.closeIdle(TimeValue.ofSeconds(IDLE_TIMEOUT));
запускатьасинхронный Метод start() клиента остается неизменным, но есть некоторые различия в логике принятия решения в исходном коде, особенно в атрибутах статуса. Старый код:
public void start() {
if (this.status.compareAndSet(CloseableHttpAsyncClientBase.Status.INACTIVE, CloseableHttpAsyncClientBase.Status.ACTIVE) && this.reactorThread != null) {
this.reactorThread.start();
}
}
Новый код:
public final void start() {
if (this.status.compareAndSet(AbstractHttpAsyncClientBase.Status.READY, AbstractHttpAsyncClientBase.Status.RUNNING)) {
DefaultConnectingIOReactor var10001 = this.ioReactor;
this.executorService.execute(var10001::start);
}
}
По старому кодексу актерское мастерство Конфигурацияможет быть напрямуюсуществоватьHttpClientсерединанастраивать,Новый код сделает API настроек устаревшим,нуждатьсясуществоватьRequestConfigсерединанастраивать Только тогда,Код остается неизменным,следующее:
setProxy(new HttpHost(ip, port))
Включено большое количество объектов, начиная с классического, например org.apache.hc.core5.http.message.BasicClassicHttpRequest
、 org.apache.hc.core5.http.ClassicHttpResponse
, а также стала осуществляться регистрация объектов HTTP-запросов различных номеров пакетов. org.apache.hc.client5.http.classic.methods
. Кажется, эта версия возвращается к классике.
В старой версии кода, если вы хотите обработать объект запроса или ответа, вы должны быть org.apache.http.HttpEntityEnclosingRequest
объект, в новой версии кода становится org.apache.hc.core5.http.HttpEntityContainer
и отменено boolean expectContinue()
метод.
В устаревшем коде,Запросы GET и DELETE по умолчанию не содержат объект запроса.,Если вы хотите реализовать эту функцию, вам нужно реализовать ее самостоятельно.,Новая версия в разработке,Все сотрудники несут сущности. Это изменение по-прежнему приветствуется.
Также есть некоторые изменения в API настройки объекта.,Оказалось, чтонастраиватьStringВведите формат кодировки,сейчассуществоватьпрямойнастраивать java.nio.charset.Charset
, какое большое улучшение.
Имя метода изменилось с getAllHeader на getHeaders, больше ничего.
HttpClient 5Отменено Получить строку ответаизизAPI getStatusLine
,Если вы хотите получить код статуса,Пожалуйста, используйте:org.apache.hc.client5.http.impl.classic.CloseableHttpResponse#getCode
Лично я считаю, что это неуместно. Это немного не соответствует структуре HTTP-запроса, но это действительно удобно.
Старая версияметод:getURI
,Возврат URIобъекта,новая версия:getUri
,также Возврат URIобъекта,Есть еще один getRequestUri
Возвращает объект String. Это просто разница в капитализации. Интересно, это инструмент, который автоматически добавляет код для адаптации.
Также поддерживается Асинхронный в синхронизированном HttpClient запросиз,Устаревший код и запросы синхронизации Public Requests объект,новая версияувеличение кода Понятноновыйизпроситьобъект:org.apache.hc.client5.http.async.methods.SimpleHttpRequest
,Этот класс понимает подклассы,также Не унаследовано от ранее упомянутогоиз HttpUriRequestBase
,Такое ощущение, что это независимая ветка.。такой жеизответобъекттакжеда org.apache.hc.client5.http.async.methods.SimpleHttpResponse
。
HttpClient 5середина Оба предлагаются Понятносинхронизировать собъекткопироватьизметодcopy()
,Странно то, что запрошенная копия помечена как устаревший метод.,Запутанное поведение. Из исходного кода видно, что запросы GET и POST можно создавать легко и быстро.
Существует метод прямого получения тела ответа org.apache.hc.client5.http.async.methods.SimpleHttpResponse#getBodyText
,Взгляните,Освоить метод синхронизации непросто.
Одно слово: бросать. Вызов API завершен, и позже мы поделимся другими изменениями на основе результатов тестирования.
Если нет большого спроса, не рекомендуется обновлять HttpClient 5.