• 【java】实现自定义注解校验——方法二


    自定义注解校验的实现步骤:

    1.创建注解类,编写校验注解,即类似@NotEmpty注解
    2.编写自定义校验的逻辑实体类,编写具体的校验逻辑。(这个类可以实现ConstraintValidator这个接口,让注解用来校验)
    3.开启使用自定义注解进行校验。

    第一种实现自定义注解的方式:https://blog.csdn.net/m0_46459413/article/details/134257302?spm=1001.2014.3001.5502

    第二种实现自定义注解的方式:

    一、创建注解类:

    1、创建类时,选择Annotation类型

    在这里插入图片描述

    2、编写注解类

    在这里插入图片描述

    如图是我们自定义的一个年龄注解,message是该注解校验失败时的提示信息,default是默认值,我们可以重写该提示信息。下面两行代码是自定义注解需要加上的,这里不作研究。

    二、自定义注解校验逻辑的实现:

    这里有两种实现方式,
    一种是当注解仅仅作用在字段(属性)上生效时:可以在工具类中编写方法进行逻辑校验;
    另一种:使用@Constraint注解,指明了校验类,进行校验,这里只实现第二种。

    第二种:使用@Constraint注解,指明校验类,进行校验

    EX:自定的Age注解上面有一个@Constraint注解,该注解指明了校验类,我们点进MyAnnoationValidator类看一下
    在这里插入图片描述

    可以看到校验类都必须要实现ConstraintValidator接口,并且重写接口中的两个方法。

    接口上是有泛型的,第一个泛型代表了我们这个校验类是哪个注解的校验类,第二个泛型代表该注解校验的参数是什么类型,第二个注解默认是Object类型,我们改成了Integer类型,
    initialize方法 是该校验类的初始化方法,在这个方法里,我们可以对传进来的参数作一些处理。
    isValid方法 就是注解类型的核心校验方法,校验通过与否就是看该方法的返回值是true还是false,true就代表校验通过,false就代表校验失败

    三、使用自定义注解:

    自定义校验注解在代码中的应用

    1、在dto中使用:

    定义一个实体类User
    在这里插入图片描述

    2、在代码中使用:

    定义一个Controller,使用@Valid注解我们的User类,@Valid注解没有实际的注解体,这个注解的作用就是使我们的@Age注解起作用。
    后面的BindingResult类的作用是当注解校验失败时,我们可以手动去处理。如果不加这个类的话,注解校验失败,会直接返回http的400错误码。加上这个类,我们可以自己自定义错误信息,然后返回,此时的http状态码为200
    在这里插入图片描述

    3、@valid注解

    1、@valid注解作用

    @valid注解主要用于数据校验,在接口的入参实体类前添加@Valid注解,这时实体类会开启一个校验的功能;然后在入参实体类中的属性上,添加不同的注解(例如@NotBlank注解)来完成不同的校验规则。

    2、@valid注解的使用
    a、在实体类中添加@valid相关注解

    使用@Valid相关注解非常简单,只需要在参数的实体类属性上添加如@NotBlank,@Max,@Min等注解对字段进行限制。如下:

    public class User{
        @NotBlank(message = "姓名不为空")
        private String username;
        @NotBlank(message = "密码不为空")
        private String password;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果嵌套了实体对象,则需要在最外层属性上添加@Valid注解,否则嵌套实体对象中的验证不生效

    public class User{
        @NotBlank(message = "姓名不为空")
        private String username;
        @NotBlank(message = "密码不为空")
        private String password;
        //嵌套必须加@Valid,否则嵌套中的验证不生效
        @Valid
        @NotNull(message = "用户信息不能为空")
        private UserInfo userInfo;
    }
    
    public class UserInfo {
        @NotBlank(message = "年龄不为空")
        @Max(value = 18,message = "不超过18岁")
        private String age;
        @NotBlank(message = "性别不为空")
        private String gender;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    b、在接口中添加@valid注解

    在controller类中添加接口,POST方法中接收设置了@Valid相关注解的实体对象,然后再参数中添加@Valid注解来开启效验功能,需要注意的是,@Valid对Get请求中接收的平面参数请求无效。

    @RestController
    public class TestController {
        @PostMapping("/user")
        public String addUserInfo(@Valid @RequestBody User user){
            return "调用成功";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    参考链接:https://blog.csdn.net/weixin_43400432/article/details/126159450

    四、观察仿照 @NotEmpty注解,编写自定义校验注解

    1、观察下@NotEmpty 注解:

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
     
    package org.hibernate.validator.constraints;
     
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import javax.validation.Constraint;
    import javax.validation.Payload;
    import javax.validation.ReportAsSingleViolation;
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;
    import javax.validation.constraintvalidation.SupportedValidationTarget;
    import javax.validation.constraintvalidation.ValidationTarget;
     
    @Documented
    @Constraint(
        validatedBy = {}
    )
    @SupportedValidationTarget({ValidationTarget.ANNOTATED_ELEMENT})
    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @ReportAsSingleViolation
    @NotNull
    @Size(
        min = 1
    )
    public @interface NotEmpty {
        String message() default "{org.hibernate.validator.constraints.NotEmpty.message}";
     
        Class<?>[] groups() default {};
     
        Class<? extends Payload>[] payload() default {};
     
        @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        public @interface List {
            NotEmpty[] value();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    2、编写身份证校验自定义注解类,也必须有message、groups、payload.

    package com.zzidc.web.validator;
     
    import javax.validation.Constraint;
    import javax.validation.Payload;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
     
    /*
     * @Description //TODO
     * @Date 2019/3/29 17:22
     * @Param
     * @return
     **/
    //注解是指定当前自定义注解可以使用在哪些地方,这里仅仅让他可以使用在方法上和属性上;
    @Target({ElementType.METHOD,ElementType.FIELD})
    //指定当前注解保留到运行时;
    @Retention(RetentionPolicy.RUNTIME)
    //指定了当前注解使用哪个类来进行校验。
    @Constraint(validatedBy = IdCardValidator.class) //
    public @interface IsIdCard {
        String message();
        // default 关键字 接口中被default修饰的方法,在类实现这个接口时不必必须实现这个方法
        Class<?>[] groups() default { };
        // Class 表示不确定的java类型
        // Class 表示java类型
        // Class 分别代表java键值中的key value
        // Class 代表Element
        Class<? extends Payload>[] payload() default {};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    3. 编写校验注解的逻辑类:IdCardValidator.class,该类必须实现ConstraintValidator

    package com.zzidc.web.validator;
     
    import com.zzidc.web.service.IdCardValidatorService;
    import org.springframework.beans.factory.annotation.Autowired;
     
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
     
    /**
     * @ClassName IdCardValidator
     * @Description  校验注解的校验逻辑
     * @Date 2019/3/29 17:23
     **/
    public class IdCardValidator implements ConstraintValidator<IsIdCard,String>{
        @Autowired
        private IdCardValidatorService idCardValidatorService;
        /*
         * @Description 校验前的初始化工作
         * @Date 2019/3/29 17:27
         * @Param [isIdCard]
         * @return void
         **/
        @Override
        public void initialize(IsIdCard isIdCard) {
            String message = isIdCard.message();
            System.out.println("自定义的message信息是:".concat(message));
        }
    
    
     
        /*
         * @Description 具体的校验逻辑
         * @Date 2019/3/29 17:29
         * @Param [s, constraintValidatorContext]
         * @return boolean
         **/
        @Override
        public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
            return idCardValidatorService.volid(s);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    我们将具体校验逻辑抽出来,抽成一个service:

    package com.zzidc.web.service;
     
    /**
     * @ClassName IdCardValidatorService
     * @Description TODO
     * @Date 2019/3/29 17:34
     **/
    public interface IdCardValidatorService {
        boolean volid(String value);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    service实现类:

    package com.zzidc.web.service.impl;
     
    import com.zzidc.web.service.IdCardValidatorService;
    import com.zzidc.web.utils.IdCardUtils;
    import org.springframework.stereotype.Service;
     
    /**
     * @ClassName IdCardValidatorServiceImpl
     * @Description TODO
     * @Date 2019/3/29 17:35
     **/
    @Service
    public class IdCardValidatorServiceImpl implements IdCardValidatorService {
        @Override
        public boolean volid(String value) {
            return IdCardUtils.isValidIdCard(value);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    身份证工具校验类:

    package com.zzidc.web.utils;
     
    import org.apache.commons.lang3.StringUtils;
     
    /**
     * @ClassName IdCardUtils
     * @Description TODO
     * @Date 2019/3/29 17:37
     **/
    public class IdCardUtils {
        public static boolean isValidIdCard(String value){
            String regex = "^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$";
            if (StringUtils.isBlank(value)) {
                return false;
            }
            return value.matches(regex);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    C语言内功修炼【整型在内存中的存储】
    【每日一题Day352】LC1726同积元组 | 哈希表+排列组合
    【老生谈算法】matlab遗传算法工具箱源码——遗传算法
    云计算技术 — 混合云 — 技术架构
    判断点是否在点组成的封闭区域内c++
    CSS中的定位
    推荐计划为什么有效?需要推荐计划的10个原因
    Linux区分文件类型,file指令,目录权限,umask掩码,共享文件,Linux中的一些有趣指令
    亚马逊平台的优势有哪些?
    基于uwb和IMU融合的三维空间定位算法matlab仿真
  • 原文地址:https://blog.csdn.net/m0_46459413/article/details/134278359