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 省略
}
相关推荐
+VX:Fegn08953 分钟前
计算机毕业设计|基于springboot + vue图书管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
AntBlack4 分钟前
忍不住推荐 : AI 时代 ,桌面端真的可以考虑一下Go+Wails 的组合
后端·go·ai编程
码事漫谈9 分钟前
C++20协程如何撕开异步编程的牢笼
后端
while(1){yan}11 分钟前
网络基础知识
java·网络·青少年编程·面试·电脑常识
Ulana15 分钟前
计算机基础10大高频考题解析
java·人工智能·算法
黄俊懿22 分钟前
【深入理解SpringCloud微服务】Seata(AT模式)源码解析——@GlobalTransactional注解与@globalLock生效的原理
java·spring cloud·微服务·云原生·架构·系统架构·架构师
wheelmouse778826 分钟前
一个优雅、通用、零侵入的 CSV 导出工具类(Java 实战)
java·开发语言
DevYK1 小时前
Coze Studio 二次开发(二)支持 MCP Server 动态配置
后端·agent·coze
cike_y1 小时前
JavaWeb-Request应用与Cookie&[特殊字符]️Session
java·开发语言·安全·java安全
掘金码甲哥1 小时前
在调度的花园里面挖呀挖
后端