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

JAVA校驗之@Valid和@Validated實踐指南

 更新時間:2025年07月01日 11:05:48   作者:Easocen  
在Java開發(fā)中參數(shù)校驗是保障程序健壯性的重要手段,@Valid和@Validated是兩個常用的校驗注解,但它們在使用場景、驗證方式和嵌套處理等方面存在顯著差異,這篇文章主要介紹了JAVA校驗之@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)行校驗)、方法方法參數(shù)。它不能直接用于成員屬性(字段)。當(dāng)用于類上時,通常與 Spring 的 AOP 攔截結(jié)合使用。
        - @Valid: 可以用于方法構(gòu)造函數(shù)、方法參數(shù)以及成員屬性(字段)。當(dāng)用于成員屬性時,它會觸發(fā)對該屬性所引用對象的級聯(lián)校驗。
  • 分組 (靈活性)    - @Validated支持分組驗證。這是其相比 @Valid 的一個重要優(yōu)勢。你可以通過在 @Validated 注解中指定一個或多個接口類來定義校驗組,從而在不同的業(yè)務(wù)場景(如創(chuàng)建、更新)中應(yīng)用不同的校驗規(guī)則。
        - @Valid: 僅支持標(biāo)準(zhǔn)的 Bean Validation 功能,不支持分組驗證。當(dāng)它觸發(fā)校驗時,它會執(zhí)行目標(biāo)對象上所有未指定分組的(即默認(rèn)組Default.class)以及任何被顯式指定為 Default.class 的約束。
  • 嵌套驗證 (遞歸校驗)    - @Validated: 單獨使用時,@Validated 本身不支持嵌套驗證。它通常需要與 @Valid 配合使用才能實現(xiàn)對復(fù)雜對象內(nèi)部嵌套屬性的校驗。@Validated 主要負(fù)責(zé)激活校驗器并指定校驗組,而 @Valid 則負(fù)責(zé)遞歸遍歷對象圖。
        - @Valid支持嵌套驗證。當(dāng)一個對象的屬性本身也是一個需要被校驗的對象時,你可以在該屬性上添加 @Valid,這樣在父對象被校驗時,其內(nèi)部的嵌套屬性也會被自動遞歸校驗。

校驗類型

  • @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。通常用于驗證復(fù)雜邏輯(如兩個字段間的關(guān)聯(lián)驗證),需要一個返回 boolean 的 getter 方法。
        適用類型Boolean 或 boolean。

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

實踐

分組校驗

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

特別注意

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

創(chuàng)建分組

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

// 用于更新操作的校驗組
public interface UpdateGroup { }

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

設(shè)置實體

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

@Data
public class UserBean {

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

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

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

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

    // ... 其他屬性
}

使用校驗

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

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

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

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

嵌套驗證

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

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

特別提示

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

驗證嵌套屬性

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

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

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

接著,在主實體類中包含這個嵌套屬性,并在該屬性上添加 @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;

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

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

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

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

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

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

驗證集合

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

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

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

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

異常處理

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

引用

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

相關(guān)文章

  • 使用SpringBoot與EasyExcel實現(xiàn)復(fù)雜的導(dǎo)入導(dǎo)出

    使用SpringBoot與EasyExcel實現(xiàn)復(fù)雜的導(dǎo)入導(dǎo)出

    這篇文章主要介紹了使用SpringBoot與EasyExcel實現(xiàn)復(fù)雜的導(dǎo)入導(dǎo)出,EasyExcel是一個快速解決大文件內(nèi)存溢出的Excel處理工具,它能讓你在不用考慮性能、內(nèi)存等因素的情況下,快速完成Excel的讀、寫等功能,需要的朋友可以參考下
    2023-10-10
  • 詳解Spring不同數(shù)據(jù)庫異常如何抽象的

    詳解Spring不同數(shù)據(jù)庫異常如何抽象的

    根據(jù)spring-jdbc中的定義,所有的數(shù)據(jù)操作異常都會轉(zhuǎn)換為 DataAccessException,下面這篇文章主要給大家介紹了關(guān)于Spring不同數(shù)據(jù)庫異常如何抽象的相關(guān)資料,需要的朋友可以參考下
    2021-09-09
  • java實現(xiàn)服務(wù)器文件打包zip并下載的示例(邊打包邊下載)

    java實現(xiàn)服務(wù)器文件打包zip并下載的示例(邊打包邊下載)

    這篇文章主要介紹了java實現(xiàn)服務(wù)器文件打包zip并下載的示例,使用該方法,可以即時打包文件,一邊打包一邊傳輸,不使用任何的緩存,讓用戶零等待,需要的朋友可以參考下
    2014-04-04
  • java如何創(chuàng)建普通二叉樹

    java如何創(chuàng)建普通二叉樹

    這篇文章主要介紹了java如何創(chuàng)建普通二叉樹的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java輕松實現(xiàn)表單提交的三種方法

    Java輕松實現(xiàn)表單提交的三種方法

    在Web開發(fā)中,表單是用戶與網(wǎng)站交互的主要方式之一,本文將詳細(xì)介紹如何在Java中實現(xiàn)表單提交,并通過代碼和案例為新手朋友提供詳細(xì)的指導(dǎo),有需要的可以參考下
    2024-10-10
  • 搭建公司私有MAVEN倉庫的方法

    搭建公司私有MAVEN倉庫的方法

    這篇文章主要介紹了搭建公司私有MAVEN倉庫的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Spring AOP定義AfterReturning增加實例分析

    Spring AOP定義AfterReturning增加實例分析

    這篇文章主要介紹了Spring AOP定義AfterReturning增加,結(jié)合實例形式分析了Spring面相切面AOP定義AfterReturning增加相關(guān)操作技巧與使用注意事項,需要的朋友可以參考下
    2020-01-01
  • JVM內(nèi)置函數(shù)Intrinsics介紹

    JVM內(nèi)置函數(shù)Intrinsics介紹

    這篇文章主要介紹了JVM內(nèi)置函數(shù)Intrinsics,我們將學(xué)習(xí)什么是intrinsics(內(nèi)部/內(nèi)置函數(shù)),以及它們?nèi)绾卧贘ava和其他基于JVM的語言中工作,需要的朋友可以參考一下
    2022-02-02
  • Java實現(xiàn)瀏覽器端大文件分片上傳

    Java實現(xiàn)瀏覽器端大文件分片上傳

    本文主要介紹了Java實現(xiàn)瀏覽器端大文件分片上傳,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Java中String、StringBuffer和StringBuilder的區(qū)別

    Java中String、StringBuffer和StringBuilder的區(qū)別

    這篇文章主要介紹了Java中String、StringBuffer和StringBuilder的區(qū)別,StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數(shù)組保存字符串char[]value但是沒有final關(guān)鍵字修飾,所以這兩個可變,需要的朋友可以參考下
    2024-01-01

最新評論

万荣县| 通州市| 牡丹江市| 雅江县| 铜梁县| 汨罗市| 平舆县| 鱼台县| 平远县| 罗定市| 寻乌县| 玉龙| 油尖旺区| 当阳市| 运城市| 周宁县| 梁河县| 彰武县| 金阳县| 温泉县| 宜兰县| 达日县| 乾安县| 新沂市| 大余县| 商南县| 元朗区| 霸州市| 曲周县| 军事| 旬邑县| 乐亭县| 黑水县| 宜宾市| 郸城县| 铜鼓县| 涟源市| 金门县| 固原市| 沈阳市| 平安县|