SpringBoot Validation依赖使用

Validation 作用

在开发过程中经常会用到参数校验的过程,例如在用户注册过程中需要校验用户注册的信息是否合法,如果用 if else语句来判断的话,当判断条件很多时会很麻烦, 而 Validation 依赖就可以很好的解决这个问题。

使用

导入依赖

在 pom.xml 文件中导入 validation 依赖

	<dependencies>
		<!--validation 依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
    </dependencies>

在类中加入 @Validated 注解

示例一

@Validated
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/register")
    public Result register(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password){
        // 查看用户名是否被占用
        User user = userService.findByUsername(username);
        if (null == user) {
            userService.register(username, password);
        }
        // 已被占用
        else{
            return Result.error("用户名已被占用");
        }
        return Result.success();
    }
}

在这段代码中,在注册时要判断用户名和密码的长度在5-16范围内,若用寻常的方式则会像下面这样比较繁琐

@PostMapping("/register")
public Result register(String username, String password){
    if (username!=null && username.length()>=5 && username.length()<=16 &&
            password!=null && password.length()>=5 && password.length()<=16){
            //查询用户
            User u = userService.findByUserName(username);
            if (u==null){
                //没有占用
                //注册
				userService.register(username,password);
                return Result.success();
            }else{
				//占用
               return Result.error("用户名已被占用");
            }
    }else{     
    	return Result.error("参数不合法");
	}
}

示例二

当前端出入的是一个实体类,而我们需要对类中的某些字段进行参数校验时,就无法用上述提到的 @Pattern 注解了,可以找到对应的实体类,在实体类中加入相对应的注解,例如这里的非空注解 @NotEmpty 使用下面的方式。

import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.groups.Default;
import lombok.Data;

import java.time.LocalDateTime;
@Data
public class Category {
    @NotNull
    private Integer id;//主键ID
    
    @NotEmpty
    private String categoryName;//分类名称
    
    @NotEmpty
    private String categoryAlias;//分类别名
    
    private Integer createUser;//创建人ID
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;//创建时间
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;//更新时间
}

然后在 Controller 层加入 @Validation 注解使校验条件生效

@RestController
@RequestMapping("/category")
public class CategoryController {

    @Autowired
    private CategoryService categoryService;

    @PostMapping
    public Result add(@RequestBody @Validated Category category){
        categoryService.add(category);
        return Result.success();
    }
}

校验分组

在开发过程中会碰到这种情况:当添加用户时,id 是由后端自动生成的,不需要校验 id 是否为空,而在修改用户 id 时则需要校验。如果在 User 实体类上添加 @NotNull 注解,则添加和修改用户的业务会冲突,这时候就需要用到分组校验。
例如在示例二的代码中,添加分组校验后的结果为

import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.groups.Default;
import lombok.Data;

import java.time.LocalDateTime;
@Data
public class Category {
    @NotNull(groups = Update.class)
    private Integer id;//主键ID
    @NotEmpty
    private String categoryName;//分类名称
    @NotEmpty
    private String categoryAlias;//分类别名
    private Integer createUser;//创建人ID
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;//创建时间
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;//更新时间

    //如果说某个校验项没有指定分组,默认属于Default分组
    //添加了指定分组的校验只属于自定义分组,不属于 Default 分组
    //分组之间可以继承, A extends B  那么A中拥有B中所有的校验项

    public interface Add extends Default {

    }

    public interface Update extends Default{

    }
}

对应 Controller 代码如下,在增加和修改文章信息的方法中指明要使用哪个分组校验规则。

@RestController
@RequestMapping("/category")
public class CategoryController {

    @Autowired
    private CategoryService categoryService;

    // 新增文章信息
    @PostMapping
    public Result add(@RequestBody @Validated(value = Category.Add.class) Category category){
        categoryService.add(category);
        return Result.success();
    }
    // 修改文章信息
    @PutMapping
    public Result update(@RequestBody @Validated(value = Category.Update.class) Category category){
        categoryService.update(category);
        return Result.success();
    }
}

自定义校验规则

在开发过程中可能会碰到 @Validated 中自带的参数校验无法满足开发场景,此时就需要用到自定义的参数校验。
例如这里需要对 Article 类中的 state 属性进行校验,使其值只能是 “草稿” 或“已发布”,这里采用了自定义校验规则@State。 其他属性可用 @Validated 自带的校验规则。

import com.itheima.anno.State;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import org.hibernate.validator.constraints.URL;

import java.time.LocalDateTime;
@Data
public class Article {
    private Integer id;//主键ID
    @NotEmpty
    @Pattern(regexp = "^\\S{1,10}$")
    private String title;//文章标题
    @NotEmpty
    private String content;//文章内容
    @NotEmpty
    @URL
    private String coverImg;//封面图像

    @State
    private String state;//发布状态 已发布|草稿
    @NotNull
    private Integer categoryId;//文章分类id
    private Integer createUser;//创建人ID
    private LocalDateTime createTime;//创建时间
    private LocalDateTime updateTime;//更新时间
}

定义校验规则步骤为两步:

1.创建自定义注解, 这里取名为State

@Documented//元注解,表示自定义的State注解是可以抽取到帮助文档里面的
@Target({ FIELD})//元注解,标识自定义的State注解可以用在哪些地方,因为这里只用在属性上,所以只写了FIELD
@Retention(RUNTIME)//元注解,标识该注解将来会在那个阶段保留,这里标识是运行时阶段
@Constraint(validatedBy = { StateValidation.class})//指定提供校验规则的类
public @interface State {
    //提供校验失败后的提示信息
    String message() default "state参数的值只能是已发布或者草稿";
    //指定分组
    Class<?>[] groups() default { };
    //负载  获取到State注解的附加信息
    Class<? extends Payload>[] payload() default { };
}

在自定义注解时可以参考官方注解定义方式

@Documented
@Constraint(
    validatedBy = {}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(NotEmpty.List.class)
public @interface NotEmpty {
    String message() default "{jakarta.validation.constraints.NotEmpty.message}";

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

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

    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        NotEmpty[] value();
    }
}

2.创建实现自定义注解 State 的类

// ConstraintValidator<给哪个注解提供校验规则,校验的数据类型> 
public class StateValidation implements ConstraintValidator<State,String> {
    /**
     *
     * @param value 将来要校验的数据
     * @param context context in which the constraint is evaluated
     *
     * @return 如果返回false,则校验不通过,如果返回true,则校验通过
     */
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        //提供校验规则
        if (value == null){
            return false;
        }
        if (value.equals("已发布") || value.equals("草稿")){
            return true;
        }
        return false;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值