溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ConstraintValidator類怎么實現(xiàn)自定義注解校驗前端傳參

發(fā)布時間:2021-06-18 13:44:01 來源:億速云 閱讀:494 作者:小新 欄目:開發(fā)技術

小編給大家分享一下ConstraintValidator類怎么實現(xiàn)自定義注解校驗前端傳參,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

一、利用@Constraint定義注解

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;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
        validatedBy = {IllegalNumberValidator.class}
)
public @interface IllegalNumber {
    /**
     * 允許前端取的幾個值
     * 
     */
    int[] acceptValues();
    /**
     * 標識此字段是否為必選項
     * 
     */
    boolean required() default true;
 
    /**
     * 標識此字段是否為必選項
     * 
     */
    String message() default "數(shù)字不合法,不在要求的取值范圍之內";
 
    /**
     * 標識要校驗的值所屬組,這個后面詳細解釋
     * 
     */
    Class<?>[] groups() default {};
    
    /**
     * 這個字段一般不需要我們關注
     * 
     */
    Class<? extends Payload>[] payload() default {};
}

二、增強注解

1.編寫增強類

注意到剛才注解中的@Constraint注解了嗎

ConstraintValidator類怎么實現(xiàn)自定義注解校驗前端傳參

validatedBy屬性標識這個注解要被哪個類所增強,我們把增強類IllegalNumberValidator定義出來

import com.google.common.collect.Lists;
import org.springframework.util.StringUtils;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class IllegalNumberValidator implements ConstraintValidator<IllegalNumber, Integer> {
    private final List<Integer> valueList = Lists.newArrayList();
    private boolean require = false;
    @Override
    public void initialize(IllegalNumber constraintAnnotation) {
        require = constraintAnnotation.required();
        int[] ints = constraintAnnotation.acceptValues();
        for (int anInt : ints) {
            valueList.add(anInt);
        }
    }
    @Override
    public boolean isValid(Integer number, ConstraintValidatorContext constraintValidatorContext) {
        // 如果是必選的話,假設為我們傳遞的參數(shù)為空那肯定不行
        if (require) {
            if (number == null) {
                return false;
            }
            return valueList.contains(number);
        } else {
            // 如果不為必選參數(shù),為空返回true,不為空還是得校驗
            if (StringUtils.isEmpty(number)) {
                return true;
            } else {
                return valueList.contains(number);
            }
        }
    }
}

增強類繼承ConstraintValidator類,實現(xiàn)的initialize()方法是初始化方法,啥意思呢,啥目的呢?在你真正執(zhí)行校驗之前,可以做一些準備性工作,發(fā)生在要校驗的值上面的注解的IllegalNumber 已經(jīng)給咱們傳進來了。我做的初始化工作就是load一下Integer類型的可選值,方便一會執(zhí)行真正的校驗。

然后在isValid()方法中你可以做真正的校驗了,很簡單,我看下傳遞的Integer類型的值是不是acceptValues里面的可選值就行了。

定義一個前端傳遞的類,方便調試注解

import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
@Data
public class TestVO {
    @NotNull
    @IllegalNumber(acceptValues = {0, 1,2},required = true,message = "請正確取值")
    private Integer number;
    @NotNull
    @Length(min = 1)
    private String password;
}

定義接口,用來接收前端傳遞的json數(shù)據(jù)并parse為TestVO類

/**
     * 測試自定義注解
     *
     * @param vo json將會映射的實體
     * @return 默認信息
     */
    @PostMapping(value = "/v1.0/test2", name = "測試自定義注解")
    public String test2(@Valid @RequestBody TestVO vo) {
        log.info("get vo success , detail message is:{}", vo);
        return RETURN_MESSAGE;
    }

注意,如果說前端傳遞數(shù)據(jù)不符合注解的校驗,其實是會拋出異常的來自@Constraint注解實現(xiàn)的注解都有此特點,例如@Length、@Max等。咱們需要在異常拋出的時候給出攔截 這里咱們做一個通用攔截:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import java.util.Objects;
import javax.validation.ConstraintViolationException;
@ControllerAdvice
public class RestResponseEntityExceptionHandler {
    private static final Logger LOG = LoggerFactory.getLogger(RestResponseEntityExceptionHandler.class);
    @Autowired
    private ApplicationContext applicationContext;
    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public String handleConstraintViolationException(ConstraintViolationException e) {
        LOG.info("ConstraintViolationException intercept success:{}", e.getMessage());
        return e.getMessage();
    }
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public String handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        LOG.info("MethodArgumentNotValidException intercept success:{}", e.getMessage());
        return Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
    }
}

2.測試效果

下面測試一下。打開postman。直接干!取值的限定是0、1、2。咱們先試下錯誤的

ConstraintValidator類怎么實現(xiàn)自定義注解校驗前端傳參

ok,再試下正確的

ConstraintValidator類怎么實現(xiàn)自定義注解校驗前端傳參

3.注解中的groups參數(shù)詳解

groups參數(shù),代表所屬組的意思。演示下怎么用,大家也就知道這個參數(shù)啥意思了。 建立Group1接口

public interface Group1 {
}

建立Group2接口

public interface Group2 {
}

給TestVO增加一個參數(shù),方便一會進行比較

@Data
public class TestVO {
    @NotNull
    @IllegalNumber(acceptValues = {0, 1,2},required = true,message = "請正確取值",groups = Group1.class)
    private Integer number;
    @NotNull
    @IllegalNumber(acceptValues = {0, 1,2},required = true,message = "請正確取值ha",groups = Group2.class)
    private Integer number2;
    @NotNull
    @Length(min = 1)
    private String password; 
}

使用注解的時候標明所屬組:

ConstraintValidator類怎么實現(xiàn)自定義注解校驗前端傳參

接口處也進行標識:

ConstraintValidator類怎么實現(xiàn)自定義注解校驗前端傳參

現(xiàn)在咱們分別測試下兩個接口,看groups參數(shù)是否能生效

test2接口

ConstraintValidator類怎么實現(xiàn)自定義注解校驗前端傳參

test3接口

ConstraintValidator類怎么實現(xiàn)自定義注解校驗前端傳參

ok,相信大家對此參數(shù)已經(jīng)掌握了,這里不再多余贅述。

以上是“ConstraintValidator類怎么實現(xiàn)自定義注解校驗前端傳參”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI