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;我們的錯誤消息將包含屬性的實際值以及 min 和 max 參數,這些參數來自 @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 消息插值機制及其創建自定義消息插值引擎的方法。