【含源码】SpringBoot WebFlux实现自定义RequestBody注解

实现环境:SpringBoot 2.1.1,JDK 1.8

一、WebFlux 实现 RequestBody 注解源码解析

1. @RequestBody

源码:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
 
 /**
  * Whether body content is required.
  * <p>Default is {@code true}, leading to an exception thrown in case
  * there is no body content. Switch this to {@code false} if you prefer
  * {@code null} to be passed when the body content is {@code null}.
  * @since 3.2
  */
 boolean required() default true;
 
}
  • @Target(ElementType.PARAMETER):Target 定义注解的作用目标,ElementType.PARAMETER 作用在方法参数上

  • @Retention(RetentionPolicy.RUNTIME):注解会在 class 字节码文件中存在,在运行时可以通过反射获取到

  • @Documented:说明该注解被包含在 javadoc 中

2. RequestBodyArgumentResolver

官方解释:

Resolves method arguments annotated with {@code @RequestBody} by reading the body of the request through a compatible {@code HttpMessageReader}.

源码中的继承关系

public class RequestBodyArgumentResolver extends AbstractMessageReaderArgumentResolver 
public abstract class AbstractMessageReaderArgumentResolver extends HandlerMethodArgumentResolverSupport
  • RequestBodyArgumentResolver:使用 HttpMessageReader 解析 request body 参数的具体实现类

Resolves method arguments annotated with {@code @RequestBody} by reading the body of the request through a compatible {@code HttpMessageReader}.

  • AbstractMessageReaderArgumentReaolver:使用 HttpMessageReder 解析 request body 参数的基类

Abstract base class for argument resolvers that resolve method arguments by reading the request body with an {@link HttpMessageReader}.

RequestBodyArgumentResolver 对 @RequestBody 的绑定及参数解析源码

public class RequestBodyArgumentResolver extends AbstractMessageReaderArgumentResolver {
 
 public RequestBodyArgumentResolver(List<HttpMessageReader<?>> readers,
   ReactiveAdapterRegistry registry) {
 
  super(readers, registry);
 }
 
 
 @Override
 public boolean supportsParameter(MethodParameter parameter) {
  return parameter.hasParameterAnnotation(RequestBody.class);
 }
 
 @Override
 public Mono<Object> resolveArgument(
   MethodParameter param, BindingContext bindingContext, ServerWebExchange exchange) {
 
  RequestBody ann = param.getParameterAnnotation(RequestBody.class);
  Assert.state(ann != null, "No RequestBody annotation");
  return readBody(param, ann.required(), bindingContext, exchange);
 }
 
}

supportsParameter 与 @RequestBody 注解绑定,resolveArgument 实现具体解析

 二、自定义 RequestBody

1. 自定义注解

import java.lang.annotation.*;
 
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyBody {
    boolean required() default true;
}

2. Resolver

import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.Assert;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.reactive.result.method.annotation.AbstractMessageReaderArgumentResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
 
import java.util.List;
 
public class MyBodyResolver extends AbstractMessageReaderArgumentResolver {
    public KIMBodyResolver(List<HttpMessageReader<?>> readers) {
        super(readers);
    }
 
    protected KIMBodyResolver(List<HttpMessageReader<?>> messageReaders, ReactiveAdapterRegistry adapterRegistry) {
        super(messageReaders, adapterRegistry);
    }
 
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(MyBody.class);//绑定注解
    }
 
    @Override
    public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        String token = request.getHeaders().getFirst("token");//获取头部token
        if (null == token||token.isEmpty()){
            Assert.state(token==null,"token is null");
            return Mono.error(new Exception("token is null"));//token不存在抛出异常
        }
        MyBody annotation = parameter.getParameterAnnotation(MyBody.class);
        Assert.state(annotation != null, "No KIMBody annotation");
 
        //调用AbstractMessageReaderArgumentResolver类中readBody方法
        return readBody(parameter,annotation.required(),bindingContext,exchange);
    }
}

3. 将 Resolver 添加入配置中

import com.example.webflux.request.MyBodyResolver;
import javafx.beans.property.ObjectProperty;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
 
import java.util.ArrayList;
import java.util.List;
 
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
 
 
    @Override
    public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
        List<HttpMessageReader<?>> readers=new ArrayList<HttpMessageReader<?>>();
        //添加Http消息编解码器
        readers.add(new DecoderHttpMessageReader<>(new Jackson2JsonDecoder()));
        //消息编解码器与Resolver绑定
        configurer.addCustomResolver(new MyBodyResolver(readers));
    }
 
}

可以查看官网(https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-config-message-codecs)说明

WebFlux 自定义 @RequestBody 与 MVC 自定义 @RequestBody 类似

如有谬误,欢迎各位大佬斧正!


作者:冲冠

来源链接:

https://blog.csdn.net/shenszy/article/details/85676415

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
@RequestBody 注解Spring Framework 中的一个注解,它用于将 HTTP 请求的请求体部分绑定到方法的参数上。在 Spring MVC 或 Spring Boot 应用程序中,通常用于处理 POST、PUT、PATCH 等请求方法中的 JSON 或表单数据。 以下是 @RequestBody 注解源码: ```java package org.springframework.web.bind.annotation; import org.springframework.core.annotation.AliasFor; import org.springframework.http.MediaType; import java.lang.annotation.*; @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestBody { @AliasFor("contentType") String value() default ""; @AliasFor("value") String contentType() default ""; boolean required() default true; Class<? extends HttpMessageConverter<?>>[] converters() default {}; Class<? extends Annotation>[] annotations() default {}; } ``` 这段源码定义了 @RequestBody 注解的属性和行为: - `value` 和 `contentType` 属性用于指定请求体的媒体类型。默认为空字符串,表示自动检测请求的媒体类型。 - `required` 属性用于指定请求体是否为必需,默认为 true。 - `converters` 属性用于指定用于将请求体转换为方法参数的对象的 HttpMessageConverter 实现类。默认为空数组,表示使用 Spring 的默认转换器。 - `annotations` 属性用于指定其他注解,以进一步自定义请求体的处理方式。 通过使用 @RequestBody 注解,我们可以将请求体的内容以 JSON 或表单数据的形式绑定到方法参数上,方便地进行数据的处理和转换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值