通过自定义注解校验后台接口请求参数
定义一个自定义注解类
/** * @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))); } } } } }