java利用注解及反射做通用的入参校验
一、原理:
1、做一个field注解,注解有两个参数:是否必填、toString之后的最大长度
2、对某个request类(或基类),使用注解标记某个字段的校验详情
3、通用的static方法,利用反射获取属性的值,并做校验。不通过则抛出特定的异常
二、上代码:
异常类:
package com.test; /** * 基础异常 * @author zyydd * @date 2019/1/24 10:33 * @version 1.0.0 **/ public class BaseException extends RuntimeException { /** 异常码 */ private String code; /** 异常描述 */ private String desc; public BaseException(){ } public String getCode() { return code; } private void setCode(String code) { this.code = code; } public String getDesc() { return desc; } private void setDesc(String desc) { this.desc = desc; } public BaseException(String code, String desc) { this(code, desc, new Throwable(desc)); } public BaseException(String code, String desc, Throwable canse) { super(new StringBuilder().append("code=").append(code).append(", desc=").append(desc).toString(), canse); this.setCode(code); this.setDesc(desc); } @Override public String toString() { return new StringBuilder().append(getClass().getName()) .append("{code=").append(this.getCode()) .append(", desc=").append(this.getDesc()) .append("}").toString(); } }
测试的request类:
package com.test; /** * @author zyydd * @date 2019/6/13 18:29 */ public class TestChildRequest { /** * name */ @ParameterAttr(isNecessary = true, lengthLimit = 10) private String name; /** * pin */ @ParameterAttr(lengthLimit = 15) private String address; @ParameterAttr(isNecessary = true) private String school; private String other; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getSchool() { return school; } public void setSchool(String school) { this.school = school; } public String getOther() { return other; } public void setOther(String other) { this.other = other; } }
field校验注解类:
package com.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author zyydd * @date 2019/6/13 16:52 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ParameterAttr { /** * 是否必须,默认不必须 * * @return */ boolean isNecessary() default false; /** * 属性toSring之后,最大长度 * * @return */ int lengthLimit() default 0; }
通用校验工具类及main测试方法:
package com.test; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @author zyydd * @date 2019/6/13 17:02 */ public class ParameterCheckUtils { private static Logger logger = LoggerFactory.getLogger(ParameterCheckUtils.class); public static void commonCheck(Object obj) throws IllegalAccessException { if (obj == null) { logger.error("obj can not be null!"); throw new BaseException("9999", "obj can not be null!"); } List<Field> fieldList = new ArrayList<Field>(); Class clazz = obj.getClass(); while (!Object.class.equals(clazz)) { fieldList.addAll(Arrays.asList(clazz.getDeclaredFields())); clazz = clazz.getSuperclass(); } for (Field field : fieldList) { field.setAccessible(true); ParameterAttr attr = field.getAnnotation(ParameterAttr.class); if (attr == null) { continue; } Object paramObj = field.get(obj); if (attr.isNecessary()) { if (paramObj == null || StringUtils.isBlank(paramObj.toString())) { logger.error("class={} field={} can not be null!", obj.getClass().getName(), field.getName()); throw new BaseException("9998", "field=" + field.getName() + " can not be null!"); } } if (attr.lengthLimit() > 0 && paramObj != null && StringUtils.isNotBlank(paramObj.toString())) { if (paramObj.toString().length() > attr.lengthLimit()) { logger.error("class={} field={} length is too long! limit={} but length={}", obj.getClass().getName(), field.getName(), attr.lengthLimit(), paramObj.toString().length()); throw new BaseException("9997", "field=" + field.getName() + " length is too long!"); } } } logger.info("commonCheck success!"); } public static void main(String[] args) throws IllegalAccessException { //正常数据 TestChildRequest request1 = new TestChildRequest(); request1.setName("王钢蛋"); request1.setAddress("aabbccddeeaabbc"); request1.setSchool("北京市智障二中"); ParameterCheckUtils.commonCheck(request1); //为空数据 try { ParameterCheckUtils.commonCheck(null); } catch (Exception e) { logger.error("error1 ", e); } //必填没传的数据 try { TestChildRequest request2 = new TestChildRequest(); request2.setName("王钢蛋"); request2.setAddress("aabbccddeeaabbc"); ParameterCheckUtils.commonCheck(request2); } catch (Exception e) { logger.error("error2 ", e); } //字段超长的数据 try { TestChildRequest request3 = new TestChildRequest(); request3.setName("王钢蛋"); request3.setAddress("aabbccddeeaabbcc"); request3.setSchool("北京市智障二中"); ParameterCheckUtils.commonCheck(request3); } catch (Exception e) { logger.error("error3 ", e); } } }
执行结果: