自定义校验注解

一般自定义校验注解需要已下三步:

1.编写校验注解 即类似@NotEmpty

2.编写自定义校验的逻辑实体类,这个类必须实现ConstraintValidator这个接口,这样才可以被注解用来校验。

3.编写具体的校验逻辑。

我们可以先观察下@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();
    }
}

我们编写的自定义注解类,也必须有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<T> 表示java类型
    // Class<K,V> 分别代表java键值中的key value
    // Class<E> 代表Element
    Class<? extends Payload>[] payload() default {};
}

编写校验注解的逻辑类,该类必须实现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);
    }
}

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

package com.zzidc.web.service;

/**
 * @ClassName IdCardValidatorService
 * @Description TODO
 * @Date 2019/3/29 17:34
 **/
public interface IdCardValidatorService {
    boolean volid(String value);
}
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);
    }
}

工具类:

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);
    }
}

 

在 Java 中编写自定义校验注解时,可以使用 `@ReportAsSingleViolation` 注解来指定只要有一个校验失败就返回结果,而不是等待所有的校验结果返回。同时,可以使用 `@javax.validation.constraints.Null` 和 `@javax.validation.constraints.NotNull` 注解来判断参数是否为 `null`。 具体来说,你可以按照以下步骤编写一个允许参数为空的自定义校验注解: 1. 定义注解 ```java @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {MyValidator.class}) @ReportAsSingleViolation public @interface MyAnnotation { String message() default "my message"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } ``` 2. 定义校验器 ```java public class MyValidator implements ConstraintValidator<MyAnnotation, String> { @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (value == null) { // 允许参数为空,直接返回 true return true; } // 对非空参数进行校验 boolean isValid = // 校验逻辑 if (!isValid) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("my message") .addConstraintViolation(); } return isValid; } } ``` 在校验器中,我们首先判断参数是否为 `null`,如果是,则直接返回 `true`,即认为校验通过。如果参数不为 `null`,则进行校验逻辑,如果校验失败,则使用 `context.buildConstraintViolationWithTemplate()` 方法构建校验失败的信息。 3. 在需要校验的参数上应用注解 ```java public void myMethod(@MyAnnotation String param) { // 方法逻辑 } ``` 在需要校验的参数上使用 `@MyAnnotation` 注解,即可触发自定义校验注解校验逻辑。如果参数为 `null`,则直接返回 `true`,否则进行校验逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值