春季最高

通过参考资料,开始使用Spring 5和Spring Boot 2学习的春天课程:

> >学习春天
休息前

通过参考资料,开始使用Spring 5和Spring Boot 2学习的春天课程:

>>看看这个课程

1.概述

在本教程中,我们将学习如何实现高效resttemplate.请求/响应日志记录。这对于调试两台服务器之间的交换特别有用。

不幸的是,春天引导并不提供一种轻松的方法来检查或记录简单的JSON响应正文。

我们将探索几种来记录HTTP标题的方法,也将探索要么或者是最有趣的部分,HTTP Body。

请注意: 春天resttemplate.将被弃用,被替换为WebClient.。你可以找到类似的文章使用WebClient.在这里:记录Spring WebClient调用

2.使用RestTemplate进行基本日志记录

开始吧配置resttemplate.登录器在application.properties文件:

logging.level.org.springFrameWork.Web.Client.RestTemplate = debug.

因此,我们可以只看基本信息喜欢请求URL,方法,正文和响应状态:

o.s.w.c.RestTemplate - HTTP POST http://localhost:8082/spring-rest/persons o.s.w.c.RestTemplate - Accept=[text/plain, application/json, application/*+json, */*] o.s.w.c.RestTemplate - Writing [my request body] with org.springframework.http.converter.StringHttpMessageConverter o.s.w.c.RestTemplate - Response 200 OK

然而,响应身体未在此记录这很不幸,因为这是最有趣的部分。

为了解决这个问题,我们将选择Apache HttpClient或Spring拦截器。

3.使用Apache HttpClient记录头/体

首先,我们要resttemplate.使用Apache HttpClient执行。

我们需要Maven的依赖:

<依赖> < groupId >表示。httpcomponents httpclient 4.5.12 

在创建resttemplate.例如,我们应该告诉它我们正在使用Apache HttpClient:

RestTemplate RestTemplate = new RestTemplate();创建restTemplate。setRequestFactory(新HttpComponentsClientHttpRequestFactory ());

然后,让我们在application.properties文件:

logging.level.org.apache.http = debug logging.level.httpclient.wire = debug

现在我们可以看到请求/响应头和正文:

o.a.http.headers - http-outgoing-0 >> POST /spring-rest/persons HTTP/1.1 o.a.http.headers - http-outgoing-0 >> Accept: text/plain, application/json, application/*+json, */* // ... more request headers o.a.http.headers - http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.9 (Java/1.8.0_171) o.a.http.headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate org.apache.http.wire - http-outgoing-0 >> "POST /spring-rest/persons HTTP/1.1[\r][\n]" org.apache.http.wire - http-outgoing-0 >> "Accept: text/plain, application/json, application/*+json, */*[\r][\n]" org.apache.http.wire - http-outgoing-0 >> "Content-Type: text/plain;charset=ISO-8859-1[\r][\n]" // ... more request headers org.apache.http.wire - http-outgoing-0 >> "[\r][\n]" org.apache.http.wire - http-outgoing-0 >> "my request body" org.apache.http.wire - http-outgoing-0 << "HTTP/1.1 200 [\r][\n]" org.apache.http.wire - http-outgoing-0 << "Content-Type: application/json[\r][\n]" // ... more response headers org.apache.http.wire - http-outgoing-0 << "Connection: keep-alive[\r][\n]" org.apache.http.wire - http-outgoing-0 << "[\r][\n]" org.apache.http.wire - http-outgoing-0 << "21[\r][\n]" org.apache.http.wire - http-outgoing-0 << "["Lucie","Jackie","Danesh","Tao"][\r][\n]"

然而,这些日志是冗长的,也不方便地调试

我们将在下一章中看到如何解决这个问题。

4.使用reastemplate拦截器的记录正文

作为另一种解决方案,我们可以配置拦截器的resttemplate.

4.1。日志记录拦截器实现

首先,让我们创建一个新的loggingInterceptor.要定制日志,请执行以下操作。这个拦截器将请求体记录为一个简单的字节数组。然而,对于响应,我们必须读取整个body stream:

public class LoggingInterceptor implements ClientHttpRequestInterceptor{静态Logger Logger = LoggerFactory.getLogger(LoggingInterceptor.class);@Override public ClientHttpResponse拦截(HttpRequest req,字节[]reqBody, ClientHttpRequestExecution ex)抛出IOException {LOGGER.debug("Request body: {}", new String(reqBody, standardcharset . utf_8));ClientHttpResponse response = ex.execute(req, reqBody);InputStreamReader isr = new InputStreamReader(response.getBody(), StandardCharsets.UTF_8);String body = new BufferedReader(isr).lines() .collect(collections .joining("\n"));LOGGER.debug("Response body: {}", body);返回响应;}}

注意,这个拦截器对响应内容本身有影响,我们将在下一章中发现这一点。

4.2。使用拦截器与RestTemplate

现在,我们必须处理流媒体问题:当拦截器使用响应流时,我们的客户端应用程序将看到一个空的响应体

为避免这种情况,我们应该使用BufferingClientHttpRequestFactory:将流内容缓冲到内存中。这样,它可以读取两次:我们的拦截器一次,第二次由我们的客户应用程序:

ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());RestTemplate RestTemplate = new RestTemplate(factory);

但是,使用这个工厂会带来性能上的缺陷,我们将在下一小节中描述。

然后,我们可以将日志拦截器添加到resttemplate.实例-我们将把它附加在现有的拦截器之后,如果有的话:

列表拦截器= resttemplate.getInterctiveors();if(collectionutils.isusempty(拦截器)){拦截器= new arraylist <>();} Interceptors.Add(新的LoggingInterceptor());resttemplate.setInterceptors(拦截器);

因此,日志中仅存在必要的信息:

c.b.r.l.loggingInterceptor  - 请求正文:我的请求正文C.B.R.L.LoggingInterceptor  - 响应机构:[“Lucie”,“Jackie”,“Danesh”,“Tao”]

4.3。resttemplate拦截器缺点

一、前面提到过的用法BufferingClientHttpRequestFactory有一个严肃的缺点:它撤消了流媒体的好处。作为结果,将整个身体数据加载到内存中可能会将我们的应用程序暴露于性能问题。更糟糕的是,它会导致OutOfMemoryError

为了防止这种情况,一种可能的选择是假设当数据量增加时,这些详细日志将被关闭,这通常在生产中发生。例如,我们可以使用一个缓冲resttemplate.实例只有调试级别已启用在我们的日志:

resttemplate resttemplate = null;if(logger.isdebugenabled()){clienthttproquestfactory factory = new bufferingclienthttprequestfactory(new simpleclienthttprokeestfactory());resttemplate =新的resttemplate(工厂);} else {resttemplate = new resttemplate();}

同样的,我们会确保我们的拦截器只在以下情况下读取响应调试启用日志记录:

if (LOGGER.isDebugEnabled()) {InputStreamReader isr = new InputStreamReader(response.getBody(), standardcharset . utf_8);String body = new BufferedReader(isr) .lines() .collect(collections .joining("\n"));LOGGER.debug("Response body: {}", body);}

5.结论

resttemplate.请求/响应日志记录不是一件简单的事情,因为Spring Boot不包括开箱即用的。

幸运的是,我们已经看到了我们可以使用Apache HttpClient记录器来获得详细的跟踪交换数据。

或者,我们可以实现a自定义拦截器获取更多人类可读日志。但是,对于大数据量,这可能导致性能缺陷。

与往常一样,本文的源代码是可用的在github上在里面测试文件夹中。示例使用resttemplate.在同一项目中定义的RET端点的实时测试中。

弹簧底部

开始使用Spring 5和Spring Boot 2,通过学习的春天课程:

>>课程
休息下

开始使用Spring 5和Spring Boot 2,通过学习的春天课程:

>>看看这个课程
6注释
最老的
最新
内联反馈
查看所有评论
评论在本文上关闭!