亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JAVA校驗(yàn)之@Valid和@Validated實(shí)踐指南

 更新時間:2025年07月01日 11:05:48   作者:Easocen  
在Java開發(fā)中參數(shù)校驗(yàn)是保障程序健壯性的重要手段,@Valid和@Validated是兩個常用的校驗(yàn)注解,但它們在使用場景、驗(yàn)證方式和嵌套處理等方面存在顯著差異,這篇文章主要介紹了JAVA校驗(yàn)之@Valid和@Validated的相關(guān)資料,需要的朋友可以參考下

概述

區(qū)別

  • 來源 (規(guī)范與框架綁定)    - @Validated: 它是 Spring 框架特有的注解,屬于 Spring 自身提供的一個功能增強(qiáng)。它基于 JSR 303 (Bean Validation 1.0) / JSR 380 (Bean Validation 2.0) 規(guī)范,但在其基礎(chǔ)上進(jìn)行了擴(kuò)展,特別適用于 Spring 環(huán)境。
        - @Valid: 這是一個標(biāo)準(zhǔn)的 Java EE 注解,是 JSR 303 / JSR 380 (Bean Validation) 規(guī)范的核心組成部分。它不依賴于任何特定的框架,可以在任何支持 Bean Validation 的環(huán)境中(如 Hibernate Validator、CDI 等)使用。
  • 注解位置 (適用范圍)    - @Validated: 主要用于(聲明在類上時,會對其所有公共方法參數(shù)進(jìn)行校驗(yàn))、方法方法參數(shù)。它不能直接用于成員屬性(字段)。當(dāng)用于類上時,通常與 Spring 的 AOP 攔截結(jié)合使用。
        - @Valid: 可以用于方法、構(gòu)造函數(shù)、方法參數(shù)以及成員屬性(字段)。當(dāng)用于成員屬性時,它會觸發(fā)對該屬性所引用對象的級聯(lián)校驗(yàn)。
  • 分組 (靈活性)    - @Validated支持分組驗(yàn)證。這是其相比 @Valid 的一個重要優(yōu)勢。你可以通過在 @Validated 注解中指定一個或多個接口類來定義校驗(yàn)組,從而在不同的業(yè)務(wù)場景(如創(chuàng)建、更新)中應(yīng)用不同的校驗(yàn)規(guī)則。
        - @Valid: 僅支持標(biāo)準(zhǔn)的 Bean Validation 功能,不支持分組驗(yàn)證。當(dāng)它觸發(fā)校驗(yàn)時,它會執(zhí)行目標(biāo)對象上所有未指定分組的(即默認(rèn)組Default.class)以及任何被顯式指定為 Default.class 的約束。
  • 嵌套驗(yàn)證 (遞歸校驗(yàn))    - @Validated: 單獨(dú)使用時,@Validated 本身不支持嵌套驗(yàn)證。它通常需要與 @Valid 配合使用才能實(shí)現(xiàn)對復(fù)雜對象內(nèi)部嵌套屬性的校驗(yàn)。@Validated 主要負(fù)責(zé)激活校驗(yàn)器并指定校驗(yàn)組,而 @Valid 則負(fù)責(zé)遞歸遍歷對象圖。
        - @Valid支持嵌套驗(yàn)證。當(dāng)一個對象的屬性本身也是一個需要被校驗(yàn)的對象時,你可以在該屬性上添加 @Valid,這樣在父對象被校驗(yàn)時,其內(nèi)部的嵌套屬性也會被自動遞歸校驗(yàn)。

校驗(yàn)類型

  • @NotNull: 被注解的元素不能為 null。
        適用類型: 任何類型(對象、基本類型包裝類、集合、數(shù)組等)。

  • @NotEmpty: 被注解的元素不能為 null 且其大小/長度必須大于零。
        適用類型CharSequence (字符串)、Collection (集合如 ListSet)、MapArray (數(shù)組)。

  • @NotBlank: 被注解的 String 類型不能為 null,不能是空字符串 (""),且不能只包含空白字符(如空格、制表符)。
        適用類型CharSequence (字符串)。

  • @Min(value): 被注解的元素必須是一個數(shù)字,且其值必須大于或等于指定值 value。
        適用類型BigDecimalBigIntegerByteShortIntegerLongFloatDouble 及其包裝類。

  • @Max(value): 被注解的元素必須是一個數(shù)字,且其值必須小于或等于指定值 value。
        適用類型BigDecimalBigIntegerByteShortIntegerLongFloatDouble 及其包裝類。

  • @DecimalMin(value, inclusive=true): 被注解的元素必須是一個數(shù)字,且其值必須大于或等于指定值 value(默認(rèn) inclusive=true)。如果 inclusive=false,則表示大于 value。
        適用類型BigDecimalBigIntegerByteShortIntegerLongFloatDouble 及其包裝類,以及 String (其內(nèi)容必須是數(shù)字)。

  • @DecimalMax(value, inclusive=true): 被注解的元素必須是一個數(shù)字,且其值必須小于或等于指定值 value(默認(rèn) inclusive=true)。如果 inclusive=false,則表示小于 value。
        適用類型BigDecimalBigIntegerByteShortIntegerLongFloatDouble 及其包裝類,以及 String (其內(nèi)容必須是數(shù)字)。

  • @Positive: 被注解的元素必須是正數(shù)(大于 0)。
        適用類型BigDecimalBigIntegerByteShortIntegerLongFloatDouble 及其包裝類。

  • @PositiveOrZero: 被注解的元素必須是正數(shù)或零(大于等于 0)。
        適用類型BigDecimalBigIntegerByteShortIntegerLongFloatDouble 及其包裝類.

  • @Negative: 被注解的元素必須是負(fù)數(shù)(小于 0)。
        適用類型BigDecimalBigIntegerByteShortIntegerLongFloatDouble 及其包裝類.

  • @NegativeOrZero: 被注解的元素必須是負(fù)數(shù)或零(小于等于 0)。
        適用類型BigDecimalBigIntegerByteShortIntegerLongFloatDouble 及其包裝類.

  • @Size(min, max): 被注解的元素大小/長度必須在指定范圍(min 到 max)之內(nèi)。
        適用類型CharSequence (字符串)、Collection (集合)、Map、Array (數(shù)組)。

  • @Digits(integer, fraction): 被注解的元素必須是一個數(shù)字,其整數(shù)部分的位數(shù)不能超過 integer 位,小數(shù)部分的位數(shù)不能超過 fraction 位。
        適用類型BigDecimalBigIntegerByteShortIntegerLongFloatDouble 及其包裝類,以及 String (其內(nèi)容必須是數(shù)字)。

  • @Past: 被注解的日期或時間必須是一個過去的日期或時間。
        適用類型java.util.Datejava.util.Calendarjava.time.LocalDatejava.time.LocalDateTimejava.time.LocalTimejava.time.MonthDayjava.time.OffsetDateTimejava.time.OffsetTimejava.time.Yearjava.time.YearMonthjava.time.ZonedDateTime 等。

  • @PastOrPresent: 被注解的日期或時間必須是一個過去的或當(dāng)前的日期或時間。
        適用類型: 同 @Past。

  • @Future: 被注解的日期或時間必須是一個未來的日期或時間。
        適用類型: 同 @Past。

  • @FutureOrPresent: 被注解的日期或時間必須是一個未來的或當(dāng)前的日期或時間。
        適用類型: 同 @Past。

  • @Pattern(regexp, flags=Pattern.CASE_INSENSITIVE): 被注解的 String 必須符合指定的正則表達(dá)式 regexp。
        適用類型CharSequence (字符串)。

  • @Email: 被注解的 String 必須是有效的郵件地址格式。
        適用類型CharSequence (字符串)。

  • @AssertTrue: 被注解的布爾類型必須為 true。通常用于驗(yàn)證復(fù)雜邏輯(如兩個字段間的關(guān)聯(lián)驗(yàn)證),需要一個返回 boolean 的 getter 方法。
        適用類型Boolean 或 boolean。

  • @AssertFalse: 被注解的布爾類型必須為 false
        適用類型Boolean 或 boolean

實(shí)踐

分組校驗(yàn)

分組校驗(yàn)允許你根據(jù)不同的業(yè)務(wù)場景(如創(chuàng)建、更新、刪除等)對同一個實(shí)體類應(yīng)用不同的驗(yàn)證規(guī)則,從而實(shí)現(xiàn)更靈活和精細(xì)的控制。

特別注意

  • 定義分組必須使用接口。 這些接口是空的,僅作為校驗(yàn)規(guī)則的標(biāo)識。
  • 要校驗(yàn)的字段上的注解必須通過 groups 屬性指定所屬的分組。 如果一個校驗(yàn)注解沒有指定 groups,它將默認(rèn)屬于 Default.class 組,并在任何未指定分組或顯式指定 Default.class 的校驗(yàn)中生效。
  • 在 Controller 方法的 @Validated 注解中指定要激活的分組。

創(chuàng)建分組

// 用于創(chuàng)建操作的校驗(yàn)組
public interface CreationGroup { }

// 用于更新操作的校驗(yàn)組
public interface UpdateGroup { }

// 你還可以定義其他分組,例如:
// public interface DeleteGroup { }

設(shè)置實(shí)體

在實(shí)體類的字段上添加校驗(yàn)注解,并使用 groups 屬性指定該校驗(yàn)規(guī)則屬于哪個分組。一個字段可以屬于多個分組。

@Data
public class UserBean {

    // 創(chuàng)建和更新時都校驗(yàn)用戶名非空
    // 默認(rèn)的 Default 組也適用,但如果指定了分組,則只在指定分組下生效
    @NotEmpty(message = "用戶名不能為空", groups = {CreationGroup.class, UpdateGroup.class})
    private String username;

    // 年齡校驗(yàn),無分組,默認(rèn)在所有場景(包括未指定分組的 @Validated)下都校驗(yàn)
    @Min(value = 18, message = "年齡不能小于18歲")
    private Integer age;

    // 郵箱格式校驗(yàn),無分組,默認(rèn)在所有場景下都校驗(yàn)
    @Email(message = "郵箱格式不正確")
    private String email;

    // ID 校驗(yàn),只在更新時生效,且必須大于等于1
    @NotNull(message = "ID不能為空", groups = UpdateGroup.class) // 更新時ID不能為null
    @Min(value = 1, message = "ID必須大于0", groups = {UpdateGroup.class})
    private Long id;

    // ... 其他屬性
}

使用校驗(yàn)

在 Controller 方法的參數(shù)上使用 @Validated 注解,并傳入需要激活的校驗(yàn)組。

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid; // 導(dǎo)入 javax.validation.Valid

@RestController
@RequestMapping("validation")
public class ValidationController {

    /**
     * 更新用戶接口:只激活 UpdateGroup 組的校驗(yàn)規(guī)則。
     * 此時,UserBean 中的 id 字段會根據(jù) UpdateGroup 的規(guī)則進(jìn)行校驗(yàn)。
     * username 和 age、email 字段則會根據(jù)它們自身定義的(或默認(rèn)的)規(guī)則進(jìn)行校驗(yàn)。
     */
    @GetMapping("updateUser")
    public UserBean updateUser(@Validated({UpdateGroup.class}) UserBean userBean){
        // 如果校驗(yàn)失敗,會拋出 MethodArgumentNotValidException,由全局異常處理器捕獲
        System.out.println("更新用戶成功: " + userBean);
        return userBean;
    }

    /**
     * 創(chuàng)建用戶接口:只激活 CreationGroup 組的校驗(yàn)規(guī)則。
     * 此時,UserBean 中的 username 字段會根據(jù) CreationGroup 的規(guī)則進(jìn)行校驗(yàn)。
     * age 和 email 字段則會根據(jù)它們自身定義的(或默認(rèn)的)規(guī)則進(jìn)行校驗(yàn)。
     * id 字段由于不屬于 CreationGroup,將不會被校驗(yàn)。
     */
    @GetMapping("createUser")
    public UserBean createUser(@Validated({CreationGroup.class}) UserBean userBean){
        // 如果校驗(yàn)失敗,會拋出 MethodArgumentNotValidException,由全局異常處理器捕獲
        System.out.println("創(chuàng)建用戶成功: " + userBean);
        return userBean;
    }

    // 注意:如果一個方法參數(shù)不加 @Validated,但實(shí)體類中有 @Valid 注解,
    // 則會默認(rèn)校驗(yàn)所有無分組的字段(即 Default 組)。
    // 例如:
    // @PostMapping("defaultValid")
    // public UserBean defaultValid(@Valid @RequestBody UserBean userBean) {
    //     return userBean;
    // }
}

嵌套驗(yàn)證

嵌套校驗(yàn)(Nested Validation) 指的是在驗(yàn)證外部對象時,對其內(nèi)部包含的其他對象進(jìn)行遞歸驗(yàn)證的過程。當(dāng)一個對象中包含另一個對象作為屬性,并且需要對這個被包含的對象也進(jìn)行驗(yàn)證時,就需要進(jìn)行嵌套校驗(yàn)。

嵌套屬性指的是在一個對象中包含另一個對象作為其屬性的情況。換句話說,當(dāng)一個對象的屬性本身又是一個對象(非基本類型),那么這些被包含的對象就可以稱為嵌套屬性。

特別提示

  • 想要嵌套校驗(yàn)生效,必須在嵌套屬性上加 @Valid 注解。這個注解告訴校驗(yàn)器深入到這個屬性對應(yīng)的對象內(nèi)部進(jìn)行校驗(yàn)。
  • @Valid 注解默認(rèn)校驗(yàn)無分組的項(xiàng)。它會觸發(fā)嵌套對象上所有屬于 Default.class 組的校驗(yàn)。
  • 嵌套驗(yàn)證要支持分組,需要結(jié)合 @Validated({YourGroup.class})。 當(dāng) @Validated 指定了分組并作用于包含 @Valid 屬性的外部對象時,@Valid 會將這個分組信息傳遞給嵌套對象,從而使其內(nèi)部只有對應(yīng)分組的校驗(yàn)規(guī)則生效。

驗(yàn)證嵌套屬性

首先,定義你的嵌套實(shí)體類,并為其字段添加校驗(yàn)規(guī)則:

import lombok.Data;
import javax.validation.constraints.NotBlank;

@Data
public class AddressBean {
    @NotBlank(message = "國家不能為空")
    private String country;
    @NotBlank(message = "城市不能為空")
    private String city;
}

接著,在主實(shí)體類中包含這個嵌套屬性,并在該屬性上添加 @Valid 和 @NotNull(如果地址對象本身不能為 null):

@Data
public class UserBean {

    @NotEmpty(message = "用戶名不能為空", groups = {CreationGroup.class})
    private String username;

    @Min(value = 18, message = "年齡不能小于18歲")
    private Integer age;

    @Email(message = "郵箱格式不正確")
    private String email;

    // 嵌套驗(yàn)證必須要加上 @Valid
    // 同時可以添加 @NotNull 來確保 address 對象本身不為空
    @Valid
    @NotNull(message = "地址信息不能為空")
    private AddressBean address; // 嵌套屬性

    // ... 其他屬性和 getter/setter
}

然后在 Controller 中使用 @Validated 來觸發(fā)校驗(yàn):

@RestController
@RequestMapping("validation")
public class ValidationController {

    /**
     * 嵌套驗(yàn)證示例。
     * 當(dāng) @RequestBody UserBean userBean 傳入時,
     * 如果 userBean 內(nèi)部的 address 屬性有 @Valid 注解,
     * 那么 address 對象自身的校驗(yàn)規(guī)則也會被觸發(fā)。
     * 此處如果 address 為 null 或其內(nèi)部字段(country, city)為空,都會觸發(fā)校驗(yàn)失敗。
     */
    @PostMapping("nestValid")
    public UserBean nestValid(@Validated @RequestBody UserBean userBean){ // @Validated 也可以不指定分組,則校驗(yàn) Default 組
        System.out.println("嵌套驗(yàn)證成功: " + userBean);
        return userBean;
    }

    /**
     * 帶分組的嵌套驗(yàn)證示例。
     * 此時,只有 UserBean 中屬于 CreationGroup 的校驗(yàn)規(guī)則生效,
     * 并且這個分組也會傳遞給嵌套的 AddressBean,如果 AddressBean 中也有分組校驗(yàn)規(guī)則,它們就會生效。
     * 此外,因?yàn)?address 屬性是 @Valid 且 @NotNull,它會始終被校驗(yàn)。
     */
    @PostMapping("nestValidWithGroup")
    public UserBean nestValidWithGroup(@Validated(CreationGroup.class) @RequestBody UserBean userBean){
        System.out.println("帶分組的嵌套驗(yàn)證成功: " + userBean);
        return userBean;
    }
}

驗(yàn)證集合

當(dāng)請求體是一個對象的集合(如 List<YourBean>)時,校驗(yàn)的原理與嵌套驗(yàn)證類似,你需要將 @Valid 放在集合參數(shù)前,而 @Validated 則用于指定校驗(yàn)組(如果需要)。同時,你也可以對集合本身進(jìn)行非空校驗(yàn)。

@RestController
@RequestMapping("/metadataTemplate")
public class ReMetadataTemplateController {

    // 假設(shè) reMetadataTemplateService 已注入

    /**
     * 更改元數(shù)據(jù)模板狀態(tài)接口,支持對列表本身非空及列表中每個對象的字段進(jìn)行分組校驗(yàn)。
     *
     * @param list 待更新的元數(shù)據(jù)模板列表
     * @return 結(jié)果
     */
    @PutMapping("/changeStatus")
    @Validated(EditGroup.class) // 指定激活 EditGroup 組的校驗(yàn)
    public Void changeStatus(
        // @Valid 觸發(fā)對 List 中每個 ReMetadataTemplateBo 對象的校驗(yàn)
        // @NotEmpty(message = "參數(shù)不能為空") 校驗(yàn) List 本身不能為 null 或空集合
        @Valid @NotEmpty(message = "元數(shù)據(jù)模板列表不能為空", groups = EditGroup.class)
        @RequestBody List<ReMetadataTemplateBo> list
    ) {
        // 如果校驗(yàn)失敗,會拋出 MethodArgumentNotValidException,由全局異常處理器捕獲
        // ... 業(yè)務(wù)邏輯
        reMetadataTemplateService.changeStatus(list);
    }
}

異常處理

為了更好地處理校驗(yàn)失敗時拋出的異常,通常需要配置一個全局異常處理器。

引用

到此這篇關(guān)于JAVA校驗(yàn)之@Valid和@Validated實(shí)踐指南的文章就介紹到這了,更多相關(guān)JAVA校驗(yàn)@Valid和@Validated內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論