您好,登錄后才能下訂單哦!
小編給大家分享一下ConstraintValidator類怎么實現自定義注解校驗前端傳參,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
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 "數字不合法,不在要求的取值范圍之內"; /** * 標識要校驗的值所屬組,這個后面詳細解釋 * */ Class<?>[] groups() default {}; /** * 這個字段一般不需要我們關注 * */ Class<? extends Payload>[] payload() default {}; }
注意到剛才注解中的@Constraint注解了嗎
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) { // 如果是必選的話,假設為我們傳遞的參數為空那肯定不行 if (require) { if (number == null) { return false; } return valueList.contains(number); } else { // 如果不為必選參數,為空返回true,不為空還是得校驗 if (StringUtils.isEmpty(number)) { return true; } else { return valueList.contains(number); } } } }
增強類繼承ConstraintValidator類,實現的initialize()方法是初始化方法,啥意思呢,啥目的呢?在你真正執行校驗之前,可以做一些準備性工作,發生在要校驗的值上面的注解的IllegalNumber 已經給咱們傳進來了。我做的初始化工作就是load一下Integer類型的可選值,方便一會執行真正的校驗。
然后在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數據并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; }
注意,如果說前端傳遞數據不符合注解的校驗,其實是會拋出異常的來自@Constraint注解實現的注解都有此特點,例如@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(); } }
下面測試一下。打開postman。直接干!取值的限定是0、1、2。咱們先試下錯誤的
ok,再試下正確的
groups參數,代表所屬組的意思。演示下怎么用,大家也就知道這個參數啥意思了。 建立Group1接口
public interface Group1 { }
建立Group2接口
public interface Group2 { }
給TestVO增加一個參數,方便一會進行比較
@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; }
使用注解的時候標明所屬組:
接口處也進行標識:
現在咱們分別測試下兩個接口,看groups參數是否能生效
test2接口
test3接口
ok,相信大家對此參數已經掌握了,這里不再多余贅述。
以上是“ConstraintValidator類怎么實現自定義注解校驗前端傳參”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。