动态

详情 返回 返回

28個驗證註解,通過業務案例讓你精通Java數據校驗(收藏篇) - 动态 详情

image.png
在現代軟件開發中,數據驗證是確保應用程序健壯性和可靠性的關鍵環節。Java Bean Validation (JSR 380) 作為一個功能強大的規範,為我們提供了一套全面的註解工具集,這些註解能夠幫助開發者在Java應用程序中以一種聲明式的方式執行數據驗證。從基本的非空驗證到複雜的正則表達式匹配,JSR 380規範及其實現,如Hibernate Validator,都為我們提供了豐富的選項來滿足各種驗證需求。

肖哥彈架構 跟大家“彈彈” 常用框架註解應用

@NotNull

1.1 註解作用介紹

@NotNull 註解用於確保被註解的字段不為 null。這在需要強制字段必須有值的情況下非常有用,例如,用户實體的用户名或電子郵件字段。

1.2 註解屬性介紹

  • message: 指定驗證失敗時返回的自定義錯誤消息。
  • groups: 指定此約束所屬的驗證組,用於在不同的場景下應用不同的驗證規則。
  • payload: 允許註解攜帶額外的元數據,這些元數據可以在驗證失敗時由驗證器使用。

    1.3 註解業務案例

    public class User {
    @NotNull(message = "用户名不能為空")
    private String username;
    
    // 其他用户屬性...
    }
    
    public class User {
    @NotNull(message = "用户名不能為空", groups = RegistrationChecks.class, payload = ErrorPayloads.class)
    private String username;
    
    // 用户名是用户身份的唯一標識,註冊時必須填寫。
    // groups屬性定義了此驗證屬於RegistrationChecks組,可用於部分驗證場景。
    // payload屬性可用於攜帶額外的元數據,供驗證器使用。
    }

    @NotBlank

    2.1 註解作用介紹

    @NotBlank 註解除了確保字符串不為 null 外,還檢查字符串至少有一個非空白字符。這適用於需要文本輸入的字段,如用户評論或表單提交。

    2.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。
  • groups: 指定驗證組。
  • payload: 額外數據。
  • trim: 布爾值,默認為 true,指示是否在驗證前去除字符串兩端的空白字符。

    2.3 註解業務案例

    public class Comment {
    @NotBlank(message = "評論內容不能為空", trim = true)
    private String content;
    
    // 其他評論屬性...
    }
    
    public class Comment {
    @NotBlank(message = "評論內容不能為空", trim = true, groups = CommentChecks.class, payload = ErrorPayloads.class)
    private String content;
    
    // 評論內容必須填寫,trim=true表示在驗證前去除兩端空白字符。
    // groups屬性定義了此驗證屬於CommentChecks組。
    }

    @NotEmpty

    3.1 註解作用介紹

    @NotEmpty 註解用於驗證字符串、集合或數組不為 null 且至少有一個元素(對於集合和數組)或至少有一個非空白字符(對於字符串)。

    3.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。
  • groups: 指定驗證組。
  • payload: 額外數據。

    3.3 註解業務案例

    public class Message {
    @NotEmpty(message = "消息內容不能為空")
    private String text;
    
    // 其他消息屬性...
    }
    
    public class Message {
    @NotEmpty(message = "消息內容不能為空", groups = MessageChecks.class, payload = ErrorPayloads.class)
    private String text;
    
    // 消息文本不能為空,適用於消息發送場景。
    }

    @Size

    4.1 註解作用介紹

    @Size 註解用於驗證字符串、集合、數組或Map的大小是否在指定的範圍內。

    4.2 註解屬性介紹

  • min: 指定最小大小。
  • max: 指定最大大小。
  • message: 自定義驗證失敗時的錯誤消息。
  • groups: 指定驗證組。
  • payload: 額外數據。

    4.3 註解業務案例

    public class Book {
    @Size(min = 1, max = 100, message = "書名長度必須在1到100個字符之間")
    private String title;
    
    // 其他書籍屬性...
    }
    
    public class Book {
    @Size(min = 1, max = 100, message = "書名長度必須在1到100個字符之間", groups = BookChecks.class, payload = ErrorPayloads.class)
    private String title;
    
    // 書名長度限制,適用於圖書管理系統。
    }

    @Past

    5.1 註解作用介紹

    @Past 註解用於驗證日期類型的字段是否表示過去的日期。

    5.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。

    5.3 註解業務案例

    import java.time.LocalDate;
    
    public class Event {
    @Past(message = "事件日期必須是過去的日期")
    private LocalDate eventDate;
    
    // 其他事件屬性...
    }
    
    import java.time.LocalDate;
    
    public class Event {
    @Past(message = "事件日期必須是過去的日期", groups = EventChecks.class, payload = ErrorPayloads.class)
    private LocalDate eventDate;
    
    // 事件日期應為過去日期,適用於歷史事件記錄。
    }

    @Future

    6.1 註解作用介紹

    @Future 註解用於驗證日期類型的字段是否表示未來的日期。

    6.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。

    6.3 註解業務案例

    public class Delivery {
    @Future(message = "預計送達日期必須是未來的日期")
    private LocalDate expectedDeliveryDate;
    
    // 其他送達屬性...
    }
    
    public class Delivery {
    @Future(message = "預計送達日期必須是未來的日期", groups = DeliveryChecks.class, payload = ErrorPayloads.class)
    private LocalDate expectedDeliveryDate;
    
    // 預計送達日期應為未來日期,適用於訂單處理系統。
    }

    @Pattern

    7.1 註解作用介紹

    @Pattern 註解用於驗證字符串是否與指定的正則表達式匹配。

    7.2 註解屬性介紹

  • regexp: 指定的正則表達式。
  • message: 自定義驗證失敗時的錯誤消息。
  • flags: 正則表達式的匹配標誌。

    7.3 註解業務案例

    public class UserRegistration {
    @Pattern(regexp = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
              message = "電子郵箱格式不正確" flags = {Pattern.Flag.CASE_INSENSITIVE})
    private String email;
    
    // 其他註冊屬性...
    }
    
    public class UserRegistration {
    @Pattern(regexp = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$", 
              message = "電子郵箱格式不正確", flags = {Pattern.Flag.CASE_INSENSITIVE}, groups = RegistrationChecks.class, payload = ErrorPayloads.class)
    private String email;
    
    // 電子郵箱格式驗證,適用於用户註冊表單。
    }

    @Min

    8.1 註解作用介紹

    @Min 註解用於驗證數值類型的字段是否大於或等於指定的最小值。

    8.2 註解屬性介紹

  • value: 指定的最小值。
  • message: 自定義驗證失敗時的錯誤消息。

    8.3 註解業務案例

    public class Product {
    @Min(value = 1, message = "購買數量不能少於1")
    private int quantity;
    
    // 其他產品屬性...
    }
    
    public class Product {
    @Min(value = 1, message = "購買數量不能少於1", groups = ProductChecks.class, payload = ErrorPayloads.class)
    private int quantity;
    
    // 購買數量驗證,適用於購物車系統。
    }

    @Max

    9.1 註解作用介紹

    @Max 註解用於驗證數值類型的字段是否小於或等於指定的最大值。

    9.2 註解屬性介紹

  • value: 指定的最大值。
  • message: 自定義驗證失敗時的錯誤消息。

    9.3 註解業務案例

    public class Product {
    @Max(value = 100, message = "庫存數量不能超過100")
    private int stock;
    
    // 其他產品屬性...
    }
    public class Product {
    @Max(value = 100, message = "庫存數量不能超過100", groups = StockChecks.class, payload = ErrorPayloads.class)
    private int stock;
    
    // 庫存數量驗證,適用於庫存管理系統。
    }

    @DecimalMin

    10.1 註解作用介紹

    @DecimalMin 註解用於驗證 BigDecimal 或包裝的數值類型字段是否大於或等於指定的十進制最小值。

    10.2 註解屬性介紹

  • value: 指定的十進制最小值。
  • inclusive: 布爾值,指示是否包含指定的邊界值(默認為 true)。
  • message: 自定義驗證失敗時的錯誤消息。

    10.3 註解業務案例

    public class Price {
    @DecimalMin(value = "0.00", inclusive = true, message = "價格必須非負")
    private BigDecimal value;
    
    // 其他價格屬性...
    }
    
    public class Price {
    @DecimalMin(value = "0.00", inclusive = true, message = "價格必須非負", groups = PriceChecks.class, payload = ErrorPayloads.class)
    private BigDecimal value;
    
    // 價格必須為非負值,適用於財務管理系統。
    }

    @DecimalMax

    11.1 註解作用介紹

    @DecimalMax 註解用於驗證 BigDecimal 或包裝的數值類型字段是否小於或等於指定的十進制最大值。

    11.2 註解屬性介紹

  • value: 指定的十進制最小值。
  • inclusive: 布爾值,指示是否包含指定的邊界值(默認為 true)。
  • message: 自定義驗證失敗時的錯誤消息。

    11.3 註解業務案例

    public class Price {
    @DecimalMax(value = "1000.00", inclusive = true, message = "價格不能超過1000")
    private BigDecimal value;
    
    // 其他價格屬性...
    }
    
    public class Price {
    @DecimalMax(value = "1000.00", inclusive = true, message = "價格不能超過1000", groups = PriceChecks.class, payload = ErrorPayloads.class)
    private BigDecimal value;
    
    // 價格上限驗證,適用於定價策略。
    }

    @Email

    12.1 註解作用介紹

    @Email 註解用於驗證字符串字段是否為有效的電子郵件地址。

    12.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。
  • regexp: 用於驗證電子郵件地址的正則表達式(可選)。

    12.3 註解業務案例

    public class User {
    @Email(message = "電子郵件地址無效")
    private String email;
    
    // 其他用户屬性...
    }
    
    public class User {
    @Email(message = "電子郵件地址無效", regexp = "^.+@.+\\..+$", groups = UserChecks.class, payload = ErrorPayloads.class)
    private String email;
    
    // 電子郵箱地址驗證,適用於用户信息管理。
    }

    @Valid

    13.1 註解作用介紹

    @Valid 註解用於遞歸地對關聯的對象或集合進行驗證。

    13.2 註解屬性介紹

  • groups: 指定嵌套對象應使用的驗證組。
  • payload: 額外數據。

    13.3 註解業務案例

    public class Order {
    @Valid
    private User user;
    
    @Valid
    private List<OrderItem> items;
    
    // 其他訂單屬性...
    }
    
    public class Order {
    @Valid(groups = OrderChecks.class, payload = ErrorPayloads.class)
    private User customer;
    
    // 遞歸驗證用户信息,適用於訂單處理。
    }

    ## @Positive

    14.1 註解作用介紹

    @Positive 註解用於驗證數值類型的字段是否嚴格大於 0。

    14.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。
  • groups: 指定驗證組。
  • payload: 額外數據。

    14.3 註解業務案例

public class Account {
    @Positive(message = "賬户餘額必須為正數")
    private BigDecimal balance;

    // 其他賬户屬性...
}

public class Account {
    @Positive(message = "賬户餘額必須為正數", groups = AccountChecks.class, payload = ErrorPayloads.class)
    private BigDecimal balance;

    // 賬户餘額驗證,適用於銀行賬户管理。
}

@PositiveOrZero

15.1 註解作用介紹

@PositiveOrZero 註解用於驗證數值類型的字段是否大於或等於 0。

15.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。
  • groups: 指定驗證組。
  • payload: 額外數據。

    15.3 註解業務案例

public class Account {
    @PositiveOrZero(message = "賬户餘額不能為負數")
    private BigDecimal balance;

    // 其他賬户屬性...
}

public class Account {
    @PositiveOrZero(message = "賬户餘額不能為負數", groups = AccountChecks.class, payload = ErrorPayloads.class)
    private BigDecimal balance;

    // 賬户餘額驗證,確保餘額非負。
}

@Negative

16.1 註解作用介紹

@Negative 註解用於驗證數值類型的字段是否嚴格小於 0。

16.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。
  • groups: 指定驗證組。
  • payload: 額外數據。

    16.3 註解業務案例

    public class Debt {
    @Negative(message = "債務金額必須為負數")
    private BigDecimal amount;
    
    // 其他債務屬性...
    }
    
    public class Debt {
    @Negative(message = "債務金額必須為負數", groups = DebtChecks.class, payload = ErrorPayloads.class)
    private BigDecimal amount;
    
    // 債務金額驗證,適用於債務管理。
    }

    @NegativeOrZero

    17.1 註解作用介紹

    @NegativeOrZero 註解用於驗證數值類型的字段是否小於或等於 0。

    17.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。
  • groups: 指定驗證組。
  • payload: 額外數據。

    17.3 註解業務案例

    public class Debt {
    @NegativeOrZero(message = "債務金額不能為正數")
    private BigDecimal amount;
    
    // 其他債務屬性...
    }
    public class Debt {
    @NegativeOrZero(message = "債務金額不能為正數", groups = DebtChecks.class, payload = ErrorPayloads.class)
    private BigDecimal amount;
    
    // 債務金額驗證,確保債務非正。
    }

    @Digits

    18.1 註解作用介紹

    @Digits 註解用於驗證數值類型的字段是否符合指定的整數和小數位數。

    18.2 註解屬性介紹

  • integer: 指定整數部分的最大位數。
  • fraction: 指定小數部分的最大位數。
  • message: 自定義驗證失敗時的錯誤消息。

    18.3 註解業務案例

    public class FinancialTransaction {
    @Digits(integer = 10, fraction = 2, message = "交易金額格式不正確")
    private BigDecimal amount;
    
    // 其他交易屬性...
    }
    public class FinancialTransaction {
    @Digits(integer = 10, fraction = 2, message = "交易金額格式不正確", groups = TransactionChecks.class, payload = ErrorPayloads.class)
    private BigDecimal amount;
    
    // 交易金額必須是最多10位整數和2位小數。
    }

    @PastOrPresent

    19.1 註解作用介紹

    @PastOrPresent 註解用於驗證日期類型的字段是否表示現在或過去的日期。

    19.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。

    19.3 註解業務案例

    import java.time.LocalDate;
    
    public class InsurancePolicy {
    @PastOrPresent(message = "保險生效日期必須為當前或過去的日期")
    private LocalDate effectiveDate;
    
    // 其他保險屬性...
    }
    import java.time.LocalDate;
    public class InsurancePolicy {
    @PastOrPresent(message = "保險生效日期必須為當前或過去的日期", groups = InsuranceChecks.class, payload = ErrorPayloads.class)
    private LocalDate effectiveDate;
    
    // 保險生效日期驗證,適用於保險單管理。
    }

    @FutureOrPresent

    20.1 註解作用介紹

    @FutureOrPresent 註解用於驗證日期類型的字段是否表示現在或未來的日期。

    20.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。

    20.3 註解業務案例

    public class Appointment {
    @FutureOrPresent(message = "預約日期必須是當前或未來的日期")
    private LocalDate appointmentDate;
    
    // 其他預約屬性...
    }
    public class Appointment {
    @FutureOrPresent(message = "預約日期必須是當前或未來的日期", groups = AppointmentChecks.class, payload = ErrorPayloads.class)
    private LocalDate appointmentDate;
    
    // 預約日期驗證,適用於預約系統。
    }

    @Valid

    21.1 註解作用介

    @Valid 註解用於遞歸地驗證關聯的對象或集合中的元素。

    21.2 註解屬性介紹

  • groups: 指定應應用於驗證的組。
  • payload: 指定應應用於驗證的額外數據。

    21.3 註解業務案例

    public class Order {
    @Valid
    private User customer;
    
    @Valid
    private List<OrderItem> items;
    
    // 其他訂單屬性...
    }
    public class Order {
    @Valid(groups = {OrderChecks.class, ItemChecks.class}, payload = {ErrorPayloads.class})
    private List<OrderItem> items;
    
    // 遞歸驗證訂單項列表,適用於訂單詳細處理。
    }

    @Validated

    22.1 註解作用介紹

    @Validated 註解用於指定驗證時使用的驗證組。

    22.2 註解屬性介紹

  • groups: 指定應應用於驗證的組。

    22.3 註解業務案例

    public class PaymentService {
    @Validated(PaymentChecks.class)
    public void processPayment(PaymentDetails details) {
        // 使用特定的驗證組來處理支付詳情
    }
    }
    public class PaymentService {
    @Validated(PaymentChecks.class)
    public void processPayment(@Validated(PaymentDetailsChecks.class) PaymentDetails details) {
        // 使用特定的驗證組來處理支付詳情。
    }
    }

    @ConvertGroup

    23.1 註解作用介紹

    @ConvertGroup 註解用於在驗證過程中將一個分組轉換為另一個分組。

    23.2 註解屬性介紹

  • from: 指定原始分組。
  • to: 指定目標分組。

    23.3 註解業務案例

    public class DataMigrationService {
    @ConvertGroup(from = LegacyDataChecks.class, to = CurrentDataChecks.class)
    public void migrateData(LegacyData data) {
        // 從舊數據驗證轉換為新數據驗證
    }
    }
    public class DataMigrationService {
    @ConvertGroup(from = LegacyDataChecks.class, to = CurrentDataChecks.class)
    public void migrateData(@Validated(LegacyDataChecks.class) LegacyData data) {
        // 從舊數據驗證轉換為新數據驗證。
    }
    }

    @ReportAsSingleViolation

    24.1 註解作用介紹

    @ReportAsSingleViolation 註解用於將驗證過程中的所有違反約束的情況報告為單個驗證錯誤。

    24.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。

    24.3 註解業務案例

    public class CriticalField {
    @ReportAsSingleViolation(message = "關鍵字段驗證失敗")
    private String field;
    
    // 其他屬性...
    }
    public class CriticalField {
    @ReportAsSingleViolation(message = "關鍵字段驗證失敗")
    private String field;
    
    // 將所有違反約束的情況報告為單個驗證錯誤。
    }

    @Groups

    25.1 註解作用介紹

    @Groups 註解用於指定驗證的分組,允許在不同場景下應用不同的驗證規則。

    25.2 註解屬性介紹

  • 無特定屬性,通常與 @Valid 或 @Validated 註解一起使用。

    25.3 註解業務案例

    public class User {
    @Valid
    private Profile profile;
    
    // 其他用户屬性...
    }
    public class Profile {
    @NotNull(groups = RegistrationChecks.class)
    private String biography;
    
    // 其他個人資料屬性...
    }

    @SafeHtml

    26.1 註解作用介紹

    @SafeHtml 註解用於驗證HTML內容是否是安全的,防止跨站腳本(XSS)攻擊。

    26.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。

    26.3 註解業務案例

    public class HtmlContent {
    @SafeHtml(message = "內容包含不安全的HTML")
    private String content;
    
    // 其他HTML內容屬性...
    }

    @EAN

    27.1 註解作用介紹

    @EAN 註解用於驗證國際標準書號(ISBN)或歐洲商品編號(EAN-13)。

    27.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。

    27.3 註解業務案例

    public class Product {
    @EAN(message = "無效的EAN或ISBN編號")
    private String ean;
    
    // 驗證國際標準書號或歐洲商品編號
    }

    @URL

    28.1 註解作用介紹

    雖然@URL註解在JSR 380規範中沒有定義,但Hibernate Validator提供了類似的功能,用於驗證字符串是否是有效的URL格式。

    28.2 註解屬性介紹

  • message: 自定義驗證失敗時的錯誤消息。
  • protocol: 指定必須的協議(如http, https)。
  • host: 指定必須的主機名。
  • port: 指定端口號。
  • regexp: 自定義的URL匹配正則表達式。

    28.3 註解業務案例

    public class Website {
    @URL(message = "無效的URL")
    private String url;
    
    // 其他網站屬性...
    }
    public class Website {
    @URL(message = "無效的URL", protocol = "https", host = "example.com", port = 443)
    private String url;
    
    // 驗證字符串是否是有效的URL格式

註解驗證綜合性案例

場景描述

電商平台,用户可以瀏覽商品、下單購買,並進行訂單管理。該平台需要驗證用户信息、商品詳情、訂單數據以及支付信息的準確性和有效性。

業務實體和驗證需求

  1. 用户信息(User):必須包含有效的電子郵件和非空的用户名。
  2. 商品詳情(Product):需要有有效的庫存數量和價格範圍。
  3. 訂單(Order):必須包含用户信息、商品列表,並且總金額必須為正數。
  4. 訂單項(OrderItem):每個訂單項需要驗證購買數量和商品ID。
  5. 支付信息(PaymentInfo):需要驗證支付金額是否正確,並且支付方式是否被接受。
import javax.validation.constraints.*;
import javax.validation.Valid;
import java.util.List;

public class ECommercePlatform {

    // 用户信息
    public class User {
        @Email(message = "電子郵件地址無效", groups = UserChecks.class)
        private String email;

        @NotBlank(message = "用户名不能為空", groups = UserChecks.class)
        private String username;

        // 用户相關方法...
    }

    // 商品詳情
    public class Product {
        @NotNull(message = "商品ID不能為空", groups = ProductChecks.class)
        private String productId;

        @PositiveOrZero(message = "庫存數量不能為負數", groups = ProductChecks.class)
        private int stock;

        @DecimalMin(value = "0.01", message = "商品價格必須至少為0.01", groups = ProductChecks.class)
        private BigDecimal price;

        // 商品相關方法...
    }

    // 訂單
    public class Order {
        @Valid
        private User user;

        @Valid
        @Size(min = 1, message = "訂單至少需要一個商品項", groups = OrderChecks.class)
        private List<OrderItem> items;

        @Positive(message = "訂單總金額必須為正數", groups = OrderChecks.class)
        private BigDecimal totalAmount;

        // 訂單相關方法...
    }

    // 訂單項
    public class OrderItem {
        @NotNull(message = "商品ID不能為空", groups = ItemChecks.class)
        private String productId;

        @Positive(message = "購買數量必須為正數", groups = ItemChecks.class)
        private int quantity;

        // 訂單項相關方法...
    }

    // 支付信息
    public class PaymentInfo {
        @Positive(message = "支付金額必須為正數", groups = PaymentChecks.class)
        private BigDecimal amount;

        @NotBlank(message = "支付方式不能為空", groups = PaymentChecks.class)
        private String method;

        // 支付信息相關方法...
    }
}

//驗證組定義
public interface UserChecks {}
public interface ProductChecks {}
public interface OrderChecks {}
public interface ItemChecks {}
public interface PaymentChecks {}

//錯誤元數據載荷
public class ErrorPayloads implements Payload {}

在這個綜合性業務場景中,我們使用了@NotNull@NotBlank@PositiveOrZero@DecimalMin@Positive@Email等註解來確保數據的有效性。@Valid註解用於遞歸驗證嵌套對象,而自定義驗證組(如UserChecksProductChecks等)允許我們在不同的場景下應用不同的驗證規則。ErrorPayloads類用於攜帶額外的元數據,這些元數據可以在驗證失敗時由驗證器使用。

在線預訂系統分組驗證

場景描述

在線預訂系統允許用户根據其類型(個人或公司)進行預訂。系統需要對不同類型的預訂應用不同的驗證規則。

import javax.validation.*;
import javax.validation.constraints.*;
import java.time.LocalDate;
import java.util.Set;

// 驗證組接口
public interface PersonalBookingChecks {}
public interface CorporateBookingChecks {}

// 預訂類型枚舉
public enum BookingType {
    PERSONAL, CORPORATE;
}

// 預訂實體類
public class Booking {
    private BookingType type;

    // 個人預訂字段
    @NotBlank(message = "個人預訂的姓名必須填寫", groups = PersonalBookingChecks.class)
    private String personalName;

    @Email(message = "個人預訂的電子郵箱格式必須正確", groups = PersonalBookingChecks.class)
    private String personalEmail;

    // 公司預訂字段
    @NotBlank(message = "公司預訂的公司名稱必須填寫", groups = CorporateBookingChecks.class)
    private String corporateName;

    @PositiveOrZero(message = "公司預訂的税務編號必須是非負數", groups = CorporateBookingChecks.class)
    private Long corporateTaxId;

    // 所有預訂類型共有的字段
    @NotNull(message = "入住日期不能為空")
    private LocalDate checkInDate;

    @NotNull(message = "退房日期不能為空")
    private LocalDate checkOutDate;

    // 用於設置預訂類型的setter方法
    public void setBookingType(BookingType type) {
        this.type = type;
    }
}

// 服務層驗證邏輯
public class BookingService {
    private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

    public void processBooking(Booking booking) {
        Set<ConstraintViolation<Booking>> violations;
        switch (booking.getType()) {
            case PERSONAL:
                violations = validator.validate(booking, PersonalBookingChecks.class);
                break;
            case CORPORATE:
                violations = validator.validate(booking, CorporateBookingChecks.class);
                break;
            default:
                throw new IllegalStateException("未知的預訂類型");
        }

        if (!violations.isEmpty()) {
            // 將驗證錯誤轉換為用户友好的字符串信息
            throw new IllegalArgumentException("預訂驗證失敗: " + formatValidationErrors(violations));
        }

        // 如果驗證通過,繼續處理預訂邏輯,例如保存到數據庫
        // 省略處理預訂的代碼...
    }

    private String formatValidationErrors(Set<ConstraintViolation<Booking>> violations) {
        StringBuilder sb = new StringBuilder();
        for (ConstraintViolation<Booking> violation : violations) {
            sb.append(violation.getPropertyPath()).append(": ").append(violation.getMessage()).append("\n");
        }
        return sb.toString();
    }

    // 省略其他服務方法...
}

// 測試類
public class BookingApplication {
    public static void main(String[] args) {
        BookingService service = new BookingService();
        Booking booking = new Booking();
        // 這裏設置了booking的屬性和類型...

        // 處理預訂
        service.processBooking(booking);
    }
}

上述代碼,Booking類包含了根據不同預訂類型(個人或公司)所需的不同字段,並使用相應的JSR 380註解進行了驗證。BookingService類中的processBooking方法根據Booking對象的類型使用分組驗證,並處理驗證結果。如果存在驗證錯誤,它將拋出一個包含所有錯誤的IllegalArgumentException異常。

Add a new 评论

Some HTML is okay.