Rumah > Jawa > tutorial java > teks badan

Creating Custom Annotations for Validation in Spring Boot

WBOY
Lepaskan: 2024-07-25 01:52:13
asal
253 人浏览过

Creating Custom Annotations for Validation in Spring Boot

Creating Custom Annotations for Validation in Spring Boot

1. Overview

While Spring standard annotations (@NotBlank, @NotNull, @Min, @Size, etc.) cover many use cases when validating user input, there are times when we need to create custom validation logic for a more specific type of input. In this article, I will demonstrate how to create custom annotations for validation.

2. Setup

We need to add the spring-boot-starter-validation dependency to our pom.xml file.


    org.springframework.boot
    spring-boot-starter-validation

Salin selepas log masuk

3. Custom Field Level Validation

3.1 Creating the Annotation

Let’s create custom annotations to validate file attributes, such as file extension, file size, and MIME type.

  • ValidFileExtension
@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[] payload() default {};
}
Salin selepas log masuk
  • ValidFileMaxSize
@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[] payload() default {};
}

Salin selepas log masuk
  • FileMimeTypeValidator
@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[] payload() default {};
}
Salin selepas log masuk

Let's break down these annotations' components:

  • @Constraint: Specifies the validator class responsible for the validation logic.
  • @Target({ElementType.FIELD}): Indicates that this annotation can only be applied to fields.
  • message(): The default error message if the validation fails.

3.2 Creating the Validator

  • FileExtensionValidator
public class FileExtensionValidator implements ConstraintValidator {

    private List 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());
    }
}
Salin selepas log masuk
  • FileMaxSizeValidator
public class FileMaxSizeValidator implements ConstraintValidator {

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

Salin selepas log masuk
  • FileMimeTypeValidator
@RequiredArgsConstructor
public class FileMimeTypeValidator implements ConstraintValidator {

    private final Tika tika;
    private List 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);
    }
}

Salin selepas log masuk

These classes are implementations of the ConstraintValidator interface and contain the actual validation logic.
For FileMimeTypeValidator, we will use Apache Tika (a toolkit designed to extract metadata and content from numerous types of documents).

3.3 Applying the Annotation

Let's create a TestUploadRequest class intended for handling file uploads, specifically for a PDF file.

@Data
public class TestUploadRequest {

    @NotNull
    @ValidFileMaxSize(maxSize = 10)
    @ValidFileExtension(extensions = {"pdf"})
    @ValidFileMimeType(mimeTypes = {"application/pdf"})
    private MultipartFile pdfFile;

}

Salin selepas log masuk
@RestController
@Validated
@RequestMapping("/test")
public class TestController {

    @PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public ResponseEntity testUpload(@Valid @ModelAttribute TestUploadRequest request) {
        return ResponseEntity.ok("test upload");
    }
}

Salin selepas log masuk
  • @Target({ElementType.TYPE}): Indicates that this annotation targets a type declaration.

4. Custom Class Level Validation

A custom validation annotation can also be defined at the class level to validate a combination of fields within a class.

4.1 Creating the Annotation

Let’s create @PasswordMatches annotation to ensure that two password fields match in a class.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
        validatedBy = {PasswordMatchesValidator.class}
)
public @interface PasswordMatches {
    String message() default "{constraints.PasswordMatches.message}";

    Class[] groups() default {};

    Class[] payload() default {};
}

Salin selepas log masuk

4.2 Creating the Validator

  • PasswordDto
public interface PasswordDto {
    String getPassword();

    String getConfirmPassword();
}


Salin selepas log masuk
  • PasswordMatchesValidator
public class PasswordMatchesValidator implements ConstraintValidator {

    @Override
    public boolean isValid(PasswordDto password, ConstraintValidatorContext constraintValidatorContext) {
        return StringUtils.equals(password.getPassword(), password.getConfirmPassword());
    }
}

Salin selepas log masuk

The PasswordDto interface is an interface for objects that contain a password and a confirm password field.
The PasswordMatchesValidator class implements the ConstraintValidator interface and contains the logic for validating that the password and confirm password fields match.

4.3 Applying the Annotation

Let's create a RegisterAccountRequest class intended for handling user registration data.

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

Salin selepas log masuk
@RestController
@Validated
@RequestMapping("/auth")
public class AuthController {

    @PostMapping("/register")
    public ResponseEntity register(@RequestBody @Valid RegisterAccountRequest request) {
        return ResponseEntity.ok("register success");
    }
}

Salin selepas log masuk

5. Summary

In this short article, we discovered how easy it is to create custom annotations to verify a field or class. The code from this article is available over on my Github.

  • spring-boot-microservices
  • user-service

6. References

  • Baeldung. (n.d.). Spring MVC Custom Validator. Retrieved from https://www.baeldung.com/spring-mvc-custom-validator

以上是Creating Custom Annotations for Validation in Spring Boot的详细内容。更多信息请关注PHP中文网其他相关文章!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!