Spring Validation 校验 ( 二 )

4. 分组验证

Bean Validation 支持分组验证,这允许您根据不同的业务场景来定义不同的验证规则。

  • @Validated(group) : 用于控制器方法参数,指定一组验证规则。

  • @GroupSequence(groups) : 指定验证的顺序。

4.1.定义分组

下面是一个使用分组验证的示例:

java 复制代码
import jakarta.validation.groups.Default;

public interface UserGroups {
    interface Registration extends Default {}
    interface Login extends Default {}
}

4.2.设置验证规则

java 复制代码
import com.yuan.springvalidationdemo.valid.UserGroups;
import jakarta.validation.GroupSequence;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

@GroupSequence({UserGroups.Registration.class, UserGroups.Login.class})
public class User2 {
    @NotBlank(groups = UserGroups.Registration.class, message = "用户名在注册时不能为空")
    @Size(min = 5, max = 20, groups = {UserGroups.Registration.class, UserGroups.Login.class}, message = "用户名长度应在5到20个字符之间")
    private String username;

    @NotBlank(groups = UserGroups.Registration.class, message = "密码在注册时不能为空")
    @Size(min = 8, max = 32, groups = {UserGroups.Registration.class, UserGroups.Login.class}, message = "密码长度应在8到32个字符之间")
    private String password;

    @Email(groups = UserGroups.Registration.class, message = "邮箱格式不正确")
    private String email;
    
    // 构造函数、getter 和 setter 省略
}

在这个示例中,User2 类定义了两个验证组:RegistrationLoginusernamepassword 字段分别在不同的组中有不同的验证规则。当验证用户注册时,Registration 组的规则会被应用;当验证用户登录时,Login 组的规则会被应用。

4.3.Controller

java 复制代码
import com.yuan.springvalidationdemo.domain.User2;
import com.yuan.springvalidationdemo.valid.UserGroups;

import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;



@RestController
public class UserController3 {

    @PostMapping("/register3")
    public ResponseEntity<String> register(@Valid @RequestBody User2 user, BindingResult result) {
        if (result.hasErrors()) {
            // 如果有验证错误,则返回错误信息
            StringBuilder errorMessage = new StringBuilder();
            result.getFieldErrors().forEach(error -> {
                errorMessage.append(error.getDefaultMessage()).append("\n");
            });
            return ResponseEntity.badRequest().body(errorMessage.toString());
        }

        // 保存用户
        return ResponseEntity.ok("注册成功");
    }

    @PostMapping("/login3")
    @Validated({UserGroups.Login.class})
    public ResponseEntity<String> login(@Valid @RequestBody User2 user, BindingResult result) {
        if (result.hasErrors()) {
            // 如果有验证错误,则返回错误信息
            StringBuilder errorMessage = new StringBuilder();
            result.getFieldErrors().forEach(error -> {
                errorMessage.append(error.getDefaultMessage()).append("\n");
            });
            return ResponseEntity.badRequest().body(errorMessage.toString());
        }

        // 登录逻辑
        return ResponseEntity.ok("登录成功");
    }
}

通过 @Validated({UserGroups.Login.class}) 指定验证 分组规则

5. 自定义注解

可以创建自定义注解来定义特定的验证逻辑。

  • @Constraint(validatedBy = MyValidator.class) : 定义自定义注解时使用,指定自定义验证器类。

5.1. 定义验证注解

java 复制代码
import jakarta.validation.Constraint;
import jakarta.validation.Payload;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueUsernameValidator.class)
@Documented
public @interface UniqueUsername {

    String message() default "用户名必须唯一";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

5.2. 实现自定义验证器

java 复制代码
import com.yuan.springvalidationdemo.service.impl.UserServiceImpl;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {

    @Autowired
    private UserServiceImpl userService;

    @Override
    public boolean isValid(String username, ConstraintValidatorContext context) {
        return !userService.existsByUsername(username);
    }

5.3. 使用注解

java 复制代码
import com.yuan.springvalidationdemo.valid.UniqueUsername;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public class User3 {

    @NotBlank(message = "用户名不能为空")
    @Size(min = 5, max = 20, message = "用户名长度应在5到20个字符之间")
    @UniqueUsername
    private String username;

    @NotBlank(message = "密码不能为空")
    private String password;

      // 构造函数、getter 和 setter 省略
}
相关推荐
玉宇夕落2 分钟前
别再死磕 Prompt 了!上下文工程 (Context Engineering) 的简单学习
后端
用户342323237631724 分钟前
定时器与 PWM 输出详解
后端
Jason_chen2 小时前
Linux 6.2 CAN/CANFD机制详解
后端
plainGeekDev2 小时前
GreenDAO → Room
android·java·kotlin
Apifox2 小时前
Apifox 6 月更新|Apifox CLI 全面升级、导入导出优化、OAuth 2.0 支持自动刷新令牌
前端·后端·测试
悟空瞎说2 小时前
NestJS 接口设计避坑:摒弃万能用户更新接口,落地单一职责与最小权限原则
后端·nestjs
smallyoung2 小时前
Spring AI 2.0 VectorStore实战:从原理到RAG落地
人工智能·后端
jiayou642 小时前
KingbaseES 表级与列级加密完全指南
数据库·后端
青丘2 小时前
Spring AI整合Milvus向量数据库实战
后端