在 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中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

公司安全软件导致部分应用无法正常运行的排查与解决方法许多公司为了保障内部网络安全,会部署安全软件。...

将姓名转换为数字以实现排序的解决方案在许多应用场景中,用户可能需要在群组中进行排序,尤其是在一个用...

系统对接中的字段映射处理在进行系统对接时,常常会遇到一个棘手的问题:如何将A系统的接口字段有效地映�...

在使用IntelliJIDEAUltimate版本启动Spring...

在使用MyBatis-Plus或其他ORM框架进行数据库操作时,经常需要根据实体类的属性名构造查询条件。如果每次都手动...

Java对象与数组的转换:深入探讨强制类型转换的风险与正确方法很多Java初学者会遇到将一个对象转换成数组的�...

电商平台SKU和SPU表设计详解本文将探讨电商平台中SKU和SPU的数据库设计问题,特别是如何处理用户自定义销售属...

Redis缓存方案如何实现产品排行榜列表的需求?在开发过程中,我们常常需要处理排行榜的需求,例如展示一个�...
