webflux (mvc) - 处理 POJO 请求参数 自定义属性

webflux - 处理 POJO 请求参数 自定义属性

使用场景

对接 第三方 接口文档时,使用 POJO 接收对象参数, 第三方有请求多,并且,字段属性是下滑线,我们在定义 POJO 接收请求参数时,大都使用 CamelCase 方式,造成请求参数解析不到

我们定义 POJO:

public class Pojo{
    private String userId;
}

@GetMapping("/index")
public String index(Pojo pojo){
    //omit...
}

实际上 第三方接口字段为 user_id, 这样就解析不到这个参数了

实现原理

在数据绑定的时候,使用POJO 中的属性替换请求参数中的下滑线参数

了解 webflux 中解析 POJO 的过程

webflux 处理 POJO 的解析 过程是在 ModelAttributeMethodArgumentResolver 类中(而 spring mvc 中为 ModelAttributeMethodProcesso),看 ModelAttributeMethodArgumentResolver:

public boolean supportsParameter(MethodParameter parameter) {
    if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
        return true;
    }
    else if (this.useDefaultResolution) {
        //在这里!! 判断是否为 POJO
        return checkParameterType(parameter, type ->
                                  !BeanUtils.isSimpleProperty(type));
    }
    return false;
}

自定义注解

自定义注解: RequestParamAlia,RequestParamAliaFor

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ParamAlia {

}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ParamAliaFor {

    String value() default "";
}

CustomizedWebExchangeDataBinder, 从 WebExchangeDataBinder 拷贝, 大体相同:

public class CustomizedWebExchangeDataBinder extends WebDataBinder {


   
    // 其他方法不变
	public Mono<Void> bind(ServerWebExchange exchange) {
		return getValuesToBind(exchange)
            .doOnNext(values ->
                  {
                     //修改在这里
                     Object target = getTarget();
                     Field[] declaredFields = target.getClass().getDeclaredFields();
                     for (Field declaredField : declaredFields) {
                         RequestParamAliaFor annotation = declaredField.getAnnotation(ParamAliaFor.class);
                         if (!Objects.isNull(annotation) && StrUtil.isNotBlank(annotation.value())){
                             String key = annotation.value();
                               if (values.containsKey(key)){
                                      values.put(declaredField.getName(), values.get(key));
                                  }
                              }
                          }
                          doBind(new MutablePropertyValues(values));
                      })
            .then();
	}



}

CustomizedModelMethodArgumentResolver , 从ModelAttributeMethodArgumentResolver 拷贝:

  @Override
    public Mono<Object> resolveArgument(
            MethodParameter parameter, BindingContext context, 
        			ServerWebExchange exchange) {

        // same as ModelAttributeMethodArgumentResolver
        return valueMono.flatMap(value -> {
            //这里变化
            CustomizedWebExchangeDataBinder binder = new CustomizedWebExchangeDataBinder(value, name);
            return bindRequestParameters(binder, exchange)
                .doOnError(bindingResultMono::onError)
                .doOnSuccess(aVoid -> {
                    BindingResult errors = binder.getBindingResult();
                    model.put(BindingResult.MODEL_KEY_PREFIX + name, errors);
                    model.put(name, value);
                    bindingResultMono.onNext(errors);
                })
                .then(Mono.fromCallable(() -> {
                    // same as ModelAttributeMethodArgumentResolver
                }));
        });
    }

ParamAliaWebfluxConfigurer

@Component
public class AliaWebfluxConfigurer implements WebFluxConfigurer {

    @Override
    public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
        configurer.addCustomResolver(new CustomizedModelMethodArgumentResolver(new ReactiveAdapterRegistry()));
    }
}

使用

public class Pojo{
    
    @ParamAliaFor("user_id")
    private String userId;
}

@GetMapping("/index")
public String index(@ParamAliaPojo pojo){
    //omit...
}

good luck!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值