【墙裂推荐】球球了,RPC之间调用别再使用 if-else做参数校验了

RPC调用时使用 @Validated进行参数校验不起作用

球球了,RPC之间调用别再使用 if-else做参数校验了。众所周知,@Validated 是一款非常好用的参数校验工具。但在RPC调用时不可用,在当前的微服务大环境下,微服务之间的调用怎么做到优雅的参数校验呢?

话不多说,直接上干货

引包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
复制代码

1. 参数校验 这里我们先要定义一个注解来代替来继承 @Validated

import org.springframework.validation.annotation.Validated;

@Validated
public @interface RPCValidated {
}
复制代码

2. 然后使用AOP来解析参数,进行参数校验。

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator;
import org.springframework.stereotype.Component;
import wangjubao.base.common.extend.Response;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Aspect
@Component
@Slf4j
public class ValidatedAop {
    private static Validator validator;

    static {
        validator = Validation.byDefaultProvider().configure()
                .messageInterpolator(new ResourceBundleMessageInterpolator(
                        new PlatformResourceBundleLocator("validationMessages")))
                .buildValidatorFactory().getValidator();
    }

    @Around("@annotation(com.qiaoba.annotation.RPCValidated))")
    public Object around(ProceedingJoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 执行方法参数的校验
        Set<ConstraintViolation<Object>> constraintViolations = validator.forExecutables().validateParameters(joinPoint.getThis(), signature.getMethod(), args);
        List<String> messages = new ArrayList<>();
        for (ConstraintViolation<Object> error : constraintViolations) {
            messages.add(error.getMessage());
        }
        if (!messages.isEmpty()) {
            return Response.paramError("参数错误:", messages.get(0));
        }
        try {
            return joinPoint.proceed(args);
        } catch (Throwable e) {
            e.printStackTrace();
            return Response.error("操作失败:", e.getMessage());
        }
    }
}
复制代码

3. 使用方法,在接口Impl实现类加上定义的@RPCValidated

@Override
@RPCValidated
public Response create(MessageSmsRechargeDto dto) {
    //todo:业务逻辑......
}
复制代码

4. 在Interfaces接口层加上@Valid注解

Response create(@Valid MessageSmsRechargeDto params);
复制代码

5. 实体类

@Data
public class MessageSmsRechargeDto implements Serializable {


    /**
     * 充值公司
     */
    @NotNull(message = "充值公司不能为空 ")
    private Long companyId;

    /**
     * 充值备注
     */
    @NotEmpty(message = "充值备注不能为空 ")
    private String rechargeRemark;
 }
复制代码

--- 至此,整个流程完成,加上自定义的参数校验注解@RPCValidated后,就可以优雅的进行参数校验,不用再写各种if-else 做参数校验了

猜你喜欢

转载自juejin.im/post/7040683548604366885