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 省略
}
相关推荐
桦说编程16 分钟前
Java 中如何创建不可变类型
java·后端·函数式编程
lifallen17 分钟前
Java Stream sort算子实现:SortedOps
java·开发语言
IT毕设实战小研19 分钟前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi42 分钟前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
没有bug.的程序员1 小时前
JVM 总览与运行原理:深入Java虚拟机的核心引擎
java·jvm·python·虚拟机
甄超锋1 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
阿华的代码王国2 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Zyy~2 小时前
《设计模式》装饰模式
java·设计模式
Jimmy2 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
A尘埃2 小时前
企业级Java项目和大模型结合场景(智能客服系统:电商、金融、政务、企业)
java·金融·政务·智能客服系统