如何在RestEasy Reactive端点记录HTTP请求与响应体?
在RestEasy Reactive端点中记录请求与响应体的实现方案
针对你的需求,以下是几种可行的实现方式,无需依赖外部插件,主要通过自定义过滤器或配置调整完成:
一、自定义Reactive过滤器(推荐)
RestEasy Reactive基于异步非阻塞模型,需使用适配Reactive的过滤器处理请求/响应体,避免流被消费后无法传递到后续逻辑。
1. 编写请求/响应过滤器
创建实现ContainerRequestFilter和ContainerResponseFilter的类,用@Provider注解注册为全局过滤器:
import jakarta.ws.rs.container.ContainerRequestContext; import jakarta.ws.rs.container.ContainerRequestFilter; import jakarta.ws.rs.container.ContainerResponseContext; import jakarta.ws.rs.container.ContainerResponseFilter; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.ext.Provider; import org.jboss.logging.Logger; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @Provider public class RequestResponseLoggingFilter implements ContainerRequestFilter, ContainerResponseFilter { private static final Logger LOG = Logger.getLogger(RequestResponseLoggingFilter.class); @Override public void filter(ContainerRequestContext requestContext) throws IOException { // 仅处理JSON类型请求 if (requestContext.getMediaType() != null && requestContext.getMediaType().isCompatible(MediaType.APPLICATION_JSON_TYPE)) { // 读取并缓存请求体,避免流被消费 InputStream originalInputStream = requestContext.getEntityStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = originalInputStream.read(buffer)) != -1) { baos.write(buffer, 0, bytesRead); } byte[] requestBody = baos.toByteArray(); // 记录请求信息 LOG.infof("Request URI: %s, Request Body: %s", requestContext.getUriInfo().getPath(), new String(requestBody)); // 将缓存流放回请求上下文 requestContext.setEntityStream(new ByteArrayInputStream(requestBody)); } } @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { // 仅处理JSON类型响应 if (responseContext.getMediaType() != null && responseContext.getMediaType().isCompatible(MediaType.APPLICATION_JSON_TYPE)) { Object responseEntity = responseContext.getEntity(); if (responseEntity != null) { // 记录响应信息 LOG.infof("Response URI: %s, Response Body: %s", requestContext.getUriInfo().getPath(), responseEntity.toString()); } } } }
2. 注意事项
- 针对大请求体,建议添加大小限制逻辑,避免内存溢出
- 若处理
Uni类型的异步响应,需结合Uni的回调方法获取最终响应体
二、调整Quarkus访问日志配置(仅适用于简单场景)
原生访问日志对请求体的支持有限,仅能作为补充方案:
在application.properties中添加:
quarkus.http.access-log.enabled=true # 自定义日志模式,补充查询参数等信息(原生不支持直接记录请求体内容) quarkus.http.access-log.pattern="%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\" %q"
三、客户端场景日志配置(调用外部服务时)
如果是作为REST客户端调用外部服务,可使用quarkus-rest-client-reactive的日志配置:
quarkus.rest-client."your-client-name".logging.scope=REQUEST_RESPONSE quarkus.rest-client."your-client-name".logging.body-limit=1024
内容的提问来源于stack exchange,提问作者Allan Juan
相关产品推荐
相关产品推荐

