最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

ConstraintValidator類如何實(shí)現(xiàn)自定義注解校驗(yàn)前端傳參

 更新時(shí)間:2021年06月18日 10:49:42   作者:追夢(mèng)狗蛋  
這篇文章主要介紹了ConstraintValidator類實(shí)現(xiàn)自定義注解校驗(yàn)前端傳參的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

前言

今天項(xiàng)目碰到這么一個(gè)問(wèn)題,前端傳遞的json格式到我的微服務(wù)后端轉(zhuǎn)換為vo類,其中有一個(gè)Integer的字段后端希望它在固定的幾個(gè)數(shù)里面取值,例如只能取值1、2、4。

一般咱們的思路是啥呢,找一些spring為我們提供的類似@Length、@NotBlank這些注解加在參數(shù)上面。

像下面這樣

在這里插入圖片描述

不過(guò)我這個(gè)校驗(yàn)一時(shí)間想不起來(lái)用哪個(gè)注解了,咋整呢?行吧,咱不求人,自己實(shí)現(xiàn)一個(gè)。

補(bǔ)充一句話,千萬(wàn)別直接拿著實(shí)體類往后傳遞到service層校驗(yàn)哈,太low了這樣子。

一、利用@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 {
    /**
     * 允許前端取的幾個(gè)值
     * 
     */
    int[] acceptValues();
    /**
     * 標(biāo)識(shí)此字段是否為必選項(xiàng)
     * 
     */
    boolean required() default true;
 
    /**
     * 標(biāo)識(shí)此字段是否為必選項(xiàng)
     * 
     */
    String message() default "數(shù)字不合法,不在要求的取值范圍之內(nèi)";
 
    /**
     * 標(biāo)識(shí)要校驗(yàn)的值所屬組,這個(gè)后面詳細(xì)解釋
     * 
     */
    Class<?>[] groups() default {};
    
    /**
     * 這個(gè)字段一般不需要我們關(guān)注
     * 
     */
    Class<? extends Payload>[] payload() default {};
}

二、增強(qiáng)注解

1.編寫增強(qiáng)類

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

在這里插入圖片描述

validatedBy屬性標(biāo)識(shí)這個(gè)注解要被哪個(gè)類所增強(qiáng),我們把增強(qiáng)類IllegalNumberValidator定義出來(lái)

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è)為我們傳遞的參數(shù)為空那肯定不行
        if (require) {
            if (number == null) {
                return false;
            }
            return valueList.contains(number);
        } else {
            // 如果不為必選參數(shù),為空返回true,不為空還是得校驗(yàn)
            if (StringUtils.isEmpty(number)) {
                return true;
            } else {
                return valueList.contains(number);
            }
        }
    }
}

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

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

定義一個(gè)前端傳遞的類,方便調(diào)試注解

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 = "請(qǐng)正確取值")
    private Integer number;
    @NotNull
    @Length(min = 1)
    private String password;
}

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

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

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

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.測(cè)試效果

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

在這里插入圖片描述

ok,再試下正確的

在這里插入圖片描述

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

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

public interface Group1 {
}

建立Group2接口

public interface Group2 {
}

給TestVO增加一個(gè)參數(shù),方便一會(huì)進(jìn)行比較

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

使用注解的時(shí)候標(biāo)明所屬組:

在這里插入圖片描述

接口處也進(jìn)行標(biāo)識(shí):

在這里插入圖片描述

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

test2接口

在這里插入圖片描述

test3接口

在這里插入圖片描述

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

總結(jié)

本篇介紹了自定義注解的另外一種手法,其實(shí)還有許許多多的手法,例如利用反射實(shí)現(xiàn)、利用攔截器實(shí)現(xiàn)等等。遇見的時(shí)候咱們?cè)俳榻B。 以上僅為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家

相關(guān)文章

  • Springboot事件和bean生命周期執(zhí)行機(jī)制實(shí)例詳解

    Springboot事件和bean生命周期執(zhí)行機(jī)制實(shí)例詳解

    這篇文章主要介紹了Springboot事件和bean的生命周期執(zhí)行機(jī)制,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • SpringBoot之跨域過(guò)濾器配置允許跨域訪問(wèn)方式

    SpringBoot之跨域過(guò)濾器配置允許跨域訪問(wèn)方式

    這篇文章主要介紹了SpringBoot之跨域過(guò)濾器配置允許跨域訪問(wèn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 關(guān)于ResponseEntity類和HttpEntity及跨平臺(tái)路徑問(wèn)題

    關(guān)于ResponseEntity類和HttpEntity及跨平臺(tái)路徑問(wèn)題

    這篇文章主要介紹了關(guān)于ResponseEntity類和HttpEntity及跨平臺(tái)路徑問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • java ssm框架實(shí)現(xiàn)分頁(yè)功能的示例代碼(oracle)

    java ssm框架實(shí)現(xiàn)分頁(yè)功能的示例代碼(oracle)

    這篇文章主要介紹了java ssm框架實(shí)現(xiàn)分頁(yè)功能的示例代碼(oracle),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • 使用Lombok子類繼承父類,父類屬性不生效問(wèn)題及解決

    使用Lombok子類繼承父類,父類屬性不生效問(wèn)題及解決

    在使用Lombok庫(kù)時(shí),若子類繼承父類,父類的屬性可能不會(huì)自動(dòng)生效,為解決此問(wèn)題,可通過(guò)在父類上添加@Getter和@Setter注解,或使用@SuperBuilder注解來(lái)確保父類屬性在子類中有效,同時(shí),需注意確保Lombok版本一致且正確配置了相關(guān)插件
    2024-10-10
  • Java-Io-RandomAccessFile任意位置讀寫數(shù)據(jù)的操作小結(jié)

    Java-Io-RandomAccessFile任意位置讀寫數(shù)據(jù)的操作小結(jié)

    RandomAccessFile類支持隨機(jī)訪問(wèn)方式,可以跳轉(zhuǎn)到文件的任意位置讀寫數(shù)據(jù),這個(gè)類在文件隨機(jī)讀取時(shí)有很大的優(yōu)勢(shì),可利用多線程完成對(duì)一個(gè)大文件的讀寫,本文給大家介紹Java-Io-RandomAccessFile(任意位置讀寫數(shù)據(jù))的相關(guān)知識(shí),需要的朋友可以參考下
    2022-05-05
  • 5個(gè)主流的Java開源IDE工具詳解

    5個(gè)主流的Java開源IDE工具詳解

    這篇文章主要介紹了5個(gè)主流的Java開源IDE工具,無(wú)論如何,Java在當(dāng)今使用的編程語(yǔ)言中始終排在前三名,在TIOBE索引中涉及700萬(wàn)到1000萬(wàn)的程序員和開發(fā)者
    2020-07-07
  • SpringBoot配置Redis連接池的實(shí)現(xiàn)步驟

    SpringBoot配置Redis連接池的實(shí)現(xiàn)步驟

    本文主要介紹了SpringBoot配置Redis連接池的實(shí)現(xiàn)步驟,詳細(xì)的講解了連接池的作用、配置方式、連接池參數(shù)說(shuō)明,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • 基于TCP通信丟包原因總結(jié)(推薦)

    基于TCP通信丟包原因總結(jié)(推薦)

    下面小編就為大家?guī)?lái)一篇基于TCP通信丟包原因總結(jié)(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • Java神操作:圖片快速轉(zhuǎn)換PDF秘籍

    Java神操作:圖片快速轉(zhuǎn)換PDF秘籍

    想掌握J(rèn)ava神操作,將圖片快速轉(zhuǎn)換成PDF嗎?這份秘籍將一步步引導(dǎo)你,輕松實(shí)現(xiàn)這一目標(biāo),別等了,跟著我們一起,解鎖這項(xiàng)超實(shí)用技能吧!
    2024-02-02

最新評(píng)論

清流县| 临安市| 两当县| 台州市| 平塘县| 云阳县| 枣阳市| 长治县| 包头市| 凌云县| 日喀则市| 明溪县| 安仁县| 高阳县| 林口县| 嘉善县| 唐河县| 兴山县| 遂溪县| 乐亭县| 新乡县| 嘉峪关市| 锡林浩特市| 大洼县| 凉山| 中山市| 巴青县| 金堂县| 新巴尔虎右旗| 湘潭市| 都昌县| 麟游县| 浦城县| 松溪县| 乐东| 乐平市| 永平县| 龙海市| 松江区| 启东市| 雅安市|