Spring の標準アノテーション (@NotBlank、@NotNull、@Min、@Size など) はユーザー入力を検証する際の多くのユースケースをカバーしていますが、より具体的なタイプの入力に対してカスタム検証ロジックを作成する必要がある場合があります。 。この記事では、検証用のカスタム アノテーションを作成する方法を説明します。
spring-boot-starter-validation 依存関係を pom.xml ファイルに追加する必要があります。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
ファイル拡張子、ファイル サイズ、MIME タイプなどのファイル属性を検証するカスタム アノテーションを作成しましょう。
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint( validatedBy = {FileExtensionValidator.class} ) public @interface ValidFileExtension { String[] extensions() default {}; String message() default "{constraints.ValidFileExtension.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint( validatedBy = {FileMaxSizeValidator.class} ) public @interface ValidFileMaxSize { long maxSize() default Long.MAX_VALUE; // MB String message() default "{constraints.ValidFileMaxSize.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint( validatedBy = {FileMimeTypeValidator.class} ) public @interface ValidFileMimeType { String[] mimeTypes() default {}; String message() default "{constraints.ValidFileMimeType.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
これらのアノテーションのコンポーネントを分解してみましょう:
public class FileExtensionValidator implements ConstraintValidator<ValidFileExtension, MultipartFile> { private List<String> extensions; @Override public void initialize(ValidFileExtension constraintAnnotation) { extensions = List.of(constraintAnnotation.extensions()); } @Override public boolean isValid(MultipartFile file, ConstraintValidatorContext constraintValidatorContext) { if (file == null || file.isEmpty()) { return true; } var extension = FilenameUtils.getExtension(file.getOriginalFilename()); return StringUtils.isNotBlank(extension) && extensions.contains(extension.toLowerCase()); } }
public class FileMaxSizeValidator implements ConstraintValidator<ValidFileMaxSize, MultipartFile> { private long maxSizeInBytes; @Override public void initialize(ValidFileMaxSize constraintAnnotation) { maxSizeInBytes = constraintAnnotation.maxSize() * 1024 * 1024; } @Override public boolean isValid(MultipartFile file, ConstraintValidatorContext constraintValidatorContext) { return file == null || file.isEmpty() || file.getSize() <= maxSizeInBytes; } }
@RequiredArgsConstructor public class FileMimeTypeValidator implements ConstraintValidator<ValidFileMimeType, MultipartFile> { private final Tika tika; private List<String> mimeTypes; @Override public void initialize(ValidFileMimeType constraintAnnotation) { mimeTypes = List.of(constraintAnnotation.mimeTypes()); } @SneakyThrows @Override public boolean isValid(MultipartFile file, ConstraintValidatorContext constraintValidatorContext) { if (file == null || file.isEmpty()) { return true; } var detect = tika.detect(TikaInputStream.get(file.getInputStream())); return mimeTypes.contains(detect); } }
これらのクラスは ConstraintValidator インターフェイスの実装であり、実際の検証ロジックが含まれています。
FileMimeTypeValidator の場合は、Apache Tika (さまざまな種類のドキュメントからメタデータとコンテンツを抽出するように設計されたツールキット) を使用します。
ファイルのアップロード、特に PDF ファイルの処理を目的とした TestUploadRequest クラスを作成しましょう。
@Data public class TestUploadRequest { @NotNull @ValidFileMaxSize(maxSize = 10) @ValidFileExtension(extensions = {"pdf"}) @ValidFileMimeType(mimeTypes = {"application/pdf"}) private MultipartFile pdfFile; }
@RestController @Validated @RequestMapping("/test") public class TestController { @PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) public ResponseEntity<String> testUpload(@Valid @ModelAttribute TestUploadRequest request) { return ResponseEntity.ok("test upload"); } }
カスタム検証アノテーションをクラス レベルで定義して、クラス内のフィールドの組み合わせを検証することもできます。
@PasswordMatches アノテーションを作成して、クラス内の 2 つのパスワード フィールドが一致することを確認しましょう。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint( validatedBy = {PasswordMatchesValidator.class} ) public @interface PasswordMatches { String message() default "{constraints.PasswordMatches.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
public interface PasswordDto { String getPassword(); String getConfirmPassword(); }
public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, PasswordDto> { @Override public boolean isValid(PasswordDto password, ConstraintValidatorContext constraintValidatorContext) { return StringUtils.equals(password.getPassword(), password.getConfirmPassword()); } }
PasswordDto インターフェースは、パスワードとパスワード確認フィールドを含むオブジェクトのインターフェースです。
PasswordMatchesValidator クラスは ConstraintValidator インターフェイスを実装し、パスワード フィールドとパスワード確認フィールドが一致することを検証するロジックを含みます。
ユーザー登録データを処理するための RegisterAccountRequest クラスを作成しましょう。
@PasswordMatches @Data public class RegisterAccountRequest implements PasswordDto { @NotBlank private String username; @NotBlank @Email private String email; @NotBlank @ToString.Exclude private String password; @NotBlank @ToString.Exclude private String confirmPassword; }
@RestController @Validated @RequestMapping("/auth") public class AuthController { @PostMapping("/register") public ResponseEntity<String> register(@RequestBody @Valid RegisterAccountRequest request) { return ResponseEntity.ok("register success"); } }
この短い記事では、フィールドまたはクラスを検証するためのカスタム アノテーションを作成することがいかに簡単であるかを発見しました。この記事のコードは私の Github から入手できます。
以上がSpring Boot での検証用のカスタム アノテーションの作成の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。