知識庫 / Spring RSS 訂閱

Spring Validation 消息插值

Spring
HongKong
2
01:11 PM · Dec 06 ,2025

1. 簡介

消息插值是指用於創建 Java Bean 驗證約束錯誤消息的過程。例如,我們可以通過為帶有 jakarta.validation.constraints.NotNull 註解的字段提供 null 值來查看消息。

在本教程中,我們將學習如何使用默認的 Spring 消息插值以及如何創建自定義插值機制。

要查看除了 jakarta.validation.validation 之外的其他庫提供的約束示例,請查看 Hibernate Validator 特定約束。我們還可以創建自定義 Spring Validation 註解。

2. 默認消息插值

在查看代碼片段之前,我們先考慮一個 HTTP 400 響應,其中包含默認的 @NotNull 約束違規消息的示例:

{
    ....
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            ....
            "defaultMessage": "must not be null",
            ....
        }
    ],
    "message": "Validation failed for object='notNullRequest'. Error count: 1",
    ....
}

Spring 從消息描述符中檢索約束違反消息的詳細信息。 每個約束都使用 message 屬性定義其默認消息描述符。但是,當然,我們也可以使用自定義值覆蓋它。

例如,我們將創建一個簡單的 REST 控制器,其中包含一個 POST 方法:

@RestController
public class RestExample {

    @PostMapping("/test-not-null")
    public void testNotNull(@Valid @RequestBody NotNullRequest request) {
        // ...
    }
}

請求體將被映射到 NotNullRequest 對象,該對象只有一個 String 字段,並使用 @NotNull 註解標記:

public class NotNullRequest {

    @NotNull(message = "stringValue has to be present")
    private String stringValue;

    // getters, setters
}

現在,當我們發送一個驗證檢查失敗的 POST 請求時,我們會看到自定義的錯誤消息:

{
    ...
    "errors": [
        {
            ...
            "defaultMessage": "stringValue has to be present",
            ...
        }
    ],
    ...
}

唯一改變的是 defaultMessage。但我們仍然獲取了大量的關於錯誤代碼、對象名稱、字段名稱等信息。為了限制顯示的數值數量,我們可以實現自定義錯誤消息處理,用於 REST API。

3. 使用消息表達式進行插值

在 Spring 中,我們可以使用統一表達式語言來定義我們的消息描述符。 這允許我們定義基於條件邏輯的錯誤消息,並還啓用了高級格式選項

為了更清楚地理解這一點,讓我們來看幾個例子。

在每個約束註解中,我們可以訪問正在驗證的字段的實際值:

@Size(
  min = 5,
  max = 14,
  message = "The author email '${validatedValue}' must be between {min} and {max} characters long"
)
private String authorEmail;

我們的錯誤消息將包含屬性的實際值以及 minmax 參數,這些參數來自 @Size 註解:

"defaultMessage": "The author email '[email protected]' must be between 5 and 14 characters long"

請注意,訪問外部變量時,我們使用 ${} 語法,但訪問驗證註解中的其他屬性時,我們使用 {}

三元運算符的使用也是可行的:

@Min(
  value = 1,
  message = "There must be at least {value} test{value > 1 ? 's' : ''} in the test case"
)
private int testCount;
<p>Spring 將三元運算符轉換為單個值,在錯誤消息中:</p>
"defaultMessage": "There must be at least 2 tests in the test case"

我們可以也可以調用外部變量的方法:

@DecimalMin(
  value = "50",
  message = "The code coverage ${formatter.format('%1$.2f', validatedValue)} must be higher than {value}%"
)
private double codeCoverage;

無效輸入將產生一個帶有格式化值的錯誤消息:

"defaultMessage": "The code coverage 44.44 must be higher than 50%"
<div>
 <p>如這些示例所示,諸如 <em >{, }, $,</em > 和 <em >/</em > 這樣的字符在消息表達式中使用,因此在使用它們時,必須使用反斜槓字符進行轉義:<em >\{, \}, \$,</em > 和 <em >\\</em >。</p>
</div

4. 自定義消息插值

在某些情況下,我們可能需要實現一個自定義消息插值引擎。 要做到這一點,我們首先必須實現 jakarta.validation.MessageInterpolation 接口:

public class MyMessageInterpolator implements MessageInterpolator {
    private final MessageInterpolator defaultInterpolator;

    public MyMessageInterpolator(MessageInterpolator interpolator) {
        this.defaultInterpolator = interpolator;
    }

    @Override
    public String interpolate(String messageTemplate, Context context) {
        messageTemplate = messageTemplate.toUpperCase();
        return defaultInterpolator.interpolate(messageTemplate, context);
    }

    @Override
    public String interpolate(String messageTemplate, Context context, Locale locale) {
        messageTemplate = messageTemplate.toUpperCase();
        return defaultInterpolator.interpolate(messageTemplate, context, locale);
    }
}

在本次簡單的實現中,我們只是將錯誤消息轉換為大寫。通過這樣做,我們的錯誤消息將顯示為:

"defaultMessage": "THE CODE COVERAGE 44.44 MUST BE HIGHER THAN 50%"

我們還需要在 jakarta.validation.Validation 工廠中 註冊我們的插值器

Validation.byDefaultProvider().configure().messageInterpolator(
  new MyMessageInterpolator(
    Validation.byDefaultProvider().configure().getDefaultMessageInterpolator())
);

5. 結論

在本文中,我們學習了默認的 Spring 消息插值機制及其創建自定義消息插值引擎的方法。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.