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

Spring Boot WebFlux实现@JsonBody注解自定义参数解析器方案咨询

WebFlux自定义@JsonBody参数解析器实现方案

1. 定义@JsonBody自定义注解

和Spring MVC环境的注解定义一致,仅用于标记需要从请求体JSON解析的参数:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonBody {
}

2. 实现HandlerMethodArgumentResolver

WebFlux环境需要实现org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver接口,核心逻辑复用Spring内置的JSON解码器处理请求体,避免自行读取请求体导致的资源泄露、重复读取问题:

import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.List;

public class JsonBodyArgumentResolver implements HandlerMethodArgumentResolver {
    private final List<HttpMessageReader<?>> messageReaders;

    public JsonBodyArgumentResolver(ServerCodecConfigurer codecConfigurer) {
        this.messageReaders = codecConfigurer.getReaders();
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // 判断参数是否标注了@JsonBody注解
        return parameter.hasParameterAnnotation(JsonBody.class);
    }

    @Override
    public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        ResolvableType targetType = ResolvableType.forMethodParameter(parameter);
        
        // 遍历所有内置的消息阅读器,找到匹配JSON的阅读器解析请求体
        for (HttpMessageReader<?> reader : messageReaders) {
            if (reader.canRead(targetType, MediaType.APPLICATION_JSON)) {
                return reader.readMono(targetType, parameter, request, exchange, bindingContext.getModel())
                        .cast(Object.class);
            }
        }
        // 没有匹配的阅读器时返回空
        return Mono.empty();
    }
}

以上实现同时支持普通POJO参数和Mono<T>/Flux<T>包装的响应式参数,Spring会自动处理返回的响应式结果完成参数绑定

3. 注册自定义解析器

在WebFlux配置类中注册解析器,使其生效:

import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;

@Configuration
public class WebFluxConfig implements WebFluxConfigurer {
    private final ServerCodecConfigurer codecConfigurer;

    public WebFluxConfig(ServerCodecConfigurer codecConfigurer) {
        this.codecConfigurer = codecConfigurer;
    }

    @Override
    public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
        configurer.addCustomResolver(new JsonBodyArgumentResolver(codecConfigurer));
    }
}

4. 控制器使用示例

和Spring MVC的使用方式完全一致:

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/student")
public class StudentController {
    // 普通POJO参数
    @PostMapping
    public Mono<Student> addStudent(@JsonBody Student student) {
        // 业务逻辑处理
        return Mono.just(student);
    }

    // 响应式包装参数
    @PostMapping("/async")
    public Mono<Student> addStudentAsync(@JsonBody Mono<Student> studentMono) {
        return studentMono.doOnNext(student -> {
            // 业务逻辑处理
        });
    }
}

注意事项

  1. 无需自行通过exchange.getRequest().getBody()读取请求体转字符串后用ObjectMapper解析,Spring内置的解码器已经处理了编码适配、类型转换、空请求体等边界场景,性能和稳定性更高
  2. 如果需要自定义JSON序列化/反序列化规则,直接配置Spring默认的Jackson2ObjectMapperBuilder即可,解析器会自动复用该配置的ObjectMapper
  3. 若接收JSON数组参数,直接声明@JsonBody List<Student> list或者@JsonBody Flux<Student> flux即可,解码器会自动适配

内容的提问来源于stack exchange,提问作者tweetysat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 17:21:03