स्प्रिंग रेस्टेमप्लेट - अनुरोधों / प्रतिक्रियाओं के पूर्ण डिबगिंग / लॉगिंग को कैसे सक्षम किया जाए?


220

मैं थोड़ी देर के लिए स्प्रिंग रेस्टेमप्लेट का उपयोग कर रहा हूं और मैं लगातार एक दीवार से टकराता हूं जब आईमैम डीबग करने की कोशिश कर रहा है, यह अनुरोध और प्रतिक्रियाएं हैं। मैं मूल रूप से उन्हीं चीजों को देखना चाह रहा हूं जैसा कि मैं देखता हूं जब मैं "वर्बोज़" विकल्प के साथ कर्ल का उपयोग करता हूं। उदाहरण के लिए :

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

भेजे गए डेटा और प्राप्त डेटा (हेडर, कुकीज़, आदि सहित) दोनों को प्रदर्शित करेगा।

मैंने कुछ संबंधित पोस्ट की जाँच की है जैसे: मैं स्प्रिंग रेस्टप्लेट में कैसे प्रतिक्रिया दर्ज करूं? लेकिन मैं इस मुद्दे को हल करने में कामयाब नहीं हुआ।

ऐसा करने का एक तरीका वास्तव में रेस्टेमप्लेट स्रोत कोड को बदलना और वहां कुछ अतिरिक्त लॉगिंग स्टेटमेंट जोड़ना होगा, लेकिन मुझे यह दृष्टिकोण वास्तव में एक अंतिम उपाय लगेगा। स्प्रिंग वेब क्लाइंट / रेस्टेमप्लेट को यह बताने के लिए कोई रास्ता होना चाहिए कि वह सब कुछ बहुत ही मैत्रीपूर्ण तरीके से लॉग इन करे।

मेरा लक्ष्य कोड के साथ ऐसा करने में सक्षम होगा:

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

और फिर लॉग फ़ाइल में या कंसोल में उसी प्रकार की डिबग जानकारी (जैसा कि मुझे कर्ल के साथ मिलती है) प्राप्त करने के लिए। मेरा मानना ​​है कि यह किसी के लिए भी बहुत उपयोगी होगा जो स्प्रिंग रेस्टेमप्लेट का उपयोग करता है और इसमें समस्याएं हैं। अपने RestTemplate समस्याओं को डीबग करने के लिए कर्ल का उपयोग करना बस काम नहीं करता है (कुछ मामलों में)।


31
2018 में पढ़ने वाले किसी को भी चेतावनी: इसका सरल उत्तर नहीं है!
डेविडफ्रैंसिस

3
सबसे आसान तरीका है AbstractHttpMessageConverter वर्ग के लिखित (...) विधि में एक ब्रेकप्वाइंट का उपयोग करना, एक आउटपुटमैसेज ऑब्जेक्ट है जहां आप डेटा देख सकते हैं। PS आप मान की प्रतिलिपि बना सकते हैं और फिर उसे ऑनलाइन फ़ॉर्मेटर से प्रारूपित कर सकते हैं।
सर्गेई चेपर्नोव

1
ऐसा लगता है कि स्प्रिंग में ऐसा करना आसान होना चाहिए, लेकिन, यहां के जवाबों को देखते हुए - ऐसा नहीं है। इसलिए एक अन्य उपाय, स्प्रिंग को पूरी तरह से बायपास करना होगा और रिक्वेस्ट / रिस्पॉन्स को कैप्चर करने के लिए फिडलर जैसे टूल का उपयोग करना होगा।
माइकल फॉक


जुलाई 2019: जैसा कि इस प्रश्न का कोई सरल समाधान नहीं है, मैंने नीचे दिए गए अपने स्वयं के उत्तर में अन्य 24 उत्तरों (अब तक) और उनकी टिप्पणियों और चर्चाओं का सारांश देने की कोशिश की । आशा करता हूँ की ये काम करेगा।
क्रिस

जवाबों:


207

ClientHttpRequestInterceptorअनुरोध और प्रतिक्रिया का पता लगाने के पूर्ण कार्यान्वयन के साथ उदाहरण को पूरा करने के लिए:

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=================================================");
    }

}

तो और RestTemplateएक का उपयोग कर तुरंत :BufferingClientHttpRequestFactoryLoggingRequestInterceptor

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

यह BufferingClientHttpRequestFactoryआवश्यक है क्योंकि हम दोनों प्रतिक्रिया बॉडी को इंटरसेप्टर में और प्रारंभिक कॉलिंग कोड के लिए उपयोग करना चाहते हैं। डिफ़ॉल्ट कार्यान्वयन केवल एक बार प्रतिक्रिया निकाय को पढ़ने की अनुमति देता है।


27
ये गलत है। यदि आप स्ट्रीम पढ़ते हैं, तो एप्लिकेशन कोड प्रतिक्रिया को पढ़ने में सक्षम नहीं होगा।
जेम्स वाटकिंस

28
हमने RestTemplate को एक BufferingClientHttpRequestFactory दिया है ताकि हम दो बार प्रतिक्रिया पढ़ सकें।
सोफिन ज़गहदौदी

16
हम इस तकनीक का उपयोग लगभग 3 महीने से कर रहे हैं। यह केवल @ asofienezaghdoudi के साथ कॉन्फ़िगर किए गए RestTemplate के साथ काम करता BufferingClientHttpResponseWrapperहै। हालाँकि, यह तब काम नहीं करता है जब अनुरोध के MockRestServiceServer.createServer(restTemplate)ओवरराइट को अधिलेखित करने के बाद से स्प्रिंग के मॉकसर्वर ढांचे का उपयोग करके परीक्षणों में उपयोग किया जाता है InterceptingClientHttpRequestFactory
RubesMN

8
तकनीक अच्छी है, कार्यान्वयन गलत है। 404 मामला, प्रतिक्रिया .getBody () IOException को फेंक दें -> आपको कभी भी लॉग आउट नहीं करना चाहिए और यहां तक ​​कि सबसे खराब, यह आपके आगे के कोड में रिसोर्सएक्स्टसेप्शन बन जाएगा, इसके बजाय एक RestClientResponseException
MilhH

6
उत्तर के लिए धन्यवाद। लेकिन यह कई "log.debug" होने के लिए बुरा अभ्यास है क्योंकि यह कई अन्य लॉग में फैल सकता है। किसी एकल log.debug निर्देश का उपयोग करना बेहतर है, ताकि आप सुनिश्चित करें कि सब कुछ एक ही स्थान पर है
user2447161

128

स्प्रिंग बूट में आप इसे गुणों (या अन्य 12 कारक विधि) में स्थापित करके पूर्ण अनुरोध / प्रतिक्रिया प्राप्त कर सकते हैं

logging.level.org.apache.http=DEBUG

यह आउटपुट है

-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":"xenoterracide@gmail.com","new":true}"

और प्रतिक्रिया

-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":"xenoterracide@gmail.com","new":true}"

या बस logging.level.org.apache.http.wire=DEBUGजो प्रासंगिक जानकारी के सभी शामिल लगता है


4
यह सबसे आसान काम था जो मैंने किया था। मैं स्वीकृत उत्तर में इसे शामिल करने के लिए अत्यधिक प्रोत्साहित करता हूं।
माइकलविल्ला

22
RestTemplate के javadoc के अनुसार :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
Ortomala Lokni

22
RestTemplate इन अपाचे कक्षाओं का उपयोग डिफ़ॉल्ट रूप से नहीं करता है, जैसा कि @OrtomalaLokni द्वारा बताया गया है, इसलिए आपको यह भी शामिल करना चाहिए कि उनका उपयोग कैसे किया जाए, इसके अलावा डीबग को प्रिंट करने के लिए कैसे उनका उपयोग किया जा रहा है।
कैप्टन मैन

मैं इस तरह से हो रहा हूं:http-outgoing-0 << "[0x1f][0x8b][0x8][0x0][0x0][0x0][0x0][0x0]
पार्थ सारथी घोष

2
@ParthaSarathiGhosh सामग्री संभवतः gzip एन्कोडेड है जिसके कारण आप कच्चा पाठ नहीं देख रहे हैं।
मैथ्यू बकेट

80

कुछ कोड के साथ @hstoerr का उत्तर देना:


अनुरोध प्रतिक्रियाएं लॉग करने के लिए LoggingRequestInterceptor बनाएं

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

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());

यह वसंत-3.1 संस्करण तक उपलब्ध नहीं है।
ज्ञान

3
यह 'लॉगिंग प्रतिक्रिया' के प्रश्न का उत्तर नहीं देता है, लेकिन इसके बजाय // लॉगिंग टिप्पणी को छोड़ दें।
जियांग वाईडी

1
लॉगिंग करना आसान था, लेकिन यह केवल अनुरोधों के लिए काम करता है, मैं प्रतिक्रिया निकायों को नहीं देखता, मान लीजिए कि मेरे पास प्रतिक्रिया ऑब्जेक्ट है, लेकिन यह स्ट्रीम पढ़ना अच्छा विचार नहीं है।
पावेल निदोबा

11
@PavelNiedoba दी बफ़ररिएंटहेटप्रेस्परेस्टफ़ेक्टरी प्रतिक्रिया को एक से अधिक बार पढ़ने की अनुमति देता है।
mjj1409

2
यह अच्छी तरह से काम करता है अगर आपको डिबगिंग के लिए डेटाबेस में अनुरोध / प्रतिक्रिया के बारे में जानकारी संग्रहीत करने की आवश्यकता है और नियमित लॉगिंग आपकी आवश्यकताओं के अनुरूप नहीं है।
गेमशूट्स

32

आपकी सबसे अच्छी शर्त फाइल में जोड़ना logging.level.org.springframework.web.client.RestTemplate=DEBUGहै application.properties

सेटिंग जैसे अन्य समाधान log4j.logger.httpclient.wireहमेशा काम नहीं करेंगे क्योंकि वे मानते हैं कि आप उपयोग करते हैं log4jऔर अपाचे HttpClient, जो हमेशा सच नहीं होता है।

हालाँकि, ध्यान दें कि यह सिंटैक्स केवल स्प्रिंग बूट के नवीनतम संस्करणों पर काम करेगा।


5
यह अनुरोध और प्रतिक्रिया निकाय में प्रवेश नहीं कर रहा है, बस url और अनुरोध प्रकार (वसंत-वेब-4.2.6)
dve

1
आप सही हैं, यह एक wireलॉगिंग नहीं है , इसमें केवल आवश्यक जानकारी जैसे url, resepone code, POST पैरामीटर आदि शामिल हैं
gamliela

1
वास्तव में आप क्या चाहते हैं यह stackoverflow.com/a/39109538/206466
xenoterracide

यह ठीक है, लेकिन प्रतिक्रिया शरीर नहीं देखा जा सकता है!
सूर्यदेव

प्रतिभाशाली। हालाँकि यह प्रतिक्रिया निकाय को प्रिंट नहीं करता है, फिर भी यह बहुत उपयोगी है। धन्यवाद।
क्रिस

30

इन उत्तरों में से कोई भी वास्तव में 100% समस्या का समाधान नहीं करता है। mjj1409 को इसमें से अधिकांश मिलता है, लेकिन प्रतिक्रिया को लॉग करने के मुद्दे से आसानी से बचा जाता है, जो थोड़ा अधिक काम लेता है। पॉल सबौ एक ऐसा समाधान प्रदान करता है जो यथार्थवादी लगता है, लेकिन वास्तव में लागू करने के लिए पर्याप्त विवरण प्रदान नहीं करता है (और यह मेरे लिए बिल्कुल भी काम नहीं करता है)। सोफिन को लॉगिंग मिल गई लेकिन एक महत्वपूर्ण समस्या के साथ: प्रतिक्रिया अब पढ़ने योग्य नहीं है क्योंकि इनपुट स्ट्रीम पहले ही भस्म हो चुकी है!

मैं एक बफरिंग क्लस्टरिएंट HttpResponseWrapper का उपयोग करने की सलाह देता हूं ताकि रिस्पांस बॉडी को पढ़ने की अनुमति देने के लिए प्रतिक्रिया ऑब्जेक्ट को कई बार लपेटें:

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;
    }

}

यह InputStream का उपभोग नहीं करेगा क्योंकि प्रतिक्रिया बॉडी को मेमोरी में लोड किया जाता है और कई बार पढ़ा जा सकता है। यदि आपके पास अपने Classpath पर BufferingClientHttpResponseWrapper नहीं है, तो आप यहाँ साधारण कार्यान्वयन पा सकते हैं:

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

RestTemplate की स्थापना के लिए:

LoggingRequestInterceptor loggingInterceptor = new LoggingRequestInterceptor();
restTemplate.getInterceptors().add(loggingInterceptor);

404 के मामले में एक ही, responseCopy.getBody () IOexception को फेंक दें, ताकि आप कभी भी अपने आगे के कोड को प्रतिक्रिया न भेजें और सामान्य रूप से RestClientResponseException रिसोर्सअसेस्टसेप्शन बन
जाएं

1
आपको status==200पहले देखना चाहिएresponseCopy.getBody()
आनंद रॉकज़

4
लेकिन यह पैकेज-प्राइवेट है। क्या आपने पैकेज 'org.springframework.http.client' में अपना LoggingRequestInterceptor डाला?
zbstof

2
किस बारे में asyncRestTemplate? ListenableFutureजब आप इसे रोकते हैं तो इसे वापस करना होगा, जिसे BufferingClientHttpResponseWrapperकॉलबैक में बदलना संभव नहीं है ।
मर फारुक अल्लम

@ ThatmerFarukAlmalı उस मामले में आपको अमरूद के संस्करण के आधार पर चेन या ट्रांसफॉर्मेशन का उपयोग करना होगा। देखें: stackoverflow.com/questions/8191891/…
जेम्स वाटकिंस

30

HTTP ट्रैफ़िक लॉग करने के लिए आप स्प्रिंग-रेस्ट-टेम्प्लेट-लॉगर का उपयोग कर सकते हैं RestTemplate

अपने मावेन प्रोजेक्ट पर निर्भरता जोड़ें:

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

फिर अपना RestTemplateनिम्न प्रकार से अनुकूलित करें :

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

सुनिश्चित करें कि डीबग लॉगिंग सक्षम है application.properties:

logging.level.org.hobsoft.spring.resttemplatelogger.LoggingCustomizer = DEBUG

अब सभी RestTemplate HTTP ट्रैफ़िक को org.hobsoft.spring.resttemplatelogger.LoggingCustomizerडीबग स्तर पर लॉग इन किया जाएगा ।

अस्वीकरण: मैंने यह पुस्तकालय लिखा है।


यह उत्तर क्यों अस्वीकृत है? इसने मेरी मदद की। धन्यवाद, @ मर्क हॉब्सन
राफेल बेचेरा रमेह

3
खुशी है कि इसने @RaffaelBecharaRameh की मदद की। शुरू में इसे डाउनवोट किया गया था क्योंकि मैंने लिंक किए गए प्रोजेक्ट से निर्देश एम्बेड नहीं किए थे। यदि आप इसे उपयोगी पाते हैं तो उत्थान करने के लिए स्वतंत्र महसूस करें!
मार्क होबसन

क्या आप ग्रैडल के माध्यम से समर्थन करते हैं?
ब्लैकहैटसमुरी

1
@BlackHatSamurai वसंत-बाकी-टेम्पलेट-लकड़हारा एक नियमित मावेन विरूपण साक्ष्य है, इसलिए इसे ग्रैडल के साथ ठीक काम करना चाहिए।
मार्क हॉसन

1
हाय @erhanasikoglu, आपका स्वागत है! यह सही है, आप इसे यहाँ उपयोग में देख सकते हैं: github.com/markhobson/spring-rest-template-logger/blob/master/…
मार्क होब्सन

29

उपयोग करने के लिए xenoterracide द्वारा दिया गया समाधान

logging.level.org.apache.http=DEBUG

अच्छा है लेकिन समस्या यह है कि डिफ़ॉल्ट रूप से Apache HttpCompords का उपयोग नहीं किया जाता है।

अपाचे HttpCompords का उपयोग करने के लिए अपने pom.xml में जोड़ें

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

और इसके RestTemplateसाथ कॉन्फ़िगर करें:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsAsyncClientHttpRequestFactory());

सबसे आसान तरीका, मैं केवल यह जोड़ूंगा कि यह MockRestServiceServer के साथ काम नहीं करता है, क्योंकि यह अनुरोध को ओवरराइट करता है।
zbstof

अच्छी तरह से काम कर रहा है और कम विन्यास कोई समस्या नहीं है!
सनलेओ

26

मुझे अंत में इसे सही तरीके से करने का एक तरीका मिला। अधिकांश समाधान यह आता है कि मैं स्प्रिंग और SLF4J को कैसे कॉन्फ़िगर करूं ताकि मुझे लॉगिंग मिल सके?

ऐसा लगता है कि दो काम करने की ज़रूरत है:

  1. Log4j.properties में निम्न पंक्ति जोड़ें: log4j.logger.httpclient.wire=DEBUG
  2. सुनिश्चित करें कि वसंत आपके लॉगिंग कॉन्फ़िगरेशन को अनदेखा नहीं करता है

दूसरा मुद्दा ज्यादातर वसंत के वातावरण में होता है जहां स्लफ 4 जे का उपयोग किया जाता है (क्योंकि यह मेरा मामला था)। जैसे कि, जब slf4j का उपयोग किया जाता है, तो सुनिश्चित करें कि निम्नलिखित दो चीजें होती हैं:

  1. आपके क्लासपाथ में कोई कॉमन्स-लॉगिंग लाइब्रेरी नहीं है: यह आपके पीपी में अपवर्जन विवरणकर्ताओं को जोड़कर किया जा सकता है:

            <exclusions><exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
  2. Log4j.properties फ़ाइल को क्लासपाथ में कहीं संग्रहीत किया जाता है जहां वसंत इसे ढूंढ / देख सकता है। यदि आपको इससे कोई समस्या है, तो एक अंतिम उपाय समाधान log4j.properties फ़ाइल को डिफ़ॉल्ट पैकेज में रखना होगा (एक अच्छा अभ्यास नहीं है, लेकिन यह देखने के लिए कि चीजें आपकी अपेक्षा के अनुरूप काम करती हैं)


7
यह मेरे लिए काम नहीं करता है, मैंने दोनों चीजें कीं। मुझे समझ नहीं आ रहा है कि मुझे अपने प्रोजेक्ट में वैसे भी लॉग 4j.properties क्यों डालने की जरूरत नहीं है (जब mvan निर्भरता द्वारा जाँच की जाती है: पेड़)
Pavel Niedoba

यह मेरे लिए भी काम नहीं करता है। मैंने रूट डिबगर को डिबग मोड में सेट करने की भी कोशिश की और अभी भी कुछ भी नहीं।
जेम्स वाटकिंस

"httpclient.wire.content" और "httpclient.wire.header" Axis2 ढांचे से लकड़हारा नाम हैं। यदि वे Axis2 का उपयोग कर रहे हैं, तो स्प्रिंग प्रोजेक्ट में SOAP अनुरोधों को लॉग इन करने के लिए उनका उपयोग किया जा सकता है ।
लाथस्पेल

11
httpclient.wireवास्तव में अपाचे HttpCompords HttpClient लाइब्रेरी से है (देखें hc.apache.org/httpcompenders-client-ga/log.html )। यह तकनीक केवल तभी काम करेगी जब आपने RestTemplateHttpComponentsClientHttpRequestFactory
स्कॉट फ्रेडरिक

22

लॉगिंग रिस्टेमप्लेट

विकल्प 1. ओपन डिबग लॉगिंग।

RestTemplate कॉन्फ़िगर करें

  • डिफ़ॉल्ट रूप से RestTemplate HTTP कनेक्शन स्थापित करने के लिए मानक JDK सुविधाओं पर निर्भर करता है। आप एक अलग HTTP लाइब्रेरी का उपयोग करने के लिए स्विच कर सकते हैं जैसे Apache HttpCompords

    @Bean public RestTemplate restTemplate (RestTemplateBuilder बिल्डर) {RestTemplate restTemplate = buildder.build (); वापसी restTemplate; }

लॉगिंग कॉन्फ़िगर करें

  • application.yml

    लॉगिंग: स्तर: org.springframework.web.client.RestTemplate: DEBUG

विकल्प 2. इंटरसेप्टर का उपयोग करना

रैपर प्रतिक्रिया

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();
    }
}

इंटरसेप्टर को लागू करें

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 कॉन्फ़िगर करें

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

लॉगिंग कॉन्फ़िगर करें

  • उदाहरण के लिए, LoggingRestTemplate के पैकेज की जाँच करें application.yml:

    लॉगिंग: स्तर: com.example.log: DEBUG

विकल्प 3. httpcomponent का उपयोग करना

आयात httpcomponent निर्भरता

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

RestTemplate कॉन्फ़िगर करें

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

लॉगिंग कॉन्फ़िगर करें

  • उदाहरण के लिए, LoggingRestTemplate के पैकेज की जाँच करें application.yml:

    लॉगिंग: स्तर: org.apache.http: DEBUG


बस ध्यान दें: यदि आप कॉन्फ़िगर करना चाहते हैं TestRestTemplate, तो कॉन्फ़िगर करें RestTemplateBuilder: @Bean सार्वजनिक RestTemplateBuilder restTemplateBuilder () {नया RestTemplateBuilder () लौटें। अतिरिक्तInterceptors (Collections.singletonList (नया LoggingRestTemplate ()))); }
किंगोलेग

यह भी ध्यान दें कि नया InputStreamReader (responseWrapper.getBody (), StandardCharsets.UTF_8)); यदि "अन्य छोर" में कोई त्रुटि दी गई है, तो एक त्रुटि फेंक सकते हैं। आप इसे एक कोशिश ब्लॉक में रखना चाह सकते हैं।
पीटर

16

---- जुलाई २०१ ९ ----

(स्प्रिंग बूट का उपयोग करके)

मुझे आश्चर्य हुआ कि स्प्रिंग बूट, यह सब शून्य विन्यास जादू के साथ है, रेस्टटेम्पलेट के साथ एक साधारण JSON प्रतिक्रिया निकाय का निरीक्षण या लॉग इन करने का आसान तरीका प्रदान नहीं करता है। मैंने यहां प्रदान किए गए विभिन्न उत्तरों और टिप्पणियों को देखा, और अपने स्वयं के आसुत संस्करण को साझा कर रहा हूं कि क्या (अभी भी) काम करता है और मुझे एक उचित समाधान की तरह लगता है, वर्तमान विकल्पों को देखते हुए (मैं स्प्रिंग बूट 2.1.6 का उपयोग ग्रेडल 4.4 के साथ कर रहा हूं) )

1. http प्रॉक्सी के रूप में फ़िडलर का उपयोग करना

यह वास्तव में काफी सुरुचिपूर्ण समाधान है, क्योंकि यह आपके स्वयं के इंटरसेप्टर बनाने या अंतर्निहित http क्लाइंट को अपाचे में बदलने के सभी बोझिल प्रयासों को दरकिनार कर देता है (नीचे देखें)।

Fiddler स्थापित करें और चलाएं

और फिर

-DproxySet=true -Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888अपने VM विकल्प में जोड़ें

2. Apache HttpClient का उपयोग करना

Apache HttpClient को अपने Maven या Gradle निर्भरता में जोड़ें।

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

HttpComponentsClientHttpRequestFactoryRestTemplate के लिए RequestFactory के रूप में उपयोग करें । ऐसा करने का सबसे सरल तरीका होगा:

RestTemplate restTemplate = new RestTemplate();

restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

अपनी application.propertiesफ़ाइल में DEBUG सक्षम करें (यदि आप स्प्रिंग बूट का उपयोग कर रहे हैं)

logging.level.org.apache.http=DEBUG

यदि आप स्प्रिंग बूट का उपयोग कर रहे हैं, तो आपको यह सुनिश्चित करना होगा कि आपके पास एक लॉगिंग ढाँचा स्थापित है, जैसे कि स्प्रिंग-बूट-स्टार्टर निर्भरता का उपयोग करके spring-boot-starter-logging

3. एक इंटरसेप्टर का उपयोग करें

मैं आपको अन्य उत्तरों और टिप्पणियों में प्रस्तावों, काउंटर-प्रस्तावों और गोचरों के माध्यम से पढ़ने दूंगा और यदि आप उस रास्ते से नीचे जाना चाहते हैं तो अपने लिए निर्णय लें।

4. लॉग बॉडी के बिना URL और रिस्पॉन्स स्टेटस

यद्यपि यह शरीर को लॉग करने की बताई गई आवश्यकताओं को पूरा नहीं करता है, यह आपके REST कॉल को लॉग करना शुरू करने का एक त्वरित और सरल तरीका है। यह पूर्ण URL और प्रतिक्रिया की स्थिति प्रदर्शित करता है।

बस अपनी application.propertiesफ़ाइल में निम्न पंक्ति जोड़ें (मान लें कि आप स्प्रिंग बूट का उपयोग कर रहे हैं, और मान लें कि आप स्प्रिंग बूट स्टार्टर निर्भरता का उपयोग कर रहे हैं जिसमें शामिल हैं spring-boot-starter-logging)

logging.level.org.springframework.web.client.RestTemplate = डीबग

आउटपुट कुछ इस तरह दिखेगा:

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]

2
नंबर 4 डिबग करने का सबसे आसान तरीका है।
युबराज

1
नंबर 2 मेरे लिए काम किया। यह अनुरोध के शरीर में प्रवेश करता है। धन्यवाद!
caglar

1
जब मैं इस मुद्दे पर आया तो मुझे ऐसा करने का एक आसान तरीका मिला।
18:00 पर बिल नेलर

12

अन्य उत्तर में वर्णित HttpClient लॉगिंग के अलावा , आप एक ClientHttpRequestInterceptor भी पेश कर सकते हैं जो अनुरोध के शरीर और प्रतिक्रिया को पढ़ता है और इसे लॉग करता है। यदि अन्य सामान भी HttpClient का उपयोग करता है, या यदि आप एक कस्टम लॉगिंग प्रारूप चाहते हैं तो आप ऐसा करना चाह सकते हैं। सावधानी: आप रेस्टेमप्लेट को एक बफ़रिंगक्लेरिएंटहेटप्रेपरेस्टफेस्टफैक्टरी देना चाहेंगे, ताकि आप दो बार प्रतिक्रिया पढ़ सकें।


12

जैसा कि अन्य प्रतिक्रियाओं में कहा गया है, प्रतिक्रिया शरीर को विशेष उपचार की आवश्यकता होती है इसलिए इसे बार-बार पढ़ा जा सकता है (डिफ़ॉल्ट रूप से, इसकी सामग्री पहले पढ़ने पर प्राप्त होती है)।

BufferingClientHttpRequestFactoryअनुरोध सेट करते समय उपयोग करने के बजाय , इंटरसेप्टर स्वयं प्रतिक्रिया को लपेट सकता है और सुनिश्चित कर सकता है कि सामग्री बरकरार रखी गई है और बार-बार (लकड़हारे के साथ-साथ प्रतिक्रिया के उपभोक्ता द्वारा) पढ़ी जा सकती है :

मेरा इंटरसेप्टर, जो

  • एक आवरण का उपयोग कर प्रतिक्रिया शरीर को बफ़र करता है
  • अधिक कॉम्पैक्ट तरीके से लॉग करता है
  • स्थिति कोड पहचानकर्ता को लॉग करता है (जैसे 201 बनाया गया)
  • एक अनुरोध अनुक्रम संख्या शामिल है जो आसानी से कई थ्रेड्स से समवर्ती लॉग प्रविष्टियों को भेद करने की अनुमति देता है

कोड:

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();
        }
    }
}

विन्यास:

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

उदाहरण लॉग आउटपुट:

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", ...  }

1
यह एक 2019 स्प्रिंग संस्करण के साथ काम करता है जो शरीर को बरकरार रखता है।
उडो हेल्ड

1
वसंत 2.1.10 पर काम करता है :) धन्यवाद
मोलर


8

यह ऐसा करने का सही तरीका नहीं हो सकता है, लेकिन मुझे लगता है कि लॉग में बहुत अधिक भरने के बिना अनुरोधों और प्रतिक्रियाओं को प्रिंट करने के लिए यह सबसे सरल तरीका है।

नीचे 2 रेखाओं को जोड़कर application.properties सभी अनुरोधों और प्रतिक्रियाओं को लॉग करता है ताकि अनुरोधों को लॉग करने के लिए पहली पंक्ति और प्रतिक्रियाओं को लॉग करने के लिए 2 पंक्ति।

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

लॉगिंग प्रतिक्रियाएं मेरे लिए काम नहीं करती हैं। यह सिर्फ स्टेटसकोड लॉग करता है। क्या इसे पेलोड लॉग करना चाहिए?
बैडेरा

वर्ग HttpEntityMethodProcessor (v5.1.8) कुछ भी लॉग नहीं करता है।
क्रिस

6

मान लें RestTemplateकि HttpClient 4.x का उपयोग करने के लिए कॉन्फ़िगर किया गया है, तो आप यहां HttpClient के लॉगिंग दस्तावेज़ पर पढ़ सकते हैं । लॉगर्स अन्य उत्तरों में निर्दिष्ट लोगों की तुलना में अलग हैं।

HttpClient 3.x के लिए लॉगिंग कॉन्फ़िगरेशन यहां उपलब्ध है


4

यहाँ कई प्रतिक्रियाओं को कोडिंग परिवर्तन और अनुकूलित कक्षाओं की आवश्यकता होती है और यह वास्तव में आवश्यक नहीं है। डिबगिंग प्रॉक्सी जैसे कि फ़िडलर को टाइप करें और कमांड लाइन (-Dhttp.proxyHost और -Dhttp.proxyPort) पर प्रॉक्सी का उपयोग करने के लिए अपना जावा वातावरण सेट करें, फिर फ़िडलर चलाएं और आप अनुरोधों और प्रतिक्रियाओं को उनकी संपूर्णता में देख सकते हैं। इसके अलावा कई सहायक फायदे भी आते हैं जैसे कि परिणाम और प्रतिक्रियाओं के साथ छेड़छाड़ करने की क्षमता और इससे पहले कि वे सर्वर को संशोधित करने से पहले प्रयोगों को चलाने के लिए भेजे जाते हैं।

अंतिम समस्या जो सामने आ सकती है यदि आप HTTPS का उपयोग करना चाहते हैं, तो आपको SSL प्रमाणपत्र को फ़िडलर से निर्यात करना होगा और इसे java keystore (cacerts) संकेत में आयात करना होगा: डिफ़ॉल्ट java keystore पासवर्ड आमतौर पर "changeit" है।


1
यह मेरे लिए intellij और fiddle की नियमित स्थापना का उपयोग करके काम करता है। मैंने रन कॉन्फ़िगरेशन को संपादित किया और VM विकल्पों को इसमें सेट किया -DproxySet=true -Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888
JD

धन्यवाद! अपने स्वयं के इंटरसेप्टर को लिखने की तुलना में यह एक सुंदर सुरुचिपूर्ण समाधान है।
क्रिस

3

अपाचे HttpClient की मदद से लॉगबैक में प्रवेश करने के लिए :

आपको क्लासपाथ में अपाचे HttpClient की आवश्यकता है:

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <version>4.5.10</version>
</dependency>

RestTemplateHttpClient का उपयोग करने के लिए अपने कॉन्फ़िगर करें :

restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

अनुरोध और प्रतिक्रियाओं को लॉग करने के लिए, लॉगबैक कॉन्फ़िगरेशन फ़ाइल में जोड़ें:

<logger name="org.apache.http.wire" level="DEBUG"/>

या और भी लॉग इन करने के लिए:

<logger name="org.apache.http" level="DEBUG"/>

लॉगबैक कॉन्फ़िगरेशन फ़ाइल क्या है?
G_V

1
@G_V logback.xml या परीक्षणों के लिए logback-test.xml।
holmis83

यह org.apache.http.wire=DEBUGआपके साथ application.propertiesअब भी काम करता है
G_V

@G_V यदि आप स्प्रिंग-बूट का उपयोग कर रहे हैं। मेरा जवाब बूट के बिना काम करता है।
holmis83

2

यदि आप किसी भी का उपयोग कर रहे हैं , जो आप इंटरसेप्टर के माध्यम से लॉग इन करने की कोशिश कर रहे हैं, तो आपके RestTemplateसाथ कॉन्फ़िगर करने की चाल BufferingClientHttpRequestFactoryकाम नहीं करती है ClientHttpRequestInterceptor। यह उस तरीके के कारण है InterceptingHttpAccessorजो (जो RestTemplateउपवर्ग) काम करता है।

लंबी कहानी छोटी ... बस इस वर्ग का उपयोग करें RestTemplate(ध्यान दें कि यह SLF4J लॉगिंग एपीआई का उपयोग करता है, आवश्यकतानुसार संपादित करें):

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();
    }
}

मैं मानता हूं कि यह मूर्खतापूर्ण है कि यह सिर्फ इतना काम करता है।


2

उपरोक्त चर्चा में इसे जोड़ना केवल हैप्पी परिदृश्यों का प्रतिनिधित्व करता है। यदि कोई त्रुटि आती है तो शायद आप प्रतिक्रिया को लॉग नहीं कर पाएंगे ।

इस स्थिति में आपके ऊपर के सभी मामले DefaultResponseErrorHandler को ओवरराइड कर सकते हैं और इसे नीचे की तरह सेट करना चाहिए

restTemplate.setErrorHandler(new DefaultResponseErrorHandlerImpl());

2

अजीब बात है, इन समाधानों में से कोई भी काम नहीं करता है क्योंकि RestTemplate कुछ क्लाइंट और सर्वर 500x त्रुटियों पर प्रतिक्रिया वापस नहीं करता है। जिस स्थिति में, आपने निम्न के रूप में ResponseErrorHandler को लागू करने के साथ ही लॉग इन किया होगा। यहाँ एक ड्राफ्ट कोड है, लेकिन आपको यह बात मिलती है:

आप त्रुटि हैंडलर के रूप में एक ही इंटरसेप्टर सेट कर सकते हैं:

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

और अवरोधन दोनों इंटरफेस को लागू करता है:

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);
    }
}

क्या होगा यदि शरीर मल्टीपार्ट / फॉर्म-डेटा है, तो क्या लॉग से बाइनरी डेटा (फ़ाइल सामग्री) को फ़िल्टर करने का एक आसान तरीका है?
ल्यूक

1

जैसा कि @MilacH ने बताया, कार्यान्वयन में त्रुटि है। यदि कोई StatusCode> 400 लौटाया जाता है तो IOException को फेंक दिया जाता है, क्योंकि ErrorHandler को रिसेप्टर्स से नहीं भेजा जाता है। अपवाद को अनदेखा किया जा सकता है और फिर हैंडलर विधि में फिर से पकड़ा जाता है।

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

सबसे अच्छा समाधान अब, बस निर्भरता जोड़ें:

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

इसमें एक LoggingRequestInterceptor वर्ग है जिसे आप अपने RestTemplate में जोड़ सकते हैं:

निम्नलिखित तरीके से इसे स्प्रिंग रेस्टेमप्लेट के इंटरसेप्टर के रूप में जोड़कर इस उपयोगिता को एकीकृत करें:

restTemplate.setRequestFactory(LoggingRequestFactoryFactory.build());

और log4j की तरह अपने ढांचे में एक slf4j कार्यान्वयन जोड़ें।

या सीधे "Zg2proRestTemplate" का उपयोग करें । @PaulSabou द्वारा "सबसे अच्छा जवाब" ऐसा दिखता है, क्योंकि एक स्प्रिंग रेस्टटेम्पलेट का उपयोग करते समय httpclient और सभी अपाचे.http लिबास आवश्यक रूप से लोड नहीं होते हैं।


जारी किया गया संस्करण क्या है?
पोपल्का

जारी किया गया संस्करण अब 0.2 है
मूसा मेयर

1
उपयोग में आसानी महान है, लेकिन इसमें हेडर की कमी है
WrRaThY

इसके अतिरिक्त: LoggingRequestInterceptor में सभी उपयोगी विधियां निजी हैं, जो एक समस्या है जब यह विस्तार की बात आती है (संरक्षित किया जा सकता है)
WrRaThY

दुख की बात है कि मैं 5 मिनट के बाद टिप्पणी संपादित नहीं कर सकता। आप सभी हेडर लॉग इन करने की क्या करना है यह है: log("Headers: {}", request.headers)में LoggingRequestInterceptor:traceRequestऔर log("Headers: {}", response.headers)में LoggingRequestInterceptor:logResponse। आप हेडिंग और बॉडी को लॉग करने के लिए कुछ झंडे जोड़ने के बारे में सोचना चाह सकते हैं। इसके अलावा - आप लॉगिंग के लिए बॉडी कंटेंट टाइप चेक कर सकते हैं (उदाहरण के लिए लॉग केवल एप्लिकेशन / json *)। यह भी विन्यास योग्य होना चाहिए। सब के सब, उन छोटे tweaks के साथ आप को फैलाने के लिए एक अच्छा पुस्तकालय होगा। अच्छा काम :)
WrRaThY

0

इसके कार्यान्वयन को भी जोड़ना चाहता था। मैं सभी लापता अर्ध-कॉलनों के लिए माफी चाहता हूं, यह ग्रूवी में लिखा गया है।

मुझे स्वीकृत उत्तर की तुलना में कुछ अधिक विन्यास की आवश्यकता थी। यहाँ एक आराम टेम्पलेट बीन है जो बहुत चुस्त है और ओपी की तलाश में है जैसे सब कुछ लॉग करेगा।

कस्टम लॉगिंग इंटरसेप्टर क्लास:

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=================================================")
        }
    }
}

बाकी खाका बीन परिभाषा:

@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
}

कार्यान्वयन:

@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

org.apache.http.wire दे भी पढ़ने योग्य नहीं करता है, तब तो मैं का उपयोग कार्यपंजी लॉग इन करने के आवेदन सर्वलेट और RestTemplate अनुरोध / resp लॉग में

build.gradle

compile group: 'org.zalando', name: 'logbook-spring-boot-starter', version: '1.13.0'

application.properties

logging.level.org.zalando.logbook:TRACE

RestTemplate

@Configuration
public class RestTemplateConfig {

@Autowired
private LogbookHttpRequestInterceptor logbookHttpRequestInterceptor;

@Autowired
private LogbookHttpResponseInterceptor logbookHttpResponseInterceptor;

@Bean
public RestTemplate restTemplate() {
    return new RestTemplateBuilder()
        .requestFactory(new MyRequestFactorySupplier())
        .build();
}

class MyRequestFactorySupplier implements Supplier<ClientHttpRequestFactory> {

    @Override
    public ClientHttpRequestFactory get() {
        // Using Apache HTTP client.
        CloseableHttpClient client = HttpClientBuilder.create()
            .addInterceptorFirst(logbookHttpRequestInterceptor)
            .addInterceptorFirst(logbookHttpResponseInterceptor)
            .build();
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(client);
        return clientHttpRequestFactory;
    }

}
}

-1

ClientHttpInterceptor का उपयोग करके प्रतिक्रिया से संबंधित, मुझे बफ़रिंग कारखानों के बिना पूरी प्रतिक्रिया रखने का एक तरीका मिला। बाइट सरणी के अंदर प्रतिक्रिया बॉडी इनपुट स्ट्रीम को स्टोर करें कुछ बर्तनों की विधि का उपयोग करके, जो बॉडी से उस एरे को कॉपी करेगा, लेकिन महत्वपूर्ण है, इस विधि को ट्राई कैच से घेरें क्योंकि यह रिस्पॉन्स खाली होने पर टूट जाएगा (यह संसाधन पहुंच अपवाद का कारण है) और कैच में केवल खाली बाइट सरणी बनाते हैं, और मूल प्रतिक्रिया से उस एरे और अन्य मापदंडों का उपयोग करके केवल क्लाइंटहार्टप्रोसेसन का अनाम आंतरिक वर्ग बनाएं। आप उस नई ClientHttpResponse ऑब्जेक्ट को बाकी टेम्प्लेट निष्पादन श्रृंखला में वापस कर सकते हैं और आप पहले से संग्रहित बॉडी बाइट सरणी का उपयोग करके प्रतिक्रिया लॉग कर सकते हैं। इस तरह से आप वास्तविक प्रतिक्रिया में InputStream का सेवन करने से बचेंगे और आप रेस्ट टेम्प्लेट की प्रतिक्रिया का उपयोग कर सकते हैं। ध्यान दें,


-2

मेरे लकड़हारा विन्यास xml का इस्तेमाल किया

<logger name="org.springframework.web.client.RestTemplate">
    <level value="trace"/>
</logger>

फिर आपको नीचे जैसा कुछ मिलेगा:

DEBUG org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:92) : Reading [com.test.java.MyClass] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@604525f1]

HttpMessageConverterExtractor.java:92,you के माध्यम से डिबग जारी रखने की आवश्यकता है, और मेरे मामले में, मुझे यह मिला:

genericMessageConverter.write(requestBody, requestBodyType, requestContentType, httpRequest);

और इस:

outputMessage.getBody().flush();

outputMessage.getBody () में http (पोस्ट प्रकार) संदेश भेजता है


ट्रेस लॉगिंग बहुत अधिक हो सकती है ... क्या होगा अगर प्रति सेकंड हजारों अनुरोध हैं ??
ग्वारसियो एमी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.