Quarkus/Vert.x:如何同时获取解析后的请求负载与原始请求输入流?
同时获取解析后的请求实体与原始请求体的解决方案
针对你遇到的单元测试正常但集成测试中流已关闭无法重置的问题,这里提供两种可行的非响应式解决方案:
方案一:通过请求过滤器提前缓存原始请求体
在请求到达端点前,用过滤器读取并缓存原始请求体,同时将流替换为可重复读取的字节流,避免框架解析实体后流被关闭或无法重置的问题。
实现缓存过滤器
import jakarta.ws.rs.container.ContainerRequestContext import jakarta.ws.rs.container.ContainerRequestFilter import jakarta.ws.rs.ext.Provider import java.io.ByteArrayInputStream import java.nio.charset.StandardCharsets @Provider class RawRequestCachingFilter : ContainerRequestFilter { override fun filter(requestContext: ContainerRequestContext) { // 读取原始请求体字节 val rawBodyBytes = requestContext.entityStream.readAllBytes() // 转换为字符串缓存 val rawPayload = String(rawBodyBytes, StandardCharsets.UTF_8) // 将流替换为可重复读取的ByteArrayInputStream,供框架后续解析实体使用 requestContext.entityStream = ByteArrayInputStream(rawBodyBytes) // 将原始请求体存入请求属性,方便端点获取 requestContext.properties["RAW_REQUEST_PAYLOAD"] = rawPayload } }
修改端点获取缓存内容
@POST @Path("/path") @Consumes(APPLICATION_JSON) fun endpoint( body: MyEntity, @Context context: ContainerRequestContext, ): RestResponse<String> { // 从请求属性中取出预缓存的原始请求体 val fullPayload = context.properties["RAW_REQUEST_PAYLOAD"] as String // 后续业务逻辑... return RestResponse.ok(fullPayload) }
优势:无需修改端点的核心逻辑,过滤器自动完成流的缓存与重置,适配单元测试和集成测试场景,对业务代码侵入性低。
方案二:手动读取原始流并解析实体
直接让端点接收原始输入流,手动完成实体解析,同时保留原始请求体内容,完全控制流的读取过程。
修改端点实现
import com.fasterxml.jackson.databind.ObjectMapper import jakarta.ws.rs.Consumes import jakarta.ws.rs.POST import jakarta.ws.rs.Path import jakarta.ws.rs.core.MediaType import jakarta.ws.rs.core.RestResponse import java.io.InputStream import java.nio.charset.StandardCharsets @POST @Path("/path") @Consumes(MediaType.APPLICATION_JSON) fun endpoint( rawInputStream: InputStream, objectMapper: ObjectMapper, // 注入Jackson的ObjectMapper ): RestResponse<String> { // 读取原始请求体字节并转换为字符串 val rawBodyBytes = rawInputStream.readAllBytes() val fullPayload = String(rawBodyBytes, StandardCharsets.UTF_8) // 手动将原始字节解析为目标实体类 val body = objectMapper.readValue(rawBodyBytes, MyEntity::class.java) // 后续业务逻辑... return RestResponse.ok(fullPayload) }
优势:完全绕过框架的自动解析逻辑,避免流被框架关闭或消费的问题,适合需要精细控制请求体处理的场景。
内容的提问来源于stack exchange,提问作者brisssou
相关产品推荐
相关产品推荐

