it-swarm.com.de

Spring RestTemplate - wie können Sie das vollständige Debuggen/Protokollieren von Anforderungen/Antworten aktivieren?

Ich benutze das Spring RestTemplate schon eine Weile und stoße ständig gegen eine Wand, wenn ich versuche, seine Anfragen und Antworten zu debuggen. Im Grunde schaue ich auf die gleichen Dinge, die ich sehe, wenn ich curl mit aktivierter Option "verbose" verwende. Zum Beispiel :

curl -v http://Twitter.com/statuses/public_timeline.rss

Zeigt sowohl die gesendeten als auch die empfangenen Daten (einschließlich der Header, Cookies usw.) an.

Ich habe einige verwandte Beiträge geprüft: Wie protokolliere ich die Antwort in Spring RestTemplate? aber ich konnte dieses Problem nicht lösen.

Eine Möglichkeit, dies zu tun, wäre, den RestTemplate-Quellcode tatsächlich zu ändern und dort zusätzliche Protokollierungsanweisungen hinzuzufügen, aber ich würde diesen Ansatz wirklich als letzten Ausweg betrachten. Spring Web Client/RestTemplate sollte einen Weg finden, alles viel freundlicher zu protokollieren.

Mein Ziel wäre es, dies mit Code wie:

restTemplate.put("http://someurl", objectToPut, urlPathValues);

und dann die gleiche Art von Debug-Informationen (wie ich sie mit curl bekomme) in die Protokolldatei oder in die Konsole holen .. Ich glaube, das wäre äußerst nützlich für alle, die Spring RestTemplate verwenden und Probleme haben. Die Verwendung von curl zum Debuggen von RestTemplate-Problemen funktioniert in manchen Fällen nicht. 

149
Paul Sabou

Ich habe endlich einen Weg gefunden, dies auf die richtige Art und Weise zu tun ... Die meiste Lösung kommt von Wie konfiguriere ich Spring und SLF4J, damit ich protokollieren kann?

Es scheint, dass es zwei Dinge gibt, die getan werden müssen:

  1. Fügen Sie in log4j.properties die folgende Zeile hinzu: log4j.logger.httpclient.wire=DEBUG
  2. Stellen Sie sicher, dass spring Ihre Protokollierungskonfiguration nicht ignoriert

Das zweite Problem tritt meistens in Frühlingsumgebungen auf, in denen slf4j verwendet wird (wie in meinem Fall). Wenn also slf4j verwendet wird, stellen Sie sicher, dass die folgenden beiden Dinge passieren:

  1. Es gibt keine Commons-Protokollierungsbibliothek in Ihrem Klassenpfad. Dies kann durch Hinzufügen der Ausschlussdeskriptoren in Ihrem pom erreicht werden:

            <exclusions><exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
    
  2. Die Datei log4j.properties wird irgendwo im Klassenpfad gespeichert, wo spring sie finden/sehen kann. Wenn Sie Probleme damit haben, besteht die letzte Lösung darin, die Datei log4j.properties in das Standardpaket zu packen (keine bewährte Methode, aber nur um zu sehen, dass alles wie erwartet funktioniert).

24
Paul Sabou

Nur um das Beispiel mit einer vollständigen Implementierung von ClientHttpRequestInterceptor abzuschließen, um die Anforderung und Antwort zu verfolgen: 

import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {

    final static Logger log = LoggerFactory.getLogger(LoggingRequestInterceptor.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        traceRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        traceResponse(response);
        return response;
    }

    private void traceRequest(HttpRequest request, byte[] body) throws IOException {
        log.info("===========================request begin================================================");
        log.debug("URI         : {}", request.getURI());
        log.debug("Method      : {}", request.getMethod());
        log.debug("Headers     : {}", request.getHeaders() );
        log.debug("Request body: {}", new String(body, "UTF-8"));
        log.info("==========================request end================================================");
    }

    private void traceResponse(ClientHttpResponse response) throws IOException {
        StringBuilder inputStringBuilder = new StringBuilder();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), "UTF-8"));
        String line = bufferedReader.readLine();
        while (line != null) {
            inputStringBuilder.append(line);
            inputStringBuilder.append('\n');
            line = bufferedReader.readLine();
        }
        log.info("============================response begin==========================================");
        log.debug("Status code  : {}", response.getStatusCode());
        log.debug("Status text  : {}", response.getStatusText());
        log.debug("Headers      : {}", response.getHeaders());
        log.debug("Response body: {}", inputStringBuilder.toString());
        log.info("=======================response end=================================================");
    }

}

Dann instanziieren Sie RestTemplate mit einer BufferingClientHttpRequestFactory und der LoggingRequestInterceptor:

RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
interceptors.add(new LoggingRequestInterceptor());
restTemplate.setInterceptors(interceptors);

Die Variable BufferingClientHttpRequestFactory ist erforderlich, da wir den Antworttext sowohl im Interceptor als auch für den ursprünglichen Aufrufcode verwenden möchten. Bei der Standardimplementierung kann der Antworttext nur einmal gelesen werden.

147

Erweiterung der @ hstoerr-Antwort mit etwas Code:


Erstellen Sie LoggingRequestInterceptor, um Anforderungsantworten zu protokollieren

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {

    private static final Logger log = LoggerFactory.getLogger(LoggingRequestInterceptor.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {

        ClientHttpResponse response = execution.execute(request, body);

        log(request,body,response);

        return response;
    }

    private void log(HttpRequest request, byte[] body, ClientHttpResponse response) throws IOException {
        //do logging
    }
}

RestTemplate einrichten

RestTemplate rt = new RestTemplate();

//set interceptors/requestFactory
ClientHttpRequestInterceptor ri = new LoggingRequestInterceptor();
List<ClientHttpRequestInterceptor> ris = new ArrayList<ClientHttpRequestInterceptor>();
ris.add(ri);
rt.setInterceptors(ris);
rt.setRequestFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
76
mjj1409

in Spring Boot können Sie die vollständige Anforderung/Antwort abrufen, indem Sie dies in den Eigenschaften (oder einer anderen 12-Faktor-Methode) festlegen.

logging.level.org.Apache.http=DEBUG

diese Ausgänge

-DEBUG .i.c.DefaultHttpClientConnectionOperator : Connecting to localhost/127.0.0.1:41827
-DEBUG .i.c.DefaultHttpClientConnectionOperator : Connection established 127.0.0.1:39546<->127.0.0.1:41827
-DEBUG o.a.http.impl.execchain.MainClientExec   : Executing request POST /v0/users HTTP/1.1
-DEBUG o.a.http.impl.execchain.MainClientExec   : Target auth state: UNCHALLENGED
-DEBUG o.a.http.impl.execchain.MainClientExec   : Proxy auth state: UNCHALLENGED
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> POST /v0/users HTTP/1.1
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> Content-Type: application/json;charset=UTF-8
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> Content-Length: 56
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> Host: localhost:41827
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> Connection: Keep-Alive
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_102)
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> Accept-Encoding: gzip,deflate
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "POST /v0/users HTTP/1.1[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "Content-Type: application/json;charset=UTF-8[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "Content-Length: 56[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "Host: localhost:41827[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_102)[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "{"id":null,"email":"[email protected]","new":true}"

und Antwort

-DEBUG .i.c.DefaultHttpClientConnectionOperator : Connecting to localhost/127.0.0.1:41827
-DEBUG .i.c.DefaultHttpClientConnectionOperator : Connection established 127.0.0.1:39546<->127.0.0.1:41827
-DEBUG o.a.http.impl.execchain.MainClientExec   : Executing request POST /v0/users HTTP/1.1
-DEBUG o.a.http.impl.execchain.MainClientExec   : Target auth state: UNCHALLENGED
-DEBUG o.a.http.impl.execchain.MainClientExec   : Proxy auth state: UNCHALLENGED
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> POST /v0/users HTTP/1.1
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> Content-Type: application/json;charset=UTF-8
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> Content-Length: 56
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> Host: localhost:41827
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> Connection: Keep-Alive
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_102)
-DEBUG org.Apache.http.headers                  : http-outgoing-0 >> Accept-Encoding: gzip,deflate
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "POST /v0/users HTTP/1.1[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "Content-Type: application/json;charset=UTF-8[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "Content-Length: 56[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "Host: localhost:41827[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_102)[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "[\r][\n]"
-DEBUG org.Apache.http.wire                     : http-outgoing-0 >> "{"id":null,"email":"[email protected]","new":true}"

oder nur logging.level.org.Apache.http.wire=DEBUG, der scheinbar alle relevanten Informationen enthält

76
xenoterracide

Keine dieser Antworten löst tatsächlich 100% des Problems. mjj1409 bekommt das meiste davon, vermeidet jedoch bequem das Problem der Protokollierung der Antwort, was etwas mehr Arbeit erfordert. Paul Sabou bietet eine Lösung, die realistisch erscheint, bietet aber nicht genügend Details, um sie tatsächlich umzusetzen (und sie funktionierte bei mir überhaupt nicht). Sofiene bekam die Protokollierung mit einem kritischen Problem: Die Antwort ist nicht mehr lesbar, da der Eingabestrom bereits verbraucht ist!

Ich empfehle die Verwendung eines BufferingClientHttpResponseWrapper, um das Antwortobjekt zu umschließen, damit der Antworttext mehrmals gelesen werden kann:

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(LoggingRequestInterceptor.class);

    @Override
    public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
            final ClientHttpRequestExecution execution) throws IOException {
        ClientHttpResponse response = execution.execute(request, body);

        response = log(request, body, response);

        return response;
    }

    private ClientHttpResponse log(final HttpRequest request, final byte[] body, final ClientHttpResponse response) {
        final ClientHttpResponse responseCopy = new BufferingClientHttpResponseWrapper(response);
        logger.debug("Method: ", request.getMethod().toString());
        logger.debug("URI: ", , request.getURI().toString());
        logger.debug("Request Body: " + new String(body));
        logger.debug("Response body: " + IOUtils.toString(responseCopy.getBody()));
        return responseCopy;
    }

}

Dadurch wird InputStream nicht verbraucht, da der Antworttext in den Arbeitsspeicher geladen wird und mehrmals gelesen werden kann. Wenn Sie den BufferingClientHttpResponseWrapper nicht in Ihrem Klassenpfad haben, finden Sie die einfache Implementierung hier:

https://github.com/spring-projects/spring-Android/blob/master/spring-Android-rest-template/src/main/Java/org/springframework/http/client/BufferingClientHttpResponseWrapper.Java

Um das RestTemplate einzurichten:

LoggingRequestInterceptor loggingInterceptor = new LoggingRequestInterceptor();
restTemplate.getInterceptors().add(loggingInterceptor);
26
James Watkins

Die von Xenoterracide zur Verfügung gestellte Lösung

logging.level.org.Apache.http=DEBUG

ist gut, aber das Problem ist, dass Apache HttpComponents standardmäßig nicht verwendet wird.

Um Apache zu verwenden, fügen Sie HttpComponents zu Ihrer pom.xml hinzu

<dependency>
    <groupId>org.Apache.httpcomponents</groupId>
    <artifactId>httpasyncclient</artifactId>
</dependency>

und konfigurieren Sie RestTemplate mit:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsAsyncClientHttpRequestFactory());
22
Ortomala Lokni

Am besten fügen Sie logging.level.org.springframework.web.client.RestTemplate=DEBUG zur application.properties-Datei hinzu.

Andere Lösungen wie die Einstellung log4j.logger.httpclient.wire funktionieren nicht immer, da sie davon ausgehen, dass Sie log4j und Apache HttpClient verwenden, was nicht immer der Fall ist.

Beachten Sie jedoch, dass diese Syntax nur mit den neuesten Spring Boot-Versionen funktioniert.

19
gamliela

RestTemplate protokollieren

Option 1. Öffnen Sie die Debug-Protokollierung.

RestTemplate konfigurieren

  • Standardmäßig setzt RestTemplate zum Aufbau von HTTP-Verbindungen Standard JDK-Funktionen ein. Sie können wechseln, um eine andere HTTP-Bibliothek wie Apache HttpComponents zu verwenden

    @Bean Public RestTemplate restTemplate (Builder für RestTemplateBuilder) { RestTemplate restTemplate = builder.build (); return restTemplate; }

Protokollierung konfigurieren

  • application.yml

    protokollierung: Niveau: org.springframework.web.client.RestTemplate: DEBUG

Option 2. Interceptor verwenden

Wrapper-Antwort

import Java.io.ByteArrayInputStream;
import Java.io.IOException;
import Java.io.InputStream;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StreamUtils;

public final class BufferingClientHttpResponseWrapper implements ClientHttpResponse {

    private final ClientHttpResponse response;

    private byte[] body;


    BufferingClientHttpResponseWrapper(ClientHttpResponse response) {
        this.response = response;
    }

    public HttpStatus getStatusCode() throws IOException {
        return this.response.getStatusCode();
    }

    public int getRawStatusCode() throws IOException {
        return this.response.getRawStatusCode();
    }

    public String getStatusText() throws IOException {
        return this.response.getStatusText();
    }

    public HttpHeaders getHeaders() {
        return this.response.getHeaders();
    }

    public InputStream getBody() throws IOException {
        if (this.body == null) {
            this.body = StreamUtils.copyToByteArray(this.response.getBody());
        }
        return new ByteArrayInputStream(this.body);
    }

    public void close() {
        this.response.close();
    }
}

Implementieren Sie Interceptor

package com.example.logging;

import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class LoggingRestTemplate implements ClientHttpRequestInterceptor {

    private final static Logger LOGGER = LoggerFactory.getLogger(LoggingRestTemplate.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body,
            ClientHttpRequestExecution execution) throws IOException {
        traceRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        return traceResponse(response);
    }

    private void traceRequest(HttpRequest request, byte[] body) throws IOException {
        if (!LOGGER.isDebugEnabled()) {
            return;
        }
        LOGGER.debug(
                "==========================request begin==============================================");
        LOGGER.debug("URI                 : {}", request.getURI());
        LOGGER.debug("Method            : {}", request.getMethod());
        LOGGER.debug("Headers         : {}", request.getHeaders());
        LOGGER.debug("Request body: {}", new String(body, "UTF-8"));
        LOGGER.debug(
                "==========================request end================================================");
    }

    private ClientHttpResponse traceResponse(ClientHttpResponse response) throws IOException {
        if (!LOGGER.isDebugEnabled()) {
            return response;
        }
        final ClientHttpResponse responseWrapper = new BufferingClientHttpResponseWrapper(response);
        StringBuilder inputStringBuilder = new StringBuilder();
        BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(responseWrapper.getBody(), "UTF-8"));
        String line = bufferedReader.readLine();
        while (line != null) {
            inputStringBuilder.append(line);
            inputStringBuilder.append('\n');
            line = bufferedReader.readLine();
        }
        LOGGER.debug(
                "==========================response begin=============================================");
        LOGGER.debug("Status code    : {}", responseWrapper.getStatusCode());
        LOGGER.debug("Status text    : {}", responseWrapper.getStatusText());
        LOGGER.debug("Headers            : {}", responseWrapper.getHeaders());
        LOGGER.debug("Response body: {}", inputStringBuilder.toString());
        LOGGER.debug(
                "==========================response end===============================================");
        return responseWrapper;
    }

}

RestTemplate konfigurieren

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    RestTemplate restTemplate = builder.build();
    restTemplate.setInterceptors(Collections.singletonList(new LoggingRestTemplate()));
    return restTemplate;
}

Protokollierung konfigurieren

  • Überprüfen Sie das Paket von LoggingRestTemplate, zum Beispiel in application.yml:

    protokollierung: Niveau: com.example.logging: DEBUG

Option 3. Verwendung von httpcomponent

Importieren Sie die http-Komponentenabhängigkeit

<dependency>
  <groupId>org.Apache.httpcomponents</groupId>
  <artifactId>httpasyncclient</artifactId>

RestTemplate konfigurieren

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    RestTemplate restTemplate = builder.build();
    restTemplate.setRequestFactory(new HttpComponentsAsyncClientHttpRequestFactory());
    return restTemplate;
}

Protokollierung konfigurieren

  • Überprüfen Sie das Paket von LoggingRestTemplate, zum Beispiel in application.yml:

    protokollierung: Ebene: org.Apache.http: DEBUG

15
user2746033

Sie können spring-rest-template-logger verwenden, um RestTemplate HTTP-Verkehr zu protokollieren.

Fügen Sie Ihrem Maven-Projekt eine Abhängigkeit hinzu:

<dependency>
    <groupId>org.hobsoft.spring</groupId>
    <artifactId>spring-rest-template-logger</artifactId>
    <version>2.0.0</version>
</dependency>

Passen Sie dann Ihre RestTemplate wie folgt an:

RestTemplate restTemplate = new RestTemplateBuilder()
    .customizers(new LoggingCustomizer())
    .build()

Nun wird der gesamte RestTemplate-HTTP-Verkehr auf Debug-Ebene in org.hobsoft.spring.resttemplatelogger.LoggingCustomizer protokolliert.

HAFTUNGSAUSSCHLUSS: Ich habe diese Bibliothek geschrieben.

15
Mark Hobson

Neben der HttpClient-Protokollierung in der anderen Antwort können Sie auch einen ClientHttpRequestInterceptor einführen, der den Hauptteil der Anforderung und die Antwort liest und protokolliert. Möglicherweise möchten Sie dies tun, wenn andere Personen auch den HttpClient verwenden oder wenn Sie ein benutzerdefiniertes Protokollierungsformat wünschen. Achtung: Sie müssen RestTemplate eine BufferingClientHttpRequestFactory geben, sodass Sie die Antwort zweimal lesen können.

10

Angenommen, RestTemplate ist configure , um HttpClient 4.x zu verwenden, können Sie die Protokollierungsdokumentation von HttpClient hier lesen. Die Logger unterscheiden sich von den in den anderen Antworten angegebenen.

Die Protokollierungskonfiguration für HttpClient 3.x ist verfügbar here .

6

Dies ist möglicherweise nicht der richtige Weg, aber ich denke, dies ist der einfachste Ansatz, um Anforderungen und Antworten zu drucken, ohne zu viele Protokolle zu füllen.

Durch Hinzufügen von weniger als zwei Zeilen protokolliert application.properties alle Anforderungen und Antworten in der ersten Zeile, um die Anforderungen zu protokollieren, und in der zweiten Zeile, um die Antworten zu protokollieren.

logging.level.org.springframework.web.client.RestTemplate=DEBUGlogging.level.org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor=DEBUG

4
User9123

---- Juli 2019 ----

(mit Spring Boot)

Ich war überrascht, dass Spring Boot mit all seiner Zero Configuration-Magie keine einfache Möglichkeit bietet, einen einfachen JSON-Antworttext mit RestTemplate zu untersuchen oder zu protokollieren. Ich habe die verschiedenen Antworten und Kommentare hier durchgesehen und teile meine eigene destillierte Version von dem, was (noch) funktioniert und mir angesichts der aktuellen Optionen als vernünftige Lösung erscheint (ich verwende Spring Boot 2.1.6 mit Gradle 4.4) )

1. Verwenden von Fiddler als http-Proxy

Dies ist eigentlich eine recht elegante Lösung, da sie alle umständlichen Bemühungen umgeht, einen eigenen Interceptor zu erstellen oder den zugrunde liegenden http-Client auf Apache zu ändern (siehe unten).

Installiere und starte Fiddler

und dann

fügen Sie -DproxySet=true -Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888 zu Ihren VM Optionen hinzu

2. Verwenden von Apache HttpClient

Fügen Sie Ihren Maven- oder Gradle-Abhängigkeiten Apache HttpClient hinzu.

<dependency>
    <groupId>org.Apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.9</version>
</dependency>

Verwenden Sie HttpComponentsClientHttpRequestFactory als RequestFactory für RestTemplate. Der einfachste Weg dies zu tun wäre:

RestTemplate restTemplate = new RestTemplate();

restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

Aktiviere DEBUG in deiner application.properties Datei (wenn du Spring Boot verwendest)

logging.level.org.Apache.http=DEBUG

Wenn Sie Spring Boot verwenden, müssen Sie sicherstellen, dass ein Protokollierungsframework eingerichtet ist, z. durch Verwendung einer Spring-Boot-Starter-Abhängigkeit, die spring-boot-starter-logging enthält.

3. Verwenden Sie einen Interceptor

Ich lasse Sie die Vorschläge, Gegenvorschläge und Fallstricke in den anderen Antworten und Kommentaren durchlesen und entscheide selbst, ob Sie diesen Weg beschreiten möchten.

4. URL und Antwortstatus ohne Text protokollieren

Obwohl dies nicht den angegebenen Anforderungen für die Protokollierung des Körpers entspricht, können Sie auf schnelle und einfache Weise mit der Protokollierung Ihrer REST -Anrufe beginnen. Es zeigt die vollständige URL und den Antwortstatus an.

Fügen Sie einfach die folgende Zeile zu Ihrer application.properties -Datei hinzu (vorausgesetzt, Sie verwenden Spring Boot, und vorausgesetzt, Sie verwenden eine Spring Boot-Starter-Abhängigkeit, die spring-boot-starter-logging enthält).

logging.level.org.springframework.web.client.RestTemplate = DEBUG

Die Ausgabe sieht ungefähr so ​​aus:

2019-07-29 11:53:50.265 DEBUG o.s.web.client.RestTemplate : HTTP GET http://www.myrestservice.com/Endpoint?myQueryParam=myValue
2019-07-29 11:53:50.276 DEBUG o.s.web.client.RestTemplate : Accept=[application/json]
2019-07-29 11:53:50.584 DEBUG o.s.web.client.RestTemplate : Response 200 OK
2019-07-29 11:53:50.585 DEBUG o.s.web.client.RestTemplate : Reading to [org.mynamespace.MyJsonModelClass]
4
Chris

In Ergänzung zu der obigen Diskussion sind dies nur glückliche Szenarien. Wahrscheinlich können Sie die Antwort nicht protokollieren, wenn ein Fehler auftritt.

In diesem Fall plus alle oben genannten Fälle müssen Sie DefaultResponseErrorHandler überschreiben und wie folgt einstellen 

restTemplate.setErrorHandler(new DefaultResponseErrorHandlerImpl());
2
user666

Wie in den anderen Antworten angegeben, benötigt der Antwortkörper eine spezielle Behandlung, damit er wiederholt gelesen werden kann (standardmäßig wird sein Inhalt beim ersten Lesen verbraucht).

Anstatt die Variable BufferingClientHttpRequestFactory beim Einrichten der Anforderung zu verwenden, kann der Interceptor selbst die Antwort umbrechen und sicherstellen, dass der Inhalt erhalten bleibt und wiederholt gelesen werden kann (sowohl vom Logger als auch vom Benutzer der Antwort):

Mein Abfänger, welcher

  • puffert den Antworttext mit einem Wrapper
  • loggt sich kompakter
  • protokolliert auch den status code Bezeichner (z. B. 201 Created)
  • enthält eine request-Sequenznummer, mit der gleichzeitige Protokolleinträge von mehreren Threads unterschieden werden können

Code:

public class LoggingInterceptor implements ClientHttpRequestInterceptor {

    private final Logger log = LoggerFactory.getLogger(getClass());
    private AtomicInteger requestNumberSequence = new AtomicInteger(0);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        int requestNumber = requestNumberSequence.incrementAndGet();
        logRequest(requestNumber, request, body);
        ClientHttpResponse response = execution.execute(request, body);
        response = new BufferedClientHttpResponse(response);
        logResponse(requestNumber, response);
        return response;
    }

    private void logRequest(int requestNumber, HttpRequest request, byte[] body) {
        if (log.isDebugEnabled()) {
            String prefix = requestNumber + " > ";
            log.debug("{} Request: {} {}", prefix, request.getMethod(), request.getURI());
            log.debug("{} Headers: {}", prefix, request.getHeaders());
            if (body.length > 0) {
                log.debug("{} Body: \n{}", prefix, new String(body, StandardCharsets.UTF_8));
            }
        }
    }

    private void logResponse(int requestNumber, ClientHttpResponse response) throws IOException {
        if (log.isDebugEnabled()) {
            String prefix = requestNumber + " < ";
            log.debug("{} Response: {} {} {}", prefix, response.getStatusCode(), response.getStatusCode().name(), response.getStatusText());
            log.debug("{} Headers: {}", prefix, response.getHeaders());
            String body = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8);
            if (body.length() > 0) {
                log.debug("{} Body: \n{}", prefix, body);
            }
        }
    }

    /**
     * Wrapper around ClientHttpResponse, buffers the body so it can be read repeatedly (for logging & consuming the result).
     */
    private static class BufferedClientHttpResponse implements ClientHttpResponse {

        private final ClientHttpResponse response;
        private byte[] body;

        public BufferedClientHttpResponse(ClientHttpResponse response) {
            this.response = response;
        }

        @Override
        public HttpStatus getStatusCode() throws IOException {
            return response.getStatusCode();
        }

        @Override
        public int getRawStatusCode() throws IOException {
            return response.getRawStatusCode();
        }

        @Override
        public String getStatusText() throws IOException {
            return response.getStatusText();
        }

        @Override
        public void close() {
            response.close();
        }

        @Override
        public InputStream getBody() throws IOException {
            if (body == null) {
                body = StreamUtils.copyToByteArray(response.getBody());
            }
            return new ByteArrayInputStream(body);
        }

        @Override
        public HttpHeaders getHeaders() {
            return response.getHeaders();
        }
    }
}

Aufbau:

 @Bean
    public RestTemplateBuilder restTemplateBuilder() {
        return new RestTemplateBuilder()
                .additionalInterceptors(Collections.singletonList(new LoggingInterceptor()));
    }

Beispiel Log-Ausgabe:

2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 >  Request: POST http://localhost:53969/payment/v4/private/payment-lists/10022/templates
2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 >  Headers: {Accept=[application/json, application/*+json], Content-Type=[application/json;charset=UTF-8], Content-Length=[986]}
2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 >  Body: 
{"idKey":null, ...}
2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 <  Response: 200 OK 
2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 <  Headers: {Content-Type=[application/json;charset=UTF-8], Transfer-Encoding=[chunked], Date=[Mon, 08 Oct 2018 08:58:53 GMT]}
2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 <  Body: 
{ "idKey" : "10022", ...  }
2
Peter Walser

Seltsamerweise funktioniert keine dieser Lösungen, da RestTemplate die Antwort auf einige 500x-Fehler von Client und Server nicht zurückgibt. In diesem Fall müssen Sie auch diese protokollieren, indem Sie ResponseErrorHandler wie folgt implementieren. Hier ist ein Entwurfscode, aber Sie bekommen den Punkt:

Sie können denselben Interceptor wie der Fehlerbehandler festlegen:

restTemplate.getInterceptors().add(interceptor);
restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.setErrorHandler(interceptor);

Und der Intercept implementiert beide Schnittstellen:

import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;
import Java.util.HashSet;
import Java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus.Series;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.ResponseErrorHandler;

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor, ResponseErrorHandler {
    static final Logger log = LoggerFactory.getLogger(LoggingRequestInterceptor.class);
    static final DefaultResponseErrorHandler defaultResponseErrorHandler = new DefaultResponseErrorHandler();
    final Set<Series> loggableStatuses = new HashSet();

    public LoggingRequestInterceptor() {
    }

    public LoggingRequestInterceptor(Set<Series> loggableStatuses) {
        loggableStatuses.addAll(loggableStatuses);
    }

    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        this.traceRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        if(response != null) {
            this.traceResponse(response);
        }

        return response;
    }

    private void traceRequest(HttpRequest request, byte[] body) throws IOException {
        log.debug("===========================request begin================================================");
        log.debug("URI         : {}", request.getURI());
        log.debug("Method      : {}", request.getMethod());
        log.debug("Headers     : {}", request.getHeaders());
        log.debug("Request body: {}", new String(body, "UTF-8"));
        log.debug("==========================request end================================================");
    }

    private void traceResponse(ClientHttpResponse response) throws IOException {
        if(this.loggableStatuses.isEmpty() || this.loggableStatuses.contains(response.getStatusCode().series())) {
            StringBuilder inputStringBuilder = new StringBuilder();

            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), "UTF-8"));

                for(String line = bufferedReader.readLine(); line != null; line = bufferedReader.readLine()) {
                    inputStringBuilder.append(line);
                    inputStringBuilder.append('\n');
                }
            } catch (Throwable var5) {
                log.error("cannot read response due to error", var5);
            }

            log.debug("============================response begin==========================================");
            log.debug("Status code  : {}", response.getStatusCode());
            log.debug("Status text  : {}", response.getStatusText());
            log.debug("Headers      : {}", response.getHeaders());
            log.debug("Response body: {}", inputStringBuilder.toString());
            log.debug("=======================response end=================================================");
        }

    }

    public boolean hasError(ClientHttpResponse response) throws IOException {
        return defaultResponseErrorHandler.hasError(response);
    }

    public void handleError(ClientHttpResponse response) throws IOException {
        this.traceResponse(response);
        defaultResponseErrorHandler.handleError(response);
    }
}
2
kisna

Der Trick, Ihre RestTemplate mit einer BufferingClientHttpRequestFactory zu konfigurieren, funktioniert nicht, wenn Sie eine ClientHttpRequestInterceptor verwenden, was Sie tun, wenn Sie versuchen, sich über Interceptors anzumelden. Dies liegt an der Funktionsweise von InterceptingHttpAccessor (welche RestTemplate-Unterklassen).

Lange Geschichte, kurz ... Verwenden Sie diese Klasse anstelle von RestTemplate (beachten Sie, dass dies die SLF4J-Protokollierungs-API verwendet, bearbeiten Sie sie nach Bedarf):

import Java.io.ByteArrayOutputStream;
import Java.io.IOException;
import Java.io.InputStream;
import Java.lang.reflect.Constructor;
import Java.nio.charset.StandardCharsets;
import Java.util.List;
import Java.util.Map;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;

/**
 * A {@link RestTemplate} that logs every request and response.
 */
public class LoggingRestTemplate extends RestTemplate {

    // Bleh, this class is not public
    private static final String RESPONSE_WRAPPER_CLASS = "org.springframework.http.client.BufferingClientHttpResponseWrapper";

    private Logger log = LoggerFactory.getLogger(this.getClass());

    private boolean hideAuthorizationHeaders = true;
    private Class<?> wrapperClass;
    private Constructor<?> wrapperConstructor;

    /**
     * Configure the logger to log requests and responses to.
     *
     * @param log log destination, or null to disable
     */
    public void setLogger(Logger log) {
        this.log = log;
    }

    /**
     * Configure the logger to log requests and responses to by name.
     *
     * @param name name of the log destination, or null to disable
     */
    public void setLoggerName(String name) {
        this.setLogger(name != null ? LoggerFactory.getLogger(name) : null);
    }

    /**
     * Configure whether to hide the contents of {@code Authorization} headers.
     *
     * <p>
     * Default true.
     *
     * @param hideAuthorizationHeaders true to hide, otherwise false
     */
    public void setHideAuthorizationHeaders(boolean hideAuthorizationHeaders) {
        this.hideAuthorizationHeaders = hideAuthorizationHeaders;
    }

    /**
     * Log a request.
     */
    protected void traceRequest(HttpRequest request, byte[] body) {
        this.log.debug("xmit: {} {}\n{}{}", request.getMethod(), request.getURI(), this.toString(request.getHeaders()),
          body != null && body.length > 0 ? "\n\n" + new String(body, StandardCharsets.UTF_8) : "");
    }

    /**
     * Log a response.
     */
    protected void traceResponse(ClientHttpResponse response) {
        final ByteArrayOutputStream bodyBuf = new ByteArrayOutputStream();
        HttpStatus statusCode = null;
        try {
            statusCode = response.getStatusCode();
        } catch (IOException e) {
            // ignore
        }
        String statusText = null;
        try {
            statusText = response.getStatusText();
        } catch (IOException e) {
            // ignore
        }
        try (final InputStream input = response.getBody()) {
            byte[] b = new byte[1024];
            int r;
            while ((r = input.read(b)) != -1)
                bodyBuf.write(b, 0, r);
        } catch (IOException e) {
            // ignore
        }
        this.log.debug("recv: {} {}\n{}{}", statusCode, statusText, this.toString(response.getHeaders()),
          bodyBuf.size() > 0 ? "\n\n" + new String(bodyBuf.toByteArray(), StandardCharsets.UTF_8) : "");
    }

    @PostConstruct
    private void addLoggingInterceptor() {
        this.getInterceptors().add(new ClientHttpRequestInterceptor() {
            @Override
            public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
              throws IOException {

                // Log request
                if (LoggingRestTemplate.this.log != null && LoggingRestTemplate.this.log.isDebugEnabled())
                    LoggingRestTemplate.this.traceRequest(request, body);

                // Perform request
                ClientHttpResponse response = execution.execute(request, body);

                // Log response
                if (LoggingRestTemplate.this.log != null && LoggingRestTemplate.this.log.isDebugEnabled()) {
                    final ClientHttpResponse bufferedResponse = LoggingRestTemplate.this.ensureBuffered(response);
                    if (bufferedResponse != null) {
                        LoggingRestTemplate.this.traceResponse(bufferedResponse);
                        response = bufferedResponse;
                    }
                }

                // Done
                return response;
            }
        });
    }

    private ClientHttpResponse ensureBuffered(ClientHttpResponse response) {
        try {
            if (this.wrapperClass == null)
                this.wrapperClass = Class.forName(RESPONSE_WRAPPER_CLASS, false, ClientHttpResponse.class.getClassLoader());
            if (!this.wrapperClass.isInstance(response)) {
                if (this.wrapperConstructor == null) {
                    this.wrapperConstructor = this.wrapperClass.getDeclaredConstructor(ClientHttpResponse.class);
                    this.wrapperConstructor.setAccessible(true);
                }
                response = (ClientHttpResponse)this.wrapperConstructor.newInstance(response);
            }
            return response;
        } catch (Exception e) {
            this.log.error("error creating {} instance: {}", RESPONSE_WRAPPER_CLASS, e);
            return null;
        }
    }

    private String toString(HttpHeaders headers) {
        final StringBuilder headerBuf = new StringBuilder();
        for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
            if (headerBuf.length() > 0)
                headerBuf.append('\n');
            final String name = entry.getKey();
            for (String value : entry.getValue()) {
                if (this.hideAuthorizationHeaders && name.equalsIgnoreCase(HttpHeaders.AUTHORIZATION))
                    value = "[omitted]";
                headerBuf.append(name).append(": ").append(value);
            }
        }
        return headerBuf.toString();
    }
}

Ich stimme zu, dass es dumm ist, dass es so viel Arbeit kostet, nur um das zu tun.

2
Archie

So viele Antworten erfordern Codierungsänderungen und angepasste Klassen, und dies ist wirklich nicht erforderlich. Rufen Sie einen Debugging-Proxy (z. B. fiddler) auf und konfigurieren Sie Ihre Java-Umgebung so, dass der Proxy in der Befehlszeile (-Dhttp.proxyHost und -Dhttp.proxyPort) verwendet wird. Führen Sie dann Fiddler aus, und Sie können die Anforderungen und Antworten vollständig anzeigen. Sie bietet auch viele zusätzliche Vorteile, z. B. die Möglichkeit, die Ergebnisse und Antworten vor und nach deren Versendung zu basteln, um Experimente auszuführen, bevor sie sich zur Änderung des Servers verpflichten.

Das letzte Problem, das auftreten kann, ist, wenn Sie HTTPS verwenden müssen. Sie müssen das SSL-Zertifikat von fiddler exportieren und in den Java-Keystore (cacerts) importieren. Hinweis: Das standardmäßige Java-Keystore-Kennwort ist normalerweise "changeit".

1
Lee Burch

benutzen:

application.properties { logging.level.org.springframework.web.client=DEBUG }

oder YAML

application.yml { logging: level:
root: WARN org.springframework.web.client: DEBUG }

1
Elton Sandré

Informationen zum Protokollieren der Anforderung und der Antwort für die Restvorlage finden Sie in den Fragen und Antworten, indem Sie mehrere Lesevorgänge für HttpInputStream aktivieren

Warum mein benutzerdefinierter ClientHttpRequestInterceptor mit leerer Antwort

0
maya16

Wie @MilacH darauf hingewiesen hat, liegt ein Fehler in der Implementierung vor. Wenn ein statusCode> 400 zurückgegeben wird, wird eine IOException ausgelöst, da der errorHandler nicht von Interceptors aufgerufen wird. Die Ausnahme kann ignoriert werden und wird dann erneut in der Handler-Methode abgefangen.

package net.sprd.fulfillment.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;

import static Java.nio.charset.StandardCharsets.UTF_8;

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {

    final static Logger log = LoggerFactory.getLogger(LoggingRequestInterceptor.class);

    @SuppressWarnings("HardcodedLineSeparator")
    public static final char LINE_BREAK = '\n';

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        try {
            traceRequest(request, body);
        } catch (Exception e) {
            log.warn("Exception in LoggingRequestInterceptor while tracing request", e);
        }

        ClientHttpResponse response = execution.execute(request, body);

        try {
            traceResponse(response);
        } catch (IOException e) {
            // ignore the exception here, as it will be handled by the error handler of the restTemplate
            log.warn("Exception in LoggingRequestInterceptor", e);
        }
        return response;
    }

    private void traceRequest(HttpRequest request, byte[] body) {
        log.info("===========================request begin================================================");
        log.info("URI         : {}", request.getURI());
        log.info("Method      : {}", request.getMethod());
        log.info("Headers     : {}", request.getHeaders());
        log.info("Request body: {}", new String(body, UTF_8));
        log.info("==========================request end================================================");
    }

    private void traceResponse(ClientHttpResponse response) throws IOException {
        StringBuilder inputStringBuilder = new StringBuilder();
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), UTF_8))) {
            String line = bufferedReader.readLine();
            while (line != null) {
                inputStringBuilder.append(line);
                inputStringBuilder.append(LINE_BREAK);
                line = bufferedReader.readLine();
            }
        }

        log.info("============================response begin==========================================");
        log.info("Status code  : {}", response.getStatusCode());
        log.info("Status text  : {}", response.getStatusText());
        log.info("Headers      : {}", response.getHeaders());
        log.info("Response body: {}", inputStringBuilder);
        log.info("=======================response end=================================================");
    }

}
0
Tony Findeisen

Wollte meine Implementierung auch hinzufügen. Ich entschuldige mich für die fehlenden Semikolons, dies ist in Groovy geschrieben. 

Ich brauchte etwas Konfigurierbareres als die akzeptierte Antwort. Hier ist eine Restvorlagen-Bean, die sehr agil ist und alles protokolliert, wie es das OP sucht.

Benutzerdefinierte Protokollierungs-Interceptor-Klasse:

import org.springframework.http.HttpRequest
import org.springframework.http.client.ClientHttpRequestExecution
import org.springframework.http.client.ClientHttpRequestInterceptor
import org.springframework.http.client.ClientHttpResponse
import org.springframework.util.StreamUtils

import Java.nio.charset.Charset

class HttpLoggingInterceptor implements ClientHttpRequestInterceptor {

    private final static Logger log = LoggerFactory.getLogger(HttpLoggingInterceptor.class)

    @Override
    ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        logRequest(request, body)
        ClientHttpResponse response = execution.execute(request, body)
        logResponse(response)
        return response
    }

    private void logRequest(HttpRequest request, byte[] body) throws IOException {
        if (log.isDebugEnabled()) {
            log.debug("===========================request begin================================================")
            log.debug("URI         : {}", request.getURI())
            log.debug("Method      : {}", request.getMethod())
            log.debug("Headers     : {}", request.getHeaders())
            log.debug("Request body: {}", new String(body, "UTF-8"))
            log.debug("==========================request end================================================")
        }
    }

    private void logResponse(ClientHttpResponse response) throws IOException {
        if (log.isDebugEnabled()) {
            log.debug("============================response begin==========================================")
            log.debug("Status code  : {}", response.getStatusCode())
            log.debug("Status text  : {}", response.getStatusText())
            log.debug("Headers      : {}", response.getHeaders())
            log.debug("Response body: {}", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()))
            log.debug("=======================response end=================================================")
        }
    }
}

Rest Template Bean Definition:

@Bean(name = 'myRestTemplate')
RestTemplate myRestTemplate(RestTemplateBuilder builder) {

    RequestConfig requestConfig = RequestConfig.custom()
            .setConnectTimeout(10 * 1000) // 10 seconds
            .setSocketTimeout(300 * 1000) // 300 seconds
            .build()

    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager()
    connectionManager.setMaxTotal(10)
    connectionManager.closeIdleConnections(5, TimeUnit.MINUTES)

    CloseableHttpClient httpClient = HttpClients.custom()
            .setConnectionManager(connectionManager)
            .setDefaultRequestConfig(requestConfig)
            .disableRedirectHandling()
            .build()

    RestTemplate restTemplate = builder
            .rootUri("https://domain.server.com")
            .basicAuthorization("username", "password")
            .requestFactory(new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient)))
            .interceptors(new HttpLoggingInterceptor())
            .build()

    return restTemplate
}

Implementierung:

@Component
class RestService {

    private final RestTemplate restTemplate
    private final static Logger log = LoggerFactory.getLogger(RestService.class)

    @Autowired
    RestService(
            @Qualifier("myRestTemplate") RestTemplate restTemplate
    ) {
        this.restTemplate = restTemplate
    }

    // add specific methods to your service that access the GET and PUT methods

    private <T> T getForObject(String path, Class<T> object, Map<String, ?> params = [:]) {
        try {
            return restTemplate.getForObject(path, object, params)
        } catch (HttpClientErrorException e) {
            log.warn("Client Error (${path}): ${e.responseBodyAsString}")
        } catch (HttpServerErrorException e) {
            String msg = "Server Error (${path}): ${e.responseBodyAsString}"
            log.error(msg, e)
        } catch (RestClientException e) {
            String msg = "Error (${path})"
            log.error(msg, e)
        }
        return null
    }

    private <T> T putForObject(String path, T object) {
        try {
            HttpEntity<T> request = new HttpEntity<>(object)
            HttpEntity<T> response = restTemplate.exchange(path, HttpMethod.PUT, request, T)
            return response.getBody()
        } catch (HttpClientErrorException e) {
            log.warn("Error (${path}): ${e.responseBodyAsString}")
        } catch (HttpServerErrorException e) {
            String msg = "Error (${path}): ${e.responseBodyAsString}"
            log.error(msg, e)
        } catch (RestClientException e) {
            String msg = "Error (${path})"
            log.error(msg, e)
        }
        return null
    }
}
0
Jason Slobotski

Beste Lösung jetzt, fügen Sie einfach Abhängigkeit hinzu:

<dependency>
  <groupId>com.github.zg2pro</groupId>
  <artifactId>spring-rest-basis</artifactId>
  <version>v.x</version>
</dependency>

Es enthält eine LoggingRequestInterceptor-Klasse, die Sie so zu Ihrem RestTemplate hinzufügen können:

integrieren Sie dieses Dienstprogramm, indem Sie es auf folgende Weise als Abfangjäger zu einer Spring RestTemplate hinzufügen:

restTemplate.setRequestFactory(LoggingRequestFactoryFactory.build());

und fügen Sie Ihrem Framework eine slf4j-Implementierung hinzu, beispielsweise log4j.

oder direkt "Zg2proRestTemplate" verwenden. Die "beste Antwort" von @PaulSabou sieht also so aus, da httpclient und alle Apache.http-Bibliotheken nicht unbedingt geladen werden, wenn ein Spring-RestTemplate verwendet wird.

0
Moses Meyer