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));
    }

}

可以查看官网说明

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

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

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值