通过自定义注解校验后台接口请求参数

定义一个自定义注解类

/**
 * @Author 田海超
 * @Date 2019/12/10 10:04
 * @Description TODO 非空注解
 **/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamNotNull {
    // 指定值
    String value() default "";

    // 中文描述
    String describeName() default "";

    //BigDecimal类型保留位数
    int bigDecimalDigit() default -1;
}

在接口对象中使用注解(如若使用代码,请自行补全set和get方法)

/**
 * @Author 田海超
 * @Date 2019/12/6 15:52
 * @Description TODO 提结接口请求参数VO
 **/
public class RequestObjectDemoVO{
    @ParamNotNull(describeName = "请求/响应序列号")
    private String seqReqNo;//请求/响应序列号
    @ParamNotNull(describeName = "接口类型", value = "prepayment_cf")
    private String interfaceType;//接口类型
    @ParamNotNull(describeName = "接口版本", value = "version1.0.0")
    private String versionNo;//接口版本
    @ParamNotNull(describeName = "进件流水号")
    private String businessNo;//进件流水号
    @ParamNotNull(describeName = "总金额", bigDecimalDigit = 2)
    private String paymentSum;//总金额
    @ParamNotNull(describeName = "本金", bigDecimalDigit = 2)
    private String balance;//本金
    @ParamNotNull(describeName = "利息", bigDecimalDigit = 2)
    private String inte;//利息
    @ParamNotNull(describeName = "保费", bigDecimalDigit = 2)
    private String premium;//保费
    @ParamNotNull(describeName = "服务费", bigDecimalDigit = 2)
    private String commission;//服务费
    @ParamNotNull(describeName = "还款来源", value = "01")
    private String paymentSource;//还款来源   01 客户还款
}

通过反射使用自定义注解校验对象属性值

/**
 * @Author 田海超
 * @Date 2019/12/10 10:36
 * @Description TODO 校验工具类
 **/
public class VerifyUtils {
    /**
     * @return java.lang.String
     * @Author 田海超
     * @Description //TODO 根据非空校验注解校验对象属性是否为空和字段值是否正确
     * @Date 10:35 2019/12/10
     * @Param [object, errorMessage[] 异常描述:errorMessage[0] -->不为空的异常描述;errorMessage[1] -->值校验错误的异常描述;errorMessage[2] -->数字数位校验错误的异常描述]
     **/
    public static String VerifyNotNullAndValueIsRight(Object object, String... errorMessage) {
        if (object == null) {
            throw new IllegalArgumentException();
        }
        try {
            // 反射获得对象类属性列表
            Field[] fields = object.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(ParamNotNull.class)) {
                    // 该处使可以获得私有属性值
                    field.setAccessible(true);
                    Object value = field.get(object);
                    String annotationValue = field.getAnnotation(ParamNotNull.class).describeName();
                    if (value == null) {
                        return MessageFormat.format(errorMessage[0], annotationValue);
                    }
                    //字符串校验空字符
                    if (value instanceof String && StringUtils.isBlank((String) value)) {
                        return MessageFormat.format(errorMessage[0], annotationValue);
                    }
                    String idealValue = field.getAnnotation(ParamNotNull.class).value();
                    // 如果配置了指定值,校验传入值是否符合要求
                    if (StringUtils.isNotBlank(idealValue)) {
                        if (!idealValue.equals(value)) {
                            return MessageFormat.format(errorMessage[1], annotationValue);
                        }
                        if (value instanceof String && !StringUtils.equals((String) value, idealValue)) {
                            return MessageFormat.format(errorMessage[1], annotationValue);
                        }
                    }
                    // 配置了bigDecimalDigit数目这个字段期望被转化成digit位的数字,这里添加校验
                    int digit = field.getAnnotation(ParamNotNull.class).bigDecimalDigit();
                    if (digit != -1 && value instanceof String && errorMessage.length >= 3 && !AbsUtil.checkDoubleNumber((String) value, digit, true)) {// 校验位数
                        return MessageFormat.format(errorMessage[2], annotationValue);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException("参数非空校验获取参数值时异常");
        }
        return "";
    }

    public static void main(String[] args) {
        System.out.println(new BigDecimal(1.02).setScale(2, BigDecimal.ROUND_UP));
        BigDecimal a = new BigDecimal(1.02);
        System.out.println(a.scale());
        System.out.println(a.scale() == 2);
    }
}

*****************************以下是彩蛋*******************

使用反射,我们还可以对接口请求对象和系统返回对象的值进行一一比较:

前提条件:两个对象要进行比较的对象属性名要一致!!!!!

/**
     * @return void
     * @Author 田海超
     * @Description //TODO 校验结算金额正确性
     * @Date 11:14 2019/12/13
     * @Param [vo, resVo]
     **/
    public void verifyAmount(RequestObjectDemoVO_1 vo, RequestObjectDemoVO_2 resVo) throws Exception{
        Field[] fields = vo.getClass().getDeclaredFields();
        Class c = resVo.getClass();
        for (Field field : fields) {
            if (field.isAnnotationPresent(ParamNotNull.class)) {
                field.setAccessible(true);
                int digit = field.getAnnotation(ParamNotNull.class).bigDecimalDigit();
                if (digit != -1) {// 金额类型--注解类ParamNotNull中的默认值是-1,不等于-1说明配置了小数位数,表明是金额字段
                    Object value = field.get(vo);
                    // 根据循环属性列表的属性名称获得要比较的对象属性Field对信息
                    Field resVoField = c.getDeclaredField(field.getName());
                    resVoField.setAccessible(true);
                    BigDecimal val = (BigDecimal) resVoField.get(resVo);
//                    System.out.println(val.toPlainString());
                    if (val != null && !val.toPlainString().equals(value)) {
                        String describeName = field.getAnnotation(ParamNotNull.class).describeName();
                        throw new DefinedException(getSimpleResJson("0102", MessageFormat.format("报文内容错误:{0}不正确", describeName)));
                    }
                }
            }
        }
    }
posted @ 2019-12-18 15:18  田海超  阅读(1366)  评论(0编辑  收藏  举报