@Validatedとは?使い方とバリデーションの基礎知識【初心者向け】

こんにちは!今回は、Spring Frameworkでデータのバリデーションに使用されるアノテーション、@Validatedについて詳しく解説します。@Validatedを使うことで、入力データの検証を簡単かつ柔軟に行えるようになります。

@Validatedとは?

@Validatedは、

「データを検証し、ルールに沿わないデータの受け取りを防ぐ」

アノテーションのことです。

通常、データのバリデーションは、アプリケーションが受け取るリクエストや保存するデータに対して重要な役割を果たします。ユーザーからの入力データが正しい形式か、必須項目が欠けていないかなどをチェックし、データベースや他のシステムに問題を引き起こすことなく、信頼性の高いデータ処理を実現します。

@Validatedを使用することで、以下のようなシナリオで役立ちます:

  • ユーザーフォームの入力検証:ユーザー登録時のデータチェック(例:メールアドレスが正しい形式か、パスワードが適切か)。
  • APIリクエストの検証:REST API経由で受け取ったデータが正しいかどうかを確認。
  • モデルクラスの検証:データベースに保存する前に、データの整合性をチェック。

基本的な使い方

まずは、簡単なコード例を見てみましょう。新しいユーザーを登録する際に、ユーザー名やメールアドレスの形式が正しいかどうかを検証する場合のケースです。

サーバー側のコード

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.*;

@RestController
@RequestMapping("/users")
@Validated
public class UserController {

    @PostMapping("/register")
    public String registerUser(@Valid @RequestBody UserDto userDto) {
        // 登録処理
        return "User registered successfully!";
    }
}

UserDtoの定義

public class UserDto {

    @NotBlank(message = "ユーザー名は必須です")
    private String username;

    @Email(message = "メールアドレスの形式が正しくありません")
    private String email;

    @Size(min = 8, message = "パスワードは8文字以上必要です")
    private String password;

    // ゲッター、セッター
}

バリデーションエラーのハンドリング

バリデーションに失敗した場合、Springは自動的に400 Bad Requestエラーを返します。また、エラーメッセージもレスポンスに含まれます。

例えば、usernameが空の場合や、emailが正しい形式でない場合、リクエストは拒否され、その理由がエラーメッセージとして返されます。

クライアント側のコード(APIリクエスト)

const user = {
  username: "",
  email: "invalid-email",
  password: "short"
};

fetch('http://localhost:8080/users/register', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(user)
}).then(response => response.json())
  .then(data => console.log(data));

この例では、ユーザー名が空で、メールアドレスの形式が正しくないため、バリデーションに失敗し、エラーメッセージが返されます。

@Validatedの応用例

@Validatedは、単なる入力データの検証にとどまらず、複雑なデータ検証やカスタムルールを適用する場合にも利用できます。

1. グループバリデーションの使用

データを検証する際に、状況に応じて異なるルールを適用したい場合、バリデーショングループを使うことができます。例えば、ユーザー登録時と更新時で異なるバリデーションルールを設定することが可能です。

public class UserDto {

    public interface CreateGroup {}
    public interface UpdateGroup {}

    @NotBlank(groups = CreateGroup.class, message = "ユーザー名は必須です")
    private String username;

    @Email(groups = {CreateGroup.class, UpdateGroup.class}, message = "メールアドレスの形式が正しくありません")
    private String email;

    @Size(min = 8, groups = CreateGroup.class, message = "パスワードは8文字以上必要です")
    private String password;
}

コントローラーでの使用例

@Validated(UserDto.CreateGroup.class)
@PostMapping("/register")
public String createUser(@Valid @RequestBody UserDto userDto) {
    return "User created!";
}

@Validated(UserDto.UpdateGroup.class)
@PutMapping("/update")
public String updateUser(@Valid @RequestBody UserDto userDto) {
    return "User updated!";
}

この例では、登録時にのみユーザー名とパスワードを検証し、更新時にはメールアドレスだけを検証します。

2. カスタムバリデータの作成

標準のバリデーションでは対応できない複雑な条件でデータを検証したい場合、カスタムバリデータを作成することが可能です。

カスタムバリデータの作成手順

まず、アノテーションを作成します。

@Constraint(validatedBy = CustomValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomConstraint {
    String message() default "無効な値です";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

次に、検証ロジックを実装します。

public class CustomValidator implements ConstraintValidator<CustomConstraint, String> {

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        // カスタム検証ロジックを実装
        return value != null && value.startsWith("valid");
    }
}

このカスタムバリデータを使って、特定の条件を満たすかどうかをチェックすることができます。

public class UserDto {

    @CustomConstraint
    private String customField;

    // ゲッター、セッター
}

3. メソッドレベルのバリデーション

@Validatedは、メソッド引数の検証にも使用できます。サービスクラスで、引数や戻り値に対してバリデーションを行いたい場合に便利です。

@Service
@Validated
public class UserService {

    public void updateUser(@NotNull Long id, @Valid UserDto userDto) {
        // 更新処理
    }

    @NotNull
    public UserDto getUserById(@Min(1) Long id) {
        // ユーザー取得処理
        return new UserDto();
    }
}

この例では、updateUserメソッドの引数やgetUserByIdの戻り値に対してバリデーションを行っています。

@Validatedの引数

@Validatedアノテーションの引数には、主に以下のものがあります。

  1. groups属性 特定のバリデーショングループを指定する場合に使用します。これにより、異なる場面で異なるバリデーションルールを適用できます。
@Validated(UserDto.UpdateGroup.class)
public void updateUser(@Valid @RequestBody UserDto userDto) {
    // 更新処理
}
  1. 複数のメソッドで適用 @Validatedは、クラスレベルだけでなく、個々のメソッドにも適用可能です。
@Validated
public void createUser(@Valid UserDto userDto) {
    // 登録処理
}

@Validだけでもいい?

実は@Validだけでも、基本的な機能は発揮します。
ただ、以下の2つの機能が使えなくなるので注意してください。

1. グループバリデーション

@Validはグループバリデーションをサポートしていません。特定のシチュエーションに応じたバリデーションルールを適用する場合は、@Validatedを使う必要があります。

@Validatedを使えば、ユーザー作成時と更新時で異なるバリデーションを適用することができますが、@Validではこれができません。

2. メソッドレベルのバリデーション

@Validatedは、メソッドレベルのバリデーションにも対応しています。これにより、引数や戻り値に対してもバリデーションを適用できますが、@Validは基本的にはメソッドの引数に対してのみ機能します。

このように、@Validatedを付けることで、メソッドの引数だけでなく、戻り値に対してもバリデーションを適用できるようになります。

おわりに

@Validatedを使えば、データのバリデーションを簡単に実装でき、システムの安全性や信頼性を高めることができます。今回は基本的な使い方から応用例まで紹介しましたので、ぜひ実際にコードを書いて試してみてください!バリデーションを適切に実装することで、ユーザー体験が向上し、エラーを未然に防ぐことができます。

もっと詳しく知りたい方は、Spring公式ドキュメントを見てみてくださいね。

他の記事が見たい方はこちら!↓↓↓

タイトルとURLをコピーしました