1. 序章

メッセージ補間は、 Java BeanValidation制約のエラーメッセージを作成するために使用されるプロセスです。 たとえば、javax.validation.constraints.NotNullアノテーションが付けられたフィールドにnull値を指定すると、メッセージを確認できます。

このチュートリアルでは、デフォルトのSpringメッセージ補間を使用する方法と、独自の補間メカニズムを作成する方法を学習します。

javax.validation 以外の制約を提供する他のライブラリの例を確認するには、 Hibernate Validator SpecificConstraintsをご覧ください。 カスタムSpringValidationアノテーションを作成することもできます。

2. デフォルトのメッセージ補間

コードスニペットに入る前に、デフォルトの@NotNull制約違反メッセージを含むHTTP400応答の例を考えてみましょう。

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

Springは、メッセージ記述子から制約違反メッセージの詳細を取得します。各制約は、message属性を使用してデフォルトのメッセージ記述子を定義します。 ただし、もちろん、カスタム値で上書きすることもできます。

例として、POSTメソッドを使用して単純なRESTコントローラーを作成します。

@RestController
public class RestExample {

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

リクエストの本文はNotNullRequestオブジェクトにマップされます。このオブジェクトには、@NotNullの注釈が付けられたStringファイルが1つだけあります。

public class NotNullRequest {

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

    // getters, setters
}

これで、この検証チェックに失敗したPOSTリクエストを送信すると、カスタムエラーメッセージが表示されます。

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

変更される唯一の値はdefaultMessageです。 ただし、エラーコード、オブジェクト名、フィールド名などに関する多くの情報はまだ取得されています。 表示される値の数を制限するために、RESTAPIのカスタムエラーメッセージ処理を実装できます。

3. メッセージ式による補間

Springでは、統合式言語を使用してメッセージ記述子を定義できます。 これにより、条件付きロジックに基づいてエラーメッセージを定義でき、高度なフォーマットオプションも有効になります。

それをより明確に理解するために、いくつかの例を見てみましょう。

すべての制約アノテーションで、検証されているフィールドの実際の値にアクセスできます。

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

エラーメッセージには、プロパティの実際の値と、@Sizeアノテーションのminおよびmaxパラメーターの両方が含まれます。

"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;

Springは、エラーメッセージで三項演算子を単一の値に変換します。

"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%"

これらの例からわかるように、 {、}、$、 / などの一部の文字はメッセージ式で使用されるため、使用する前にバックスラッシュ文字でエスケープする必要がありますそれらは文字通り: \ {、\}、\ $、および\\

4. カスタムメッセージ補間

場合によっては、カスタムメッセージ補間エンジンを実装する必要があります。 そのためには、最初にjavax.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%"

また、補間器javax.validation.Validationファクトリに登録する必要があります。

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

5. 結論

この記事では、デフォルトのSpringメッセージ補間がどのように機能するか、およびカスタムメッセージ補間エンジンを作成する方法を学習しました。

そして、いつものように、すべてのソースコードはGitHub利用できます。