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 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
bobz9652 小时前
tcp/ip 中的多路复用
后端
bobz9652 小时前
tls ingress 简单记录
后端
皮皮林5513 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
你的人类朋友3 小时前
什么是OpenSSL
后端·安全·程序员
bobz9654 小时前
mcp 直接操作浏览器
后端
前端小张同学6 小时前
服务器部署 gitlab 占用空间太大怎么办,优化思路。
后端
databook6 小时前
Manim实现闪光轨迹特效
后端·python·动效
武子康7 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在7 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net