首頁  >  文章  >  Java  >  在 Spring Boot 中建立用於驗證的自訂註釋

在 Spring Boot 中建立用於驗證的自訂註釋

WBOY
WBOY原創
2024-07-25 01:52:13439瀏覽

Creating Custom Annotations for Validation in Spring Boot

在 Spring Boot 中建立用於驗證的自訂註釋

1. 概述

雖然 Spring 標準註解(@NotBlank、@NotNull、@Min、@Size 等)涵蓋了驗證使用者輸入時的許多用例,但有時我們需要為更具體的輸入類型建立自訂驗證邏輯。在本文中,我將示範如何建立自訂註解以進行驗證。

2. 設定

我們需要將 spring-boot-starter-validation 依賴項新增到我們的 pom.xml 檔案中。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

3. 自訂欄位層級驗證

3.1 建立註釋

讓我們建立自訂註解來驗證檔案屬性,例如檔案副檔名、檔案大小和 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 {};
}

  • 文件Mime類型驗證器
@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 {};
}

讓我們分解這些註解的組成部分:

  • @Constraint:指定負責驗證邏輯的驗證器類別。
  • @Target({ElementType.FIELD}):表示此註解只能套用於欄位。
  • message(): 驗證失敗時預設的錯誤訊息。

3.2 建立驗證器

  • 檔案副檔名驗證器
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;
    }
}

  • 文件Mime類型驗證器
@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(一個旨在從多種類型的文件中提取元資料和內容的工具包)。

3.3 應用註釋

讓我們建立一個 TestUploadRequest 類,用於處理檔案上傳,特別是 PDF 檔案。

@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");
    }
}

  • @Target({ElementType.TYPE}):表示此註解的目標是類型宣告。

4. 自訂類別等級驗證

也可以在類別層級定義自訂驗證註解來驗證類別中的欄位組合。

4.1 建立註釋

讓我們建立 @PasswordMatches 註解來確保類別中的兩個密碼欄位符合。

@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 {};
}

4.2 建立驗證器

  • 密碼Dto
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 接口,並包含用於驗證密碼和確認密碼欄位是否匹配的邏輯。

4.3 應用註釋

讓我們建立一個 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");
    }
}

5. 總結

在這篇短文中,我們發現建立自訂註解來驗證欄位或類別是多麼容易。本文中的程式碼可以在我的 Github 上找到。

  • spring-boot-微服務
  • 用戶服務

6. 參考文獻

  • 拜爾東。 (日期不詳)。 Spring MVC 自訂驗證器。已檢索 取自 https://www.baeldung.com/spring-mvc-custom-validator

以上是在 Spring Boot 中建立用於驗證的自訂註釋的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn