相对于传统的流水账式的校验,使用注解好处很多,提高开发效率,减少出错率,极大的减少代码量,统一在实体类管理维护,直观清晰。

    以下是一个示例。 两个校验,1、校验值只能存在于指定的枚举值内 2、校验时间是否合理。
    第一步,自定义注解,起到标记作用。 (注解在这里只起到标记和设定参数的作用)

    1. /**
    2. * 类型枚举校验
    3. * @author caixl
    4. */
    5. @Retention(RetentionPolicy.RUNTIME)
    6. @Target(ElementType.FIELD)
    7. public @interface TypeEnumValid {
    8. public String value() default "";
    9. }
    1. /**
    2. 校验时间的合理性,如证件有效期必须在今天以后
    3. */
    4. @Retention(RetentionPolicy.RUNTIME)
    5. @Target(ElementType.FIELD)
    6. public @interface DateValid {
    7. public DateTypeEnum value() default DateTypeEnum.All;
    8. }
    9. ------另外一个类 DateTypeEnum的枚举 -----
    10. /**
    11. * Past 过去
    12. * @author caixl
    13. */
    14. public enum DateTypeEnum {
    15. Futher, TodateOrFuther, Todate, Past, TodateOrPast, All
    16. }

    第二步,在实体类标记某个字段。 如下片段,两种类型的校验都用到了。

    1. @DateValid(DateTypeEnum.Futher)
    2. @Size(max=10)
    3. @NotEmpty
    4. private String doc_expire;
    5. @TypeEnumValid("0;1;2;3;4;5")
    6. private int business_type;
    7. @Size(max=80)
    8. @NotEmpty
    9. private String address;
    10. @TypeEnumValid("1;2")
    11. private int bpremises_type;
    12. @NotEmpty
    13. @Size(max=20)
    14. @TypeEnumValid("1;2;3;4;5;6;7;8;9;10")

    第三步,对所有自定义注解的校验逻辑, 这里抽象出来为一个方法。 主要用到反射,和固定校验逻辑。

    1. /**
    2. * 对自定义的注解进行校验
    3. * @author caixl
    4. */
    5. @Slf4j
    6. public class AnnotationValid {
    7. public static String valid(Object object) {
    8. StringBuffer errorStr = new StringBuffer();
    9. try {
    10. errorStr.append(vaildDateAnnotation(object));
    11. } catch (Exception e) {
    12. log.info("校验时发生异常", e);
    13. errorStr.append("校验时发生异常");
    14. }
    15. return errorStr.toString();
    16. }
    17. public static String vaildDateAnnotation(Object object) {
    18. StringBuffer errorStr = new StringBuffer();
    19. Field[] fields = object.getClass().getDeclaredFields();
    20. for (Field field : fields) {
    21. String fieldname = field.getName();
    22. Annotation[] allFAnnos= field.getAnnotations();
    23. if(null ==allFAnnos || allFAnnos.length ==0) continue;
    24. //开始时间格式的校验
    25. DateValid dateValid = field.getAnnotation(DateValid.class);
    26. if(null != dateValid) {
    27. try {
    28. field.setAccessible(true);
    29. String fieldval = (String)field.get(object);
    30. if(! StringUtils.hasLength(fieldval)) continue; //空则不做校验
    31. if(! DateUtil.validDateFormat(fieldval)) {
    32. errorStr.append(fieldname+"日期格式不正确");
    33. }else if(dateValid.value() == DateTypeEnum.Futher) {
    34. if(!(DateUtil.dateMinusNowDate(fieldval) > 0)) {
    35. errorStr.append(fieldname+"日期需大于今天;");
    36. }
    37. }else if(dateValid.value() == DateTypeEnum.TodateOrFuther) {
    38. if(!(DateUtil.dateMinusNowDate(fieldval) >= 0)){
    39. errorStr.append(fieldname+"日期需等于或大于今天;");
    40. }
    41. }else if(dateValid.value() == DateTypeEnum.Past) {
    42. if(!(DateUtil.dateMinusNowDate(fieldval) < 0)) {
    43. errorStr.append(fieldname+"日期需小于今天;");
    44. }
    45. }else if(dateValid.value() == DateTypeEnum.TodateOrPast) {
    46. if(!(DateUtil.dateMinusNowDate(fieldval) <= 0)) {
    47. errorStr.append(fieldname+"日期需小于或等于今天;");
    48. }
    49. }
    50. } catch (Exception e) {
    51. log.info("日期校验异常", e);
    52. errorStr.append(fieldname+"日期校验异常");
    53. }
    54. }
    55. //校验枚举
    56. TypeEnumValid enumValid = field.getAnnotation(TypeEnumValid.class);
    57. if(null != enumValid) {
    58. try {
    59. field.setAccessible(true);
    60. Object fieldObject = field.get(object);
    61. String fieldval = fieldObject.toString();
    62. /*
    63. * if((fieldObject.getClass()). equals(String.class)) { fieldval =
    64. * (String)fieldObject; }else
    65. * if((fieldObject.getClass()).equals(Integer.class)){ fieldval =
    66. * ((Integer)fieldObject).toString() ; }
    67. */
    68. if(! StringUtils.hasLength(fieldval)) continue; //空则不做校验
    69. String annoStr = enumValid.value();
    70. String[] allEnum = annoStr.split(";");
    71. if(! vaildStrInArr(fieldval,allEnum)) {
    72. errorStr.append(fieldname+"不在取值范围内;");
    73. }
    74. } catch (Exception e) {
    75. log.info("枚举校验异常", e);
    76. errorStr.append(fieldname+ "枚举校验异常");
    77. }
    78. }
    79. }
    80. return errorStr.toString();
    81. }
    82. public static boolean vaildStrInArr(String str , String[] arr) {
    83. if(!StringUtils.hasText(str ) || null ==arr || ! (arr.length>0) ) {
    84. return false;
    85. }
    86. for(String arrstr : arr) {
    87. if(null != arrstr && str.equals(arrstr)) {
    88. return true;
    89. }
    90. }
    91. return false;
    92. }
    93. }

    第四步,在业务代码中,使用我们前面封装的内容。 一行代码即可,无错误则返回的是一个空字符串。

    String validMsg = AnnotationValid.valid(sendMerchantVo);  //注解校验,这里传入的是要校验的实体类
    

    另外附上DateUtil的内容,上面用到了,在另外一个文件中。
    https://www.yuque.com/caixl/java/wg2n4r