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

SpringBoot參數(shù)校驗(yàn)@Validated、@Valid方式詳解

 更新時(shí)間:2025年11月13日 09:41:25   作者:我認(rèn)不到你  
Spring?Boot中使用@Validated和@Valid進(jìn)行參數(shù)校驗(yàn),確保數(shù)據(jù)的完整性和安全性,@Validated適用于分組校驗(yàn),而@Valid則更為通用,通過(guò)自定義注解和枚舉校驗(yàn)注解處理類(lèi),可以實(shí)現(xiàn)更復(fù)雜的驗(yàn)證邏輯

SpringBoot參數(shù)校驗(yàn)@Validated、@Valid(javax.validation)

一、應(yīng)用場(chǎng)景

在實(shí)際開(kāi)發(fā)中,前端校驗(yàn)并不安全,任何人都可以通過(guò)接口來(lái)調(diào)用我們的服務(wù),就算加了一層token的校驗(yàn),有心人總會(huì)轉(zhuǎn)空子,來(lái)傳各式各樣錯(cuò)誤的參數(shù),如果后端不校驗(yàn),導(dǎo)致數(shù)據(jù)庫(kù)數(shù)據(jù)混亂、特別是關(guān)于金額的數(shù)據(jù),可能一個(gè)接口把公司都給干倒了

二、原生參數(shù)校驗(yàn)

返回類(lèi)(可以不用看)

/**
 * 用于返回
 * @param <T>
 */
@ApiModel("統(tǒng)一返回類(lèi)")
public class Results<T> {
    public static final String ERROR = "500";
    public static final String SUCCESS = "200";

    /**
     * 返回碼
     */
    @ApiModelProperty("返回碼,正確碼為:200")
    private String resCode ;

    /**
     * 返回消息
     */
    @ApiModelProperty("返回消息")
    private String msg ;

    /**
     * 返回實(shí)體
     */
    @ApiModelProperty("返回實(shí)體")
    private T obj;

    public static <T> Results<T> success(){
        return success(SUCCESS,"成功",null);
    }

    public static <T> Results<T> success(String msg){
        return success(SUCCESS,msg,null);
    }

    public static <T> Results<T> success(T obj){
        return success(SUCCESS,"成功",obj);
    }

    public static <T> Results<T> success(String msg,T obj){
        return success(SUCCESS,msg,obj);
    }

    public static <T> Results<T> success(String resCode,String msg,T obj){
        Results<T> result = new Results<T>();
        result.setResCode(resCode);
        result.setMsg(msg);
        result.setObj(obj);
        return result;
    }

    public static <T> Results<T> failed() {
        return failed(ERROR,"失敗",null);
    }

    public static <T> Results<T> failed(String msg) {
        return failed(ERROR,msg,null);
    }

    public static <T> Results<T> failed(String msg,T obj) {
        return failed(ERROR,msg,obj);
    }

    public static <T> Results<T> failed(String resCode,String msg) {
        return failed(resCode,msg,null);
    }

    public static <T> Results<T> failed(Integer resCode,String msg) {
        return failed(String.valueOf(resCode),msg);
    }

    public static <T> Results<T> failed(String resCode,String msg,T obj) {
        Results<T> result = new Results<T>();
        result.setResCode(resCode);
        result.setMsg(msg);
        result.setObj(obj);
        return result;
    }

    public static <T> Results<T> failedNoPermission() {
        return failed(90005,"沒(méi)有權(quán)限");
    }
    public static <T> Results<T> failedNoPermission(String msg) {
        return failed(90005,msg);
    }


    public static <T> Results<T> failedParameterException() {
        return failed(90004,"參數(shù)異常");
    }
    public static <T> Results<T> failedParameterException(String msg) {
        return failed(90004,msg);
    }

    public static <T> Results<T> failedLoginException() {
        return failed(90002,"登錄失敗");
    }
    public static <T> Results<T> failedLoginException(String msg) {
        return failed(90002,msg);
    }

    public String getResCode() {
        return resCode;
    }

    public void setResCode(String resCode) {
        this.resCode = resCode;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }

    @Override
    public String toString() {
        return "Results{" +
                "resCode='" + resCode + '\'' +
                ", msg='" + msg + '\'' +
                ", obj=" + obj +
                '}';
    }
}

實(shí)體類(lèi)

@ApiModel("測(cè)試 validation 入?yún)?)
@Data
public class TestDto {
    @ApiModelProperty(value = "名字",required = true)
    private String name;
    @ApiModelProperty(value = "年齡",required = true)
    private Integer age;
    @ApiModelProperty(value = "愛(ài)好",required = true)
    private List<String> hobbies;
}

服務(wù)層(為了方便,我直接跟Controller寫(xiě)在一起了)

我們可以看見(jiàn)如果參數(shù)過(guò)大,要一個(gè)一個(gè)篩選條件十分浪費(fèi)時(shí)間

@RestController
// lombok 的日志注解
@Slf4j
// swagger 的注解
@Api("測(cè)試")
public class TestController {

    @PostMapping("/testValidation")
	// swagger 的注解
    @ApiOperation("測(cè)試 validation")
    public Results testValidation(@RequestBody TestDto dto){
        try {
            log.info("test 入?yún)?dto={}",dto);
            // 這要一個(gè)一個(gè)的塞,很浪費(fèi)時(shí)間
            if (dto.getName() == null || "".equals(dto.getName().trim())){
                return Results.failed("名字不能為空");
            }
            if (dto.getAge() == null){
                return Results.failed("年齡不能為空");
            }
            if (dto.getHobbies() == null || dto.getHobbies().size() == 0){
                return Results.failed("愛(ài)好不能為空");
            }
            return Results.success();
        } catch (Exception e) {
            log.error("test 報(bào)錯(cuò)",e);
            return Results.failed();
        }
    }
}

三、使用javax.validation進(jìn)行參數(shù)校驗(yàn)

導(dǎo)包

        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

全局異常處理類(lèi)

springboot開(kāi)發(fā)中,在進(jìn)行 入?yún)⑿r?yàn) 時(shí),會(huì)拋出異常,最終全局統(tǒng)一捕獲異常。

  • 表單綁定到 java bean 出錯(cuò)時(shí),會(huì)拋出 BindException 異常
  • 將請(qǐng)求體解析并綁定到 java bean 時(shí),如果出錯(cuò),則拋出 MethodArgumentNotValidException 異常
  • 普通參數(shù)(非 java bean)校驗(yàn)出錯(cuò)時(shí),會(huì)拋出 ConstraintViolationException 異常
@RestControllerAdvice
public class ExceptionControllerAdvice {

    /**
     * 將請(qǐng)求體解析并綁定到 java bean 時(shí),如果出錯(cuò)
     * 表單綁定到 java bean 出錯(cuò)
     * 校驗(yàn)參數(shù) @RequestBody 時(shí)的異常
     * 注意 @Validated 需要放在 自定義實(shí)體類(lèi)(入?yún)ⅲ?的類(lèi)上
     * 例如 :
     * public Results testUpdate(@Validated(Update.class) @RequestBody TestDto dto){}
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Results MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        // 從異常對(duì)象中拿到ObjectError對(duì)象
        BindingResult br = e.getBindingResult();
        if (br.hasFieldErrors()) {
            List<FieldError> fieldErrorList = br.getFieldErrors();
            List<String> errors = new ArrayList<>(fieldErrorList.size());
            for (FieldError error : fieldErrorList) {
                errors.add(error.getField() + ":" + error.getDefaultMessage());
            }
            // 然后提取錯(cuò)誤提示信息進(jìn)行返回
            return Results.failed(errors.toString());
        }
        // 然后提取錯(cuò)誤提示信息進(jìn)行返回
        return Results.failed("校驗(yàn)錯(cuò)誤");
    }

    /**
     * 表單綁定到 java bean 出錯(cuò)
     *
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(BindException.class)
    public Results MethodArgumentNotValidExceptionHandler(BindException e) {
        // 從異常對(duì)象中拿到ObjectError對(duì)象
        BindingResult br = e.getBindingResult();
        if (br.hasFieldErrors()) {
            List<FieldError> fieldErrorList = br.getFieldErrors();
            List<String> errors = new ArrayList<>(fieldErrorList.size());
            for (FieldError error : fieldErrorList) {
                errors.add(error.getField() + ":" + error.getDefaultMessage());
            }
            // 然后提取錯(cuò)誤提示信息進(jìn)行返回
            return Results.failed(errors.toString());
        }
        // 然后提取錯(cuò)誤提示信息進(jìn)行返回
        return Results.failed("校驗(yàn)錯(cuò)誤");
    }

    /**
     * 普通參數(shù)(非 java bean)校驗(yàn)出錯(cuò)
     * 校驗(yàn)參數(shù) @RequestParam @PathVariable 時(shí)的異常
     * 注意 @Validated 需要放在controller的類(lèi)上
     * 例如:
     *
     * @RestController
     * @RequestMapping("/cs")
     * @Validated public class TestController {
     * @PostMapping("/test") public Results test(
     * @Pattern(regexp = "^\\d{19}$", message = "用戶ID,應(yīng)為19位數(shù)字") String id,
     * @NotBlank(message = "名字不能為空") String name
     * ) {}
     * }
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(ConstraintViolationException.class)
    public Results constraintViolationException(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        if (CollectionUtils.isEmpty(violations)) {
            log.error("constraintViolationException violations 為空", e);
            return Results.failed();
        }
        Map<String, String> map = violations.stream()
                .collect(Collectors.toMap(o -> {
                    PathImpl x = (PathImpl) o.getPropertyPath();
                    return x.getLeafNode().toString();
                }, ConstraintViolation::getMessage, (k1, k2) -> k1));
        return Results.failed(map.toString());
    }
}

如果不加這個(gè)全局處理類(lèi),只會(huì)給前端返回這樣的參數(shù)

加上全局配置類(lèi)

實(shí)體類(lèi)

@ApiModel("測(cè)試 validation 入?yún)?)
@Data
public class TestDto {
    
    @ApiModelProperty(value = "名字",required = true)
    // 適用于 String 類(lèi)型的數(shù)據(jù)上,加了@NotBlank 注解的參數(shù)不能為 Null 且 trim() 之后 size > 0,必須有實(shí)際字符
    @NotBlank(message = "名字不能為空")
    private String name;
    
    @ApiModelProperty(value = "年齡",required = true)
    @NotNull(message = "年齡不能為空")
    // 適用于基本數(shù)據(jù)類(lèi)型(Integer,Long,Double等等),當(dāng) @NotNull 注解被使用在 String 類(lèi)型的數(shù)據(jù)上,則表示該數(shù)據(jù)不能為 Null(但是可以為 Empty)
    private Integer age;
    
    @ApiModelProperty(value = "愛(ài)好",required = true)
    // 適用于 String、Collection集合、Map、數(shù)組等等,加了@NotEmpty 注解的參數(shù)不能為 Null 或者 長(zhǎng)度為 0
    @NotEmpty(message = "年齡不能為空")
    private List<String> hobbies;
}

服務(wù)層(為了方便,我直接跟Controller寫(xiě)在一起了)

必須要加上 @Valid 或者 @Validated,后續(xù)我會(huì)講解這兩個(gè)有什么不同,目前來(lái)說(shuō),都可以用,但推薦用 @Validated

@RestController
@Slf4j
@Api("測(cè)試")
public class TestController {

    @PostMapping("/testValidation")
    @ApiOperation("測(cè)試 validation")
    // 必須要加上 @Valid 或者 @Validated
    public Results testValidation(
        // 必須要加上 @Valid 或者 @Validated
        @Valid @RequestBody TestDto dto){
        try {
            log.info("test 入?yún)?dto={}",dto);
            return Results.success();
        } catch (Exception e) {
            log.error("test 報(bào)錯(cuò)",e);
            return Results.failed();
        }
    }
}

測(cè)試

四、javax.validation包下其它常用的校驗(yàn)注解:

這個(gè)顏色的是常用的

注解含義
@Null任何類(lèi)型 必須為null
@NotBlank字符串、字符 字符類(lèi)不能為null,且去掉空格之后長(zhǎng)度大于
@NotNull任何類(lèi)型 不能為null
@Length(min = 6, max = 8, message = “密碼長(zhǎng)度為6-8位。”)字符串的大小必須在指定的范圍內(nèi)
@NotEmpty適用于 String、Collection集合、Map、數(shù)組等等,加了@NotEmpty 注解的參數(shù)不能為 Null 或者 長(zhǎng)度為 0
@AssertTrueBoolean、boolean 布爾屬性必須是true
@AssertFalseBoolean、boolean 布爾屬性必須是false
@Min(10)必須是一個(gè)數(shù)字,其值必須大于等于指定的最小值(我這填的是10)(整型)
@Max(10)必須是一個(gè)數(shù)字,其值必須小于等于指定的最大值(我這填的是10)(整型)
@DecimalMin(“10”)必須是一個(gè)數(shù)字,其值必須大于等于指定的最小值(我這填的是10)(字符串,可以是小數(shù))
@DecimalMax(“10”)必須是一個(gè)數(shù)字,其值必須小于等于指定的最大值(我這填的是10)(字符串,可以是小數(shù))
@Size(max = 10,min = 1)集合 限定集合大小
@Digits(integer = 3, fraction = 2, message = “請(qǐng)輸入有效的數(shù)字”)
private double number;
@Digits 用于驗(yàn)證數(shù)字的整數(shù)位數(shù)和小數(shù)位數(shù)。該注解的 integer 和 fraction 屬性分別用于指定整數(shù)位數(shù)和小數(shù)位數(shù)的限制。
integer 屬性用于指定數(shù)字的最大整數(shù)位數(shù)。它是一個(gè)整數(shù)值,表示數(shù)字允許的最大整數(shù)位數(shù)。例如,integer = 3 表示數(shù)字最多可以有三位整數(shù)部分。
fraction 屬性用于指定數(shù)字的最大小數(shù)位數(shù)。它是一個(gè)整數(shù)值,表示數(shù)字允許的最大小數(shù)位數(shù)。例如,fraction = 2 表示數(shù)字最多可以有兩位小數(shù)部分。
@Past時(shí)間、日期 必須是一個(gè)過(guò)去的時(shí)間或日期
@Future時(shí)期、時(shí)間 必須是一個(gè)未來(lái)的時(shí)間或日期
@Email字符串 必須是一個(gè)郵箱格式
@Pattern(regexp = “[a-zA-Z]*”, message = “密碼不合法”)字符串、字符 正則匹配字符串
@Range(max = 150, min = 1, message = “年齡范圍應(yīng)該在1-150內(nèi)。”)數(shù)字類(lèi)型(原子和包裝) 限定數(shù)字范圍(長(zhǎng)整型)
@URL(protocol=,host=, port=,regexp=, flags=)被注釋的字符串必須是一個(gè)有效的url
@CreditCardNumber被注釋的字符串必須通過(guò)Luhn校驗(yàn)算法,銀行卡,信用卡等號(hào)碼一般都用Luhn計(jì)算合法性
@ScriptAssert(lang=, script=, alias=)要有Java Scripting API 即JSR 223 (“Scripting for the JavaTM Platform”)的實(shí)現(xiàn)
@SafeHtml(whitelistType=, additionalTags=)classpath中要有jsoup包

五、@Validated 與 @Valid 比較

文字講解

Spring Validation驗(yàn)證框架對(duì)參數(shù)的驗(yàn)證機(jī)制提供了@Validated(Spring’s JSR-303規(guī)范,是標(biāo)準(zhǔn)JSR-303的一個(gè)變種),javax提供了@Valid(標(biāo)準(zhǔn)JSR-303規(guī)范),配合BindingResult可以直接提供參數(shù)驗(yàn)證結(jié)果。

@Valid屬于javax.validation包下,是jdk給提供的 是使用Hibernate validation的時(shí)候使用

@Validated是org.springframework.validation.annotation包下的,是spring提供的 是只用Spring Validator校驗(yàn)機(jī)制使用

說(shuō)明:java的JSR303聲明了@Valid這類(lèi)接口,而Hibernate-validator對(duì)其進(jìn)行了實(shí)現(xiàn)

@Validation對(duì)@Valid進(jìn)行了二次封裝,在使用上并沒(méi)有區(qū)別,但在分組、注解位置、嵌套驗(yàn)證等功能上有所不同,這里主要就這幾種情況進(jìn)行說(shuō)明。

在檢驗(yàn)Controller的入?yún)⑹欠穹弦?guī)范時(shí),使用@Validated或者@Valid在基本驗(yàn)證功能上沒(méi)有太多區(qū)別。但是在分組、注解地方、嵌套驗(yàn)證等功能上兩個(gè)有所不同:

  1. 分組:

@Validated:提供了一個(gè)分組功能,可以在入?yún)Ⅱ?yàn)證時(shí),根據(jù)不同的分組采用不同的驗(yàn)證機(jī)制,這個(gè)網(wǎng)上也有資料,不詳述。@Valid:作為標(biāo)準(zhǔn)JSR-303規(guī)范,還沒(méi)有吸收分組的功能。

  1. 注解地方:

@Validated:用在類(lèi)型、方法和方法參數(shù)上。但不能用于成員屬性(field)

@Valid:可以用在方法、構(gòu)造函數(shù)、方法參數(shù)和成員屬性(field)上 所以可以用@Valid實(shí)現(xiàn)嵌套驗(yàn)證

總結(jié):

@Valid 和 @Validated 兩者都可以對(duì)數(shù)據(jù)進(jìn)行校驗(yàn),待校驗(yàn)字段上打的規(guī)則注解(@NotNull, @NotEmpty等)都可以對(duì) @Valid 和 @Validated 生效;

@Valid 進(jìn)行校驗(yàn)的時(shí)候,需要用 BindingResult 來(lái)做一個(gè)校驗(yàn)結(jié)果接收。當(dāng)校驗(yàn)不通過(guò)的時(shí)候,如果手動(dòng)不 return ,則并不會(huì)阻止程序的執(zhí)行;

@Validated 進(jìn)行校驗(yàn)的時(shí)候,當(dāng)校驗(yàn)不通過(guò)的時(shí)候,程序會(huì)拋出400異常,阻止方法中的代碼執(zhí)行,這時(shí)需要再寫(xiě)一個(gè)全局校驗(yàn)異常捕獲處理類(lèi),然后返回校驗(yàn)提示。

總體來(lái)說(shuō),@Validated 使用起來(lái)要比 @Valid 方便一些,它可以幫我們節(jié)省一定的代碼,并且使得方法看上去更加的簡(jiǎn)潔。

代碼講解,groups屬性

在開(kāi)發(fā)中,新增、修改兩個(gè)接口,一般關(guān)系就在于新增時(shí)ID可以為空,修改時(shí)ID不能為空,那我們?nèi)绻褂?validation 用于參數(shù)校驗(yàn),創(chuàng)建兩個(gè)實(shí)體類(lèi)就非常的不劃算,這時(shí)

①、創(chuàng)建一個(gè)update接口

import javax.validation.groups.Default;

public interface Update extends Default {
}

②、修改實(shí)體類(lèi)

@ApiModel("測(cè)試 validation 入?yún)?)
@Data
public class TestDto {
    @ApiModelProperty(value = "ID",required = true)
    // 新增時(shí)ID為空,修改時(shí)ID不能為空
    @NotNull(message = "ID不能為空",groups = Update.class)
    private Integer id;
    @ApiModelProperty(value = "名字",required = true)
    @NotBlank(message = "名字不能為空")
    private String name;
}

③、服務(wù)層(為了方便,我直接跟Controller寫(xiě)在一起了)

@RestController
@Slf4j
@Api("測(cè)試")
public class TestController {

    @PostMapping("/testAdd")
    @ApiOperation("測(cè)試 新增")
    public Results testAdd(@Validated @RequestBody TestDto dto){
        try {
            log.info("testAdd 入?yún)?dto={}",dto);
            return Results.success();
        } catch (Exception e) {
            log.error("testAdd 報(bào)錯(cuò)",e);
            return Results.failed();
        }
    }

    @PostMapping("/testUpdate")
    @ApiOperation("測(cè)試 新增")
    public Results testUpdate(@Validated(Update.class) @RequestBody TestDto dto){
        try {
            log.info("testUpdate 入?yún)?dto={}",dto);
            return Results.success();
        } catch (Exception e) {
            log.error("testUpdate 報(bào)錯(cuò)",e);
            return Results.failed();
        }
    }
}

⑤、測(cè)試

  • 新增:

  • 修改:

六、校驗(yàn)List

錯(cuò)誤案例

僅在外層包一個(gè)@Valid是校驗(yàn)不了List中實(shí)體類(lèi)的參數(shù)的

    @ResponseBody
    @PostMapping("/testList")
    public Results testList(@RequestBody @Valid List<TestDto> dto){
        try {
            log.info("testList 入?yún)?dto={}",dto);
            return Results.success();
        } catch (Exception e) {
            log.error("testList 報(bào)錯(cuò)",e);
            return Results.failed();
        }
    }

方法其實(shí)有兩種,我就只講比較優(yōu)雅且方便的方法

創(chuàng)建ValidList類(lèi)(可以直接復(fù)制使用)

/**
 * 可被校驗(yàn)的List
 *
 * @param <E> 元素類(lèi)型
 * @author Deolin
 */
@Data
public class ValidList<E> implements List<E> {
    @Valid
    private List<E> list = new ArrayList<>();
    @Override
    public int size() {
        return list.size();
    }
    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }
    @Override
    public boolean contains(Object o) {
        return list.contains(o);
    }
    @Override
    public Iterator<E> iterator() {
        return list.iterator();
    }
    @Override
    public Object[] toArray() {
        return list.toArray();
    }
    @Override
    public <T> T[] toArray(T[] a) {
        return list.toArray(a);
    }
    @Override
    public boolean add(E e) {
        return list.add(e);
    }
    @Override
    public boolean remove(Object o) {
        return list.remove(o);
    }
    @Override
    public boolean containsAll(Collection<?> c) {
        return list.containsAll(c);
    }
    @Override
    public boolean addAll(Collection<? extends E> c) {
        return list.addAll(c);
    }
    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        return list.addAll(index, c);
    }
    @Override
    public boolean removeAll(Collection<?> c) {
        return list.removeAll(c);
    }
    @Override
    public boolean retainAll(Collection<?> c) {
        return list.retainAll(c);
    }
    @Override
    public void clear() {
        list.clear();
    }
    @Override
    public E get(int index) {
        return list.get(index);
    }
    @Override
    public E set(int index, E element) {
        return list.set(index, element);
    }
    @Override
    public void add(int index, E element) {
        list.add(index, element);
    }
    @Override
    public E remove(int index) {
        return list.remove(index);
    }
    @Override
    public int indexOf(Object o) {
        return list.indexOf(o);
    }
    @Override
    public int lastIndexOf(Object o) {
        return list.lastIndexOf(o);
    }
    @Override
    public ListIterator<E> listIterator() {
        return list.listIterator();
    }
    @Override
    public ListIterator<E> listIterator(int index) {
        return list.listIterator(index);
    }
    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        return list.subList(fromIndex, toIndex);
    }
}

測(cè)試

controller:

    @ResponseBody
    @PostMapping("/testList")
    public Results testList(@RequestBody @ValidList List<TestDto> dto){
        try {
            log.info("testList 入?yún)?dto={}",dto);
            return Results.success();
        } catch (Exception e) {
            log.error("testList 報(bào)錯(cuò)",e);
            return Results.failed();
        }
    }

經(jīng)過(guò)我們寫(xiě)的全局異常處理類(lèi),得出的結(jié)果

七、自定義 枚舉校驗(yàn)注解

注解

/**
 * 枚舉校驗(yàn)注解
 */
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {EnumValueValidator.class})
public @interface EnumValue {

    // 默認(rèn)錯(cuò)誤消息
    String message() default "必須為指定值";

    String[] strValues() default {};

    int[] intValues() default {};

    // 分組
    Class<?>[] groups() default {};

    // 負(fù)載
    Class<? extends Payload>[] payload() default {};

    // 指定多個(gè)時(shí)使用
    @Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Documented
    @interface List {
        EnumValue[] value();
    }
}

枚舉校驗(yàn)注解處理類(lèi)

/**
 * 枚舉校驗(yàn)注解處理類(lèi)
 */
public class EnumValueValidator implements ConstraintValidator<EnumValue, Object> {

    private String[] strValues;
    private int[] intValues;

    @Override
    public void initialize(EnumValue constraintAnnotation) {
        strValues = constraintAnnotation.strValues();
        intValues = constraintAnnotation.intValues();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (value instanceof String) {
            for (String s : strValues) {
                if (s.equals(value)) {
                    return true;
                }
            }
        } else if (value instanceof Integer) {
            for (int s : intValues) {
                if (s == ((Integer) value).intValue()) {
                    return true;
                }
            }
        }
        return false;
    }
}

使用

@Data
@Accessors(chain = true)
public class Test {
    @EnumValue(strValues = {"1", "2", "3"}, message = "傳入類(lèi)型不正確")
    private String type;
    @EnumValue(intValues = {1, 2, 3}, message = "傳入類(lèi)型不正確")
    private String status;
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • springboot2整合redis使用lettuce連接池的方法(解決lettuce連接池?zé)o效問(wèn)題)

    springboot2整合redis使用lettuce連接池的方法(解決lettuce連接池?zé)o效問(wèn)題)

    這篇文章主要介紹了springboot2整合redis使用lettuce連接池(解決lettuce連接池?zé)o效問(wèn)題),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Springboot整合Dubbo教程之項(xiàng)目創(chuàng)建和環(huán)境搭建

    Springboot整合Dubbo教程之項(xiàng)目創(chuàng)建和環(huán)境搭建

    本篇文章主要介紹了Springboot整合Dubbo教程之項(xiàng)目創(chuàng)建和環(huán)境搭建,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • mybatis-plus支持null字段全量更新的兩種方法

    mybatis-plus支持null字段全量更新的兩種方法

    本文主要介紹了mybatis-plus支持null字段全量更新的兩種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • IDEA項(xiàng)目中配置Maven鏡像源(下載源)的詳細(xì)過(guò)程

    IDEA項(xiàng)目中配置Maven鏡像源(下載源)的詳細(xì)過(guò)程

    Maven是一個(gè)能使我們的java程序開(kāi)發(fā)節(jié)省時(shí)間和精力,是開(kāi)發(fā)變得相對(duì)簡(jiǎn)單,還能使開(kāi)發(fā)規(guī)范化的工具,下面這篇文章主要給大家介紹了關(guān)于IDEA項(xiàng)目中配置Maven鏡像源(下載源)的詳細(xì)過(guò)程,需要的朋友可以參考下
    2024-02-02
  • Java 中使用數(shù)組存儲(chǔ)和操作數(shù)據(jù)

    Java 中使用數(shù)組存儲(chǔ)和操作數(shù)據(jù)

    本文將介紹Java中常用的數(shù)組操作方法,通過(guò)詳細(xì)的示例和解釋,幫助讀者全面理解和掌握這些方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • iBatis習(xí)慣用的16條SQL語(yǔ)句

    iBatis習(xí)慣用的16條SQL語(yǔ)句

    iBatis 是apache 的一個(gè)開(kāi)源項(xiàng)目,一個(gè)O/R Mapping 解決方案,iBatis 最大的特點(diǎn)就是小巧,上手很快.這篇文章主要介紹了iBatis習(xí)慣用的16條SQL語(yǔ)句的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Java原生序列化和反序列化代碼實(shí)例

    Java原生序列化和反序列化代碼實(shí)例

    這篇文章主要介紹了Java原生序列化和反序列化代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • java中Swing會(huì)奔跑的線程俠

    java中Swing會(huì)奔跑的線程俠

    本文通過(guò)代碼示例給大家詳細(xì)講解了java中Swing會(huì)奔跑的線程俠這個(gè)經(jīng)典的示例,有興趣的朋友學(xué)習(xí)下。
    2018-03-03
  • Gradle的使用教程詳解

    Gradle的使用教程詳解

    Gradle它使用一種基于Groovy的特定領(lǐng)域語(yǔ)言(DSL)來(lái)聲明項(xiàng)目設(shè)置,目前也增加了基于Kotlin語(yǔ)言的kotlin-based DSL,拋棄了基于XML的各種繁瑣配置,下面通過(guò)本文給大家介紹Gradle的使用教程,感興趣的朋友一起看看吧
    2020-09-09
  • Spring事務(wù)管理的使用細(xì)則淺析

    Spring事務(wù)管理的使用細(xì)則淺析

    事務(wù)的作用就是為了保證用戶的每一個(gè)操作都是可靠的,事務(wù)中的每一步操作都必須成功執(zhí)行,只要有發(fā)生異常就 回退到事務(wù)開(kāi)始未進(jìn)行操作的狀態(tài)。事務(wù)管理是Spring框架中最為常用的功能之一,我們?cè)谑褂肧pring開(kāi)發(fā)應(yīng)用時(shí),大部分情況下也都需要使用事務(wù)
    2023-02-02

最新評(píng)論

霍州市| 南充市| 温泉县| 宣化县| 南江县| 登封市| 嘉禾县| 常宁市| 昌黎县| 夏河县| 宣城市| 宣化县| 竹北市| 甘洛县| 长兴县| 易门县| 肃宁县| 彭州市| 库伦旗| 扶沟县| 鄂伦春自治旗| 剑阁县| 昭觉县| 红河县| 阳原县| 个旧市| 宁国市| 伽师县| 盘山县| 德令哈市| 宁波市| 遵化市| 抚宁县| 普安县| 宁远县| 松桃| 额尔古纳市| 绩溪县| 平罗县| 灵石县| 保山市|