如何仅对特定Endpoint记录RestTemplate请求与响应日志?
RestTemplate特定Endpoint日志记录解决方案
1. 自定义拦截器实现Endpoint过滤
基于你已实现的日志逻辑,在拦截器中添加目标Endpoint的匹配判断,仅对符合条件的请求/响应输出日志:
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 org.springframework.util.StreamUtils; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Set; public class TargetEndpointLoggingInterceptor implements ClientHttpRequestInterceptor { private static final Logger logger = LoggerFactory.getLogger(TargetEndpointLoggingInterceptor.class); // 定义需要记录日志的Endpoint集合 private final Set<String> targetEndpoints = Set.of("/api/v1/payments", "/api/v1/notifications"); @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { String requestUri = request.getURI().getPath(); boolean needLog = targetEndpoints.stream().anyMatch(requestUri::startsWith); // 仅匹配目标Endpoint时记录请求日志 if (needLog) { logRequestDetails(request, body); } ClientHttpResponse response = execution.execute(request, body); // 仅匹配目标Endpoint时记录响应日志 if (needLog) { logResponseDetails(response); } return response; } private void logRequestDetails(HttpRequest request, byte[] body) { logger.info("Request URI: {}, Method: {}, Headers: {}, Body: {}", request.getURI(), request.getMethod(), request.getHeaders(), new String(body, StandardCharsets.UTF_8)); } private void logResponseDetails(ClientHttpResponse response) throws IOException { String responseBody = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8); logger.info("Response Status: {}, Headers: {}, Body: {}", response.getStatusCode(), response.getHeaders(), responseBody); } }
2. 注册自定义拦截器到RestTemplate
在RestTemplate配置类中替换原日志拦截器,使用上述自定义拦截器:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; import java.util.ArrayList; import java.util.List; @Configuration public class RestTemplateConfiguration { @Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>(); interceptors.add(new TargetEndpointLoggingInterceptor()); restTemplate.setInterceptors(interceptors); return restTemplate; } }
3. 动态配置目标Endpoint(可选)
若需要灵活调整目标Endpoint,可从配置文件读取,避免硬编码:
拦截器修改
import org.springframework.beans.factory.annotation.Value; import java.util.HashSet; import java.util.List; import java.util.Set; public class TargetEndpointLoggingInterceptor implements ClientHttpRequestInterceptor { private static final Logger logger = LoggerFactory.getLogger(TargetEndpointLoggingInterceptor.class); private final Set<String> targetEndpoints; // 从配置文件注入目标Endpoint列表 public TargetEndpointLoggingInterceptor(@Value("#{'${rest.log.target.endpoints}'.split(',')}") List<String> endpoints) { this.targetEndpoints = new HashSet<>(endpoints); } // 后续intercept、日志方法逻辑同前 }
配置文件添加参数
# application.properties rest.log.target.endpoints=/api/v1/payments,/api/v1/notifications,/api/v1/orders
4. 多RestTemplate实例隔离日志(可选)
若部分请求无需日志,可创建两个RestTemplate实例,分别对应日志/非日志场景:
@Configuration public class RestTemplateConfiguration { // 带日志拦截的实例,用于特定Endpoint请求 @Bean("loggingRestTemplate") public RestTemplate loggingRestTemplate() { RestTemplate restTemplate = new RestTemplate(); List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>(); interceptors.add(new TargetEndpointLoggingInterceptor()); restTemplate.setInterceptors(interceptors); return restTemplate; } // 普通实例,不记录日志 @Bean public RestTemplate defaultRestTemplate() { return new RestTemplate(); } }
使用时指定注入对应实例:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.web.client.RestTemplate; // 注入带日志的实例处理需要日志的请求 @Autowired @Qualifier("loggingRestTemplate") private RestTemplate loggingRestTemplate; // 注入普通实例处理无需日志的请求 @Autowired @Qualifier("defaultRestTemplate") private RestTemplate defaultRestTemplate;
内容的提问来源于stack exchange,提问作者SpicySandwich
相关产品推荐
相关产品推荐

