Я уже некоторое время использую Spring RestTemplate и постоянно бьюсь о стену, когда пытаюсь отлаживать ее запросы и ответы. Я в основном ищу то же самое, что и при использовании curl с включенной опцией «verbose». Например :
curl -v http://twitter.com/statuses/public_timeline.rss
Будет отображать как отправленные данные, так и полученные данные (включая заголовки, куки и т. Д.).
Я проверил некоторые похожие сообщения, такие как: Как мне регистрировать ответы в Spring RestTemplate? но мне не удалось решить эту проблему.
Один из способов сделать это состоит в том, чтобы фактически изменить исходный код RestTemplate и добавить туда несколько дополнительных операторов регистрации, но я бы нашел этот подход действительно последним средством. Должен быть какой-то способ сказать Spring Web Client / RestTemplate, чтобы все регистрировалось более дружественным способом.
Моя цель - сделать это с помощью кода вроде:
restTemplate.put("http://someurl", objectToPut, urlPathValues);
и затем получить тот же тип отладочной информации (как я получаю с помощью curl) в файле журнала или в консоли. Я считаю, что это было бы чрезвычайно полезно для любого, кто использует Spring RestTemplate и имеет проблемы. Использование curl для отладки ваших проблем RestTemplate просто не работает (в некоторых случаях).
источник
Ответы:
Просто для завершения примера с полной реализацией
ClientHttpRequestInterceptor
для отслеживания запроса и ответа:Затем создайте экземпляр
RestTemplate
с помощью aBufferingClientHttpRequestFactory
иLoggingRequestInterceptor
:BufferingClientHttpRequestFactory
Требуется , как мы хотим , чтобы использовать тело ответа как в перехватчик и для исходного кода вызова. Реализация по умолчанию позволяет прочитать тело ответа только один раз.источник
BufferingClientHttpResponseWrapper
учетом @sofienezaghdoudi. Тем не менее, она не работает , когда используется в тестах с использованием mockServer рамок весны , так какMockRestServiceServer.createServer(restTemplate)
переписывает RequestFactory кInterceptingClientHttpRequestFactory
.в Spring Boot вы можете получить полный запрос / ответ, установив его в свойствах (или другой метод 12 факторов)
это выводы
и ответ
или просто,
logging.level.org.apache.http.wire=DEBUG
который, кажется, содержит всю соответствующую информациюисточник
by default the RestTemplate relies on standard JDK facilities to establish HTTP connections. You can switch to use a different HTTP library such as Apache HttpComponents
http-outgoing-0 << "[0x1f][0x8b][0x8][0x0][0x0][0x0][0x0][0x0]
Расширяем ответ @hstoerr с помощью некоторого кода:
Создать LoggingRequestInterceptor для регистрации ответов на запросы
Настройка RestTemplate
источник
Лучше всего добавить
logging.level.org.springframework.web.client.RestTemplate=DEBUG
вapplication.properties
файл.Другие решения, такие как настройка
log4j.logger.httpclient.wire
, не всегда будут работать, потому что они предполагают, что вы используетеlog4j
Apache.HttpClient
, что не всегда верно.Обратите внимание, что этот синтаксис будет работать только в последних версиях Spring Boot.
источник
wire
логирование, оно включает в себя только важную информацию, такую как URL, повторный отсчет кода, параметры POST и т. Д.Ни один из этих ответов на самом деле не решает 100% проблемы. mjj1409 получает большую часть этого, но удобно избегает проблемы регистрации ответа, которая требует немного больше работы. Пол Сабу предлагает решение, которое кажется реалистичным, но не предоставляет достаточно подробностей для его реализации (и оно не сработало для меня). Софиен получила протоколирование, но с критической проблемой: ответ больше не читается, потому что входной поток уже использован!
Я рекомендую использовать BufferingClientHttpResponseWrapper, чтобы обернуть объект ответа, чтобы разрешить чтение тела ответа несколько раз:
Это не будет использовать InputStream, потому что тело ответа загружается в память и может быть прочитано несколько раз. Если у вас нет BufferingClientHttpResponseWrapper на вашем пути к классам, вы можете найти простую реализацию здесь:
https://github.com/spring-projects/spring-android/blob/master/spring-android-rest-template/src/main/java/org/springframework/http/client/BufferingClientHttpResponseWrapper.java
Для настройки RestTemplate:
источник
status==200
, прежде чемresponseCopy.getBody()
asyncRestTemplate
?ListenableFuture
Когда вы перехватываете, потребуется вернуть a , который невозможно изменить при обратномBufferingClientHttpResponseWrapper
вызове.Вы можете использовать spring-rest-template-logger для регистрации
RestTemplate
трафика HTTP.Добавьте зависимость в ваш проект Maven:
Затем настройте ваш
RestTemplate
следующим образом:Убедитесь, что ведение журнала отладки включено в
application.properties
:Теперь весь HTTP-трафик RestTemplate будет регистрироваться в
org.hobsoft.spring.resttemplatelogger.LoggingCustomizer
на уровне отладки.ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я написал эту библиотеку.
источник
Решение, данное ксенотеррацидом для использования
это хорошо, но проблема в том, что по умолчанию Apache HttpComponents не используется.
Чтобы использовать Apache HttpComponents, добавьте в свой pom.xml
и настроить
RestTemplate
с помощью:источник
Я наконец нашел способ сделать это правильно. Большая часть решения исходит от того, как настроить Spring и SLF4J, чтобы я мог получать журналы?
Кажется, есть две вещи, которые необходимо сделать:
log4j.logger.httpclient.wire=DEBUG
Вторая проблема возникает в основном в среде Spring, где используется slf4j (как это было в моем случае). Таким образом, при использовании slf4j убедитесь, что следующие две вещи происходят:
В вашем пути к классам нет библиотеки регистрации общего доступа: это можно сделать, добавив дескрипторы исключения в ваш pom:
Файл log4j.properties хранится где-то в пути к классам, где Spring может найти / увидеть его. Если у вас есть проблемы с этим, последним решением было бы поместить файл log4j.properties в пакет по умолчанию (не очень хорошая практика, но просто чтобы убедиться, что все работает так, как вы ожидаете)
источник
httpclient.wire
на самом деле из библиотеки Apache HttpComponents HttpClient (см. hc.apache.org/httpcomponents-client-ga/logging.html ). Этот метод будет работать, только если выRestTemplate
настроили использоватьHttpComponentsClientHttpRequestFactory
Ведение журнала RestTemplate
Вариант 1. Откройте журнал отладки.
Конфигурировать RestTemplate
По умолчанию RestTemplate использует стандартные средства JDK для установления HTTP-соединений. Вы можете переключиться на использование другой библиотеки HTTP, такой как Apache HttpComponents
@Bean public RestTemplate restTemplate (RestTemplateBuilder builder) {RestTemplate restTemplate = builder.build (); вернуть restTemplate; }
Настроить ведение журнала
application.yml
ведение журнала: level: org.springframework.web.client.RestTemplate: DEBUG
Вариант 2. Использование перехватчика
Ответ Оболочки
Внедрить перехватчик
Конфигурировать RestTemplate
Настроить ведение журнала
Проверьте пакет LoggingRestTemplate, например, в
application.yml
:logging: level: com.example.logging: DEBUG
Вариант 3. Использование httpcomponent
Импортировать зависимость httpcomponent
Конфигурировать RestTemplate
Настроить ведение журнала
Проверьте пакет LoggingRestTemplate, например, в
application.yml
:ведение журнала: уровень: org.apache.http: DEBUG
источник
TestRestTemplate
, настройтеRestTemplateBuilder
: @Bean public RestTemplateBuilder restTemplateBuilder () {вернуть новый RestTemplateBuilder (). AdditionalInterceptors (Collections.singletonList (new LoggingRestTemplate ())); }---- июль 2019 года ----
(используя Spring Boot)
Я был удивлен, что Spring Boot, со всей его магией Zero Configuration, не предоставляет простой способ проверки или записи простого тела ответа JSON с RestTemplate. Я просмотрел различные ответы и комментарии, представленные здесь, и делюсь своей собственной дистиллированной версией того, что (все еще) работает, и мне кажется разумным решением, учитывая текущие параметры (я использую Spring Boot 2.1.6 с Gradle 4.4 )
1. Использование Fiddler в качестве http-прокси
На самом деле это довольно элегантное решение, так как оно обходит все громоздкие усилия по созданию собственного перехватчика или замене базового http-клиента на apache (см. Ниже).
а потом
2. Использование Apache HttpClient
Добавьте Apache HttpClient в зависимости от Maven или Gradle.
Используйте
HttpComponentsClientHttpRequestFactory
как RequestFactory для RestTemplate. Самый простой способ сделать это будет:Включите DEBUG в свой
application.properties
файл (если вы используете Spring Boot)Если вы используете Spring Boot, вам нужно убедиться, что у вас настроена среда ведения журналов, например, с помощью зависимости spring-boot-starter, которая включает
spring-boot-starter-logging
.3. Используйте перехватчик
Я позволю вам прочитать предложения, встречные предложения и ошибки в других ответах и комментариях и решить для себя, хотите ли вы пойти по этому пути.
4. Записать URL и статус ответа без тела
Хотя это не отвечает заявленным требованиям регистрации тела, это быстрый и простой способ начать регистрацию ваших вызовов REST. Он отображает полный URL-адрес и статус ответа.
Просто добавьте следующую строку в ваш
application.properties
файл (при условии, что вы используете Spring Boot, и если вы используете зависимость для начальной загрузки Spring, которая включает в себяspring-boot-starter-logging
)Вывод будет выглядеть примерно так:
источник
Помимо ведения журнала HttpClient, описанного в другом ответе , вы также можете ввести ClientHttpRequestInterceptor, который читает тело запроса и ответ и регистрирует его. Возможно, вы захотите сделать это, если другие вещи также используют HttpClient, или если вы хотите пользовательский формат ведения журнала. Осторожно: вы захотите дать RestTemplate объект BufferingClientHttpRequestFactory, чтобы вы могли прочитать ответ дважды.
источник
Как указано в других ответах, тело ответа требует особой обработки, чтобы его можно было читать повторно (по умолчанию его содержимое расходуется при первом чтении).
Вместо использования
BufferingClientHttpRequestFactory
при настройке запроса, перехватчик сам может обернуть ответ и убедиться, что содержимое сохраняется и может многократно читаться (регистратором, а также потребителем ответа):Мой перехватчик, который
Код:
Конфигурация:
Пример вывода журнала:
источник
application.properties
application.yml
источник
Возможно, это неправильный способ сделать это, но я думаю, что это самый простой подход к печати запросов и ответов без чрезмерного заполнения журналов.
Добавляя ниже 2 строки, application.properties регистрирует все запросы и ответы в 1-й строке, чтобы регистрировать запросы, а во 2-й строке - в ответах.
источник
Предполагая,
RestTemplate
что настроено использование HttpClient 4.x, вы можете прочитать документацию по протоколированию HttpClient здесь . Регистраторы отличаются от тех, которые указаны в других ответах.Конфигурация регистрации для HttpClient 3.x доступна здесь .
источник
Так много ответов здесь требуют изменений кодирования и настраиваемых классов, и это действительно не нужно. Получите прокси-сервер для отладки, такой как fiddler, и настройте свою среду java на использование прокси в командной строке (-Dhttp.proxyHost и -Dhttp.proxyPort), затем запустите fiddler, и вы сможете увидеть запросы и ответы полностью. Также имеется множество дополнительных преимуществ, таких как возможность манипулировать результатами и ответами до и после того, как они отправлены для проведения экспериментов, прежде чем приступить к модификации сервера.
Последняя проблема, которая может возникнуть, заключается в том, что если вы должны использовать HTTPS, вам нужно будет экспортировать сертификат SSL из fiddler и импортировать его в подсказку хранилища ключей java (cacerts): пароль хранилища ключей java по умолчанию обычно "changeit".
источник
-DproxySet=true -Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888
.Для входа в Logback с помощью Apache HttpClient:
Вам нужен Apache HttpClient в classpath:
Настройте
RestTemplate
для использования HttpClient:Для регистрации запросов и ответов добавьте в файл конфигурации Logback:
Или войти еще больше:
источник
org.apache.http.wire=DEBUG
в вашемapplication.properties
сейчасУловка настройки вашего
RestTemplate
сBufferingClientHttpRequestFactory
не работает, если вы используете какой-либоClientHttpRequestInterceptor
, что вы будете делать, если вы пытаетесь войти через перехватчики. Это связано с тем, какInterceptingHttpAccessor
(какиеRestTemplate
подклассы) работает.Короче говоря ... просто используйте этот класс вместо
RestTemplate
(обратите внимание, что для этого используется API журналирования SLF4J, редактируйте по мере необходимости):Я согласен, что глупо, что для этого требуется такая большая работа.
источник
В добавление к обсуждению выше это только представляет счастливые сценарии. вероятно, вы не сможете записать ответ, если ошибка придет .
В этом случае плюс все вышеперечисленные случаи вы должны переопределить DefaultResponseErrorHandler и установить его, как показано ниже
источник
Как ни странно, ни одно из этих решений не работает, так как RestTemplate, похоже, не возвращает ответ на некоторые ошибки клиента и сервера в 500 раз. В этом случае вы также будете регистрировать их, реализовав ResponseErrorHandler следующим образом. Вот черновик кода, но вы понимаете:
Вы можете установить тот же перехватчик, что и обработчик ошибок:
И перехват осуществляет оба интерфейса:
источник
Как указал @MilacH, в реализации есть ошибка. Если statusCode> 400 возвращается, IOException генерируется, так как errorHandler не вызывается из перехватчиков. Исключение можно игнорировать, а затем снова перехватить в методе обработчика.
источник
Лучшее решение сейчас, просто добавьте зависимость:
Он содержит класс LoggingRequestInterceptor, который вы можете добавить таким образом в RestTemplate:
интегрируйте эту утилиту, добавив ее в качестве перехватчика в Spring RestTemplate, следующим образом:
и добавьте реализацию slf4j в ваш фреймворк, например, log4j.
или напрямую используйте "Zg2proRestTemplate" . «Лучший ответ» @PaulSabou выглядит так, поскольку httpclient и все библиотеки apache.http не обязательно загружаются при использовании пружинного RestTemplate.
источник
log("Headers: {}", request.headers)
внутриLoggingRequestInterceptor:traceRequest
иlog("Headers: {}", response.headers)
внутриLoggingRequestInterceptor:logResponse
. Вы можете подумать о добавлении некоторых флагов для регистрации заголовков и тела. Кроме того - вы можете проверить тип содержимого тела для регистрации (например, log only application / json *). Это также должно быть настраиваемым. в общем, с этими небольшими изменениями у вас будет хорошая библиотека для распространения. хорошая работа :)Хотел добавить и мою реализацию этого тоже. Я прошу прощения за все недостающие точки с запятой, это написано на Groovy.
Мне нужно что-то более настраиваемое, чем принятый ответ. Вот бин шаблона отдыха, который очень гибок и регистрирует все, как ищет OP.
Пользовательский класс перехватчика регистрации:
Определение шаблона компонента Rest:
Реализация:
источник
Обратитесь к разделу «Вопросы и ответы» для регистрации запросов и ответов для шаблона остальных, включив множественные чтения в HttpInputStream
Почему мой пользовательский ClientHttpRequestInterceptor с пустым ответом
источник
org.apache.http.wire выдает слишком нечитаемые журналы, поэтому я использую журнал для регистрации приложения Servlet и RestTemplate req / resp для входа
build.gradle
application.properties
RestTemplate
источник
Что касается ответа с использованием ClientHttpInterceptor, я нашел способ сохранить весь ответ без буферизации фабрик. Просто сохраните входной поток тела ответа внутри байтового массива, используя некоторый метод utils, который скопирует этот массив из тела, но важно, окружите этот метод try catch, потому что он сломается, если ответ пуст (что является причиной исключения доступа к ресурсам), и в catch просто создайте пустой байтовый массив, а затем просто создайте анонимный внутренний класс ClientHttpResponse, используя этот массив и другие параметры из исходного ответа. Затем вы можете вернуть этот новый объект ClientHttpResponse в цепочку выполнения остальных шаблонов и зарегистрировать ответ, используя байтовый массив тела, который был ранее сохранен. Таким образом, вы не будете использовать InputStream в реальном ответе и сможете использовать ответ Rest Template как есть. Заметка,
источник
мой конфиг логгера использовал xml
тогда вы получите что-то вроде ниже:
через HttpMessageConverterExtractor.java:92, вам нужно продолжить отладку, и в моем случае я получил это:
и это:
outputMessage.getBody () содержит сообщение, отправляемое http (тип записи)
источник