You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 20:10:17