9个Spring Boot参数验证高阶技巧,第8,9个代码量直接减半!

点击上方"程序员蜗牛g",选择"设为星标"跟蜗牛哥一起,每天进步一点点程序员蜗牛g大厂程序员一枚 跟蜗牛一起 每天进步一点点32篇原创内容**公众号

本篇文章将详细的介绍基于注解参数验证的9大技巧。

实战案例

2.1 基本注解

Spring Validation 提供了一组用于常见验证任务的标准如下示例:

在Controller接口参数上开启验证功能:

**

**

2.2 自定义注解验证

对于特定的业务规则,你可以创建自己的自定义验证约束。

**

**

typescript 复制代码
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {  @Resource  private UserRepository userRepository;  @Override  public boolean isValid(String username, ConstraintValidatorContext context) {    if (username == null) {      return true; // Let @NotNull handle null values    }    return !userRepository.existsByUsername(username);  }}

2.3 分组验证

分组验证允许你针对不同场景应用不同的规则,例如创建操作与更新操作。如下示例(定义分组):

使用分组

less 复制代码
public class ProductDTO {  @Null(groups = ValidationGroups.Create.class, message = "创建商品时ID必须为空")  @NotNull(groups = ValidationGroups.Update.class, message = "更新商品时商品ID不能为空")  private Long id;  @NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class})  private String name;}

分组验证

注意:使用 @Validated 注解,因为它是支持验证组的注解。@Valid 不支持。

2.4 嵌套验证

对于复杂对象,你可以验证嵌套对象和集合。

注意:使用 @Valid 注解需要级联验证的字段,以确保验证器深入检查嵌套对象。

2.5 方法级验证

你也可以直接对服务层方法进行验证,而不仅仅是对控制器参数进行验证。

如果你是在Controller方法上那么你 不需要 在类上使用@Validated注解。

2.6 错误消息国际化

当发生错误时我们可以通过2中方式来提示具体的错误消息。

  • 直接指定错误消息

**

**

直接通过 message 指定要展示的错误消息。

  • 使用占位符

message属性可以使用 {xxx} 语法,其中 xxx 为你在资源文件中定义的key。

接下来,新建 classpath:messages_zh_CN.properties 和 classpath:messages_en_US.properties 资源文件。

上面我们是使用的spring boot默认的basename,你可以自定义,通过 spring.messages.basename 属性配置。

2.7 编程验证

除了注解之外,你还可以手动触发验证。

适用于验证是有条件的复杂业务逻辑,或用于验证未通过控制器传递的对象。

2.8 组合验证

将多个基本约束组合成一个单一的、可复用的且更具表现力的注解。

less 复制代码
@NotNull@Size(min = 8, max = 30)@Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$",         message = "密码必须包含至少一个数字、小写字母、大写字母和特殊字符")@Target({ElementType.FIELD, ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = {})public @interface StrongPassword {
  String message() default "密码不符合安全要求";  Class<?>[] groups() default {};  Class<? extends Payload>[] payload() default {};}

使用组合注解

优点:提高代码可读性,并确保验证规则得到一致应用。

2.9 跨字段验证

根据字段与其他字段的关系来验证字段,例如确保 "确认密码" 字段与 "密码" 字段匹配。创建一个类级约束:

密码验证器

vbnet 复制代码
public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, Object> {  private String field;  private String fieldMatch;  @Override  public void initialize(PasswordMatches constraintAnnotation) {    this.field = constraintAnnotation.field();    this.fieldMatch = constraintAnnotation.fieldMatch();  }  @Override  public boolean isValid(Object value, ConstraintValidatorContext context) {    try {      // 通过反射获取字段值      Field field1 = value.getClass().getDeclaredField(field);      field1.setAccessible(true);      Object fieldValue1 = field1.get(value);      Field field2 = value.getClass().getDeclaredField(fieldMatch);      field2.setAccessible(true);      Object fieldValue2 = field2.get(value);      // 比较两个字段值(处理null情况)      if (fieldValue1 == null) {        return fieldValue2 == null;      }      return fieldValue1.equals(fieldValue2);    } catch (NoSuchFieldException | IllegalAccessException e) {      throw new RuntimeException("Failed to validate password fields", e);    }  }}

使用注解

Controller接口

less 复制代码
@PostMapping("/register")public ResponseEntity<?> register(@Valid @RequestBody UserRegistrationDTO dto, BindingResult result) {  if (result.hasErrors()) {    List<String> errors = result.getAllErrors()        .stream()        .map(err -> err.getDefaultMessage())        .toList() ;    return ResponseEntity.badRequest().body(errors);  }  return ResponseEntity.ok("Registration successful");}

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记 就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

相关推荐
yeyong6 小时前
咨询kimi关于设计日志告警功能,还是有启发的
后端
库森学长6 小时前
2025年,你不能错过Spring AI,那个汲取了LangChain灵感的家伙!
后端·openai·ai编程
Java水解6 小时前
Spring Boot 启动流程详解
spring boot·后端
学历真的很重要7 小时前
Claude Code Windows 原生版安装指南
人工智能·windows·后端·语言模型·面试·go
转转技术团队7 小时前
让AI成为你的编程助手:如何高效使用Cursor
后端·cursor
shellvon7 小时前
你怎么被识别的?从TLS到Canvas的设备追踪术
后端·算法
yinke小琪7 小时前
消息队列如何保证消息顺序性?从原理到代码手把手教你
java·后端·面试
考虑考虑7 小时前
Java实现墨水屏点阵图
java·后端·java ee
网安Ruler7 小时前
第49天:Web开发-JavaEE应用&SpringBoot栈&模版注入&Thymeleaf&Freemarker&Velocity
java·spring boot·后端