首页 > 其他分享 >Spring Boot 参数校验

Spring Boot 参数校验

时间:2023-02-13 17:14:33浏览次数:42  
标签:Spring Boot 校验 value class private 注解 public

JSR-303

JSR-303 是 Java EE6中的一项子规范,叫做 Bean Validation,为 JavaBean 验证定义了相应的元数据模型和API,通过使用 xml 可以对原有的元数据信息进行覆盖和扩展,在应用程序中,通过使用 BeanValidation 或是自定义的 constraint即可确保数据模型的准确性。constraint 可以附加到字段,getter方法,类或者接口上面。对于一些特定的需求,用户还可以很容易的自定义constraint。Bean Validation 是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回。JSR-303 的依赖为:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

常用注解

注解 释意
@Null 必须为null
@NotNull 必须不为null
@AssertTrue 必须为true
@AssertFalse 必须为false
@Min(value) 必须是数字,且大于等于指定值
@Max(value) 必须是数字,且小于等于指定值
@DecimalMin(value) 必须是数字,且大于等于指定值
@DecimalMax(value) 必须是数字,且小于等于指定值
@Size(max, min) 大小必须在指定范围内
@Digits(integer, fraction) 必须是数字,且必须在可接受的范围内
@Past 必须是一个过去的日期(前一天的日期,时分秒不算在内)
@Future 必须是一个将来的日期
@Pattern(value) 必须符合指定的正则表达式
@Email 必须是邮箱地址
@Length 字符串大小必须在指定范围内
@NotEmpty 字符串必须非空
@Range 必须在合适范围内

JSR-303 使用

校验异常全局处理(封装异常报错信息返回)

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Result onException(Exception e) {
        List<ObjectError> allErrors = ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors();
        StringBuilder msg = new StringBuilder();
        for (ObjectError allError : allErrors) {
            FieldError fieldError = (FieldError)allError;
            msg.append(fieldError.getDefaultMessage()+";");
        }
        return new Result().setCode(2000).setMsg(msg.toString());
    }
}

简单校验

在参数接收类属性上添加校验注解

@Data
public class ArticleDto {

    @Min(value = 1, message = "id不能小于1")
    @Max(value = 100, message = "id不能大于100")
    private Integer id;

    @NotEmpty(message = "文章名不能为空")
    private String name;

    @NotEmpty(message = "出版社不能为空")
    private String publish;

    @Past
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date publishDate;
}

同一个属性可以添加多个约束注解。如例子中的 @Min 和 @Max
在 controller 请求方法接收参数地方加上 @Validated 注解,表示该参数需要进行参数校验操作。

@RestController
@RequestMapping("test")
public class TestController {

    @PostMapping("testArticle")
    public Result testArticle(@Validated @RequestBody ArticleDto articleDto) {
        System.out.println(articleDto);
        return Result.ok();
    }
}

在参数校验失败时后端会立即对错误信息进行返回并停止后面的处理操作。

{
    "code": 2000,
    "msg": "需要是一个过去的时间;文章名不能为空;",
    "data": null
}

分组校验

新增文章时不需要文章 id,因为文章 id 一般是后端或者数据库自动生成,但是修改文章时需要上传文章 id 来唯一标识某一篇文章内容,并且新增和修改都是使用的同一个 DTO 进行接收参数。

此时需要对这个文章参数校验进行分组,新增文章是一个分组,修改文章又是另一个分组,以此来区分文章 id 是否执行 @Null 和 @NotNull 校验。

所有的校验注解都有一个 groups 属性来指定分组。

dto 类属性添加注解,并指定校验分组

@Data
public class ArticleDto {

    @Min(value = 1, message = "id不能小于1")
    @Max(value = 100, message = "id不能大于100")
    @NotNull(groups = UpdateArticleGroup.class)
    @Null(groups = AddArticleGroup.class)
    private Integer id;

    // 可以指定两个分组都进行校验
    @NotEmpty(message = "文章名不能为空", groups = {UpdateArticleGroup.class, AddArticleGroup.class})
    private String name;

    @NotEmpty(message = "出版社不能为空", groups = {UpdateArticleGroup.class, AddArticleGroup.class})
    private String publish;

    @Past(groups = {UpdateArticleGroup.class, AddArticleGroup.class})
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date publishDate;

    // 添加文章校验分组
    public interface AddArticleGroup{}

    // 修改文章校验分组
    public interface UpdateArticleGroup{}
}

controller 指定使用哪个校验分组进行校验

@RestController
@RequestMapping("test")
public class TestController {

    @PostMapping("addArticle")
    public Result testArticle(@Validated(value = ArticleDto.AddArticleGroup.class) @RequestBody ArticleDto articleDto) {
        System.out.println(articleDto);
        return Result.ok();
    }

    @PostMapping("updateArticle")
    Result updateArticle(@Validated(value = ArticleDto.UpdateArticleGroup.class) @RequestBody ArticleDto articleDto) {
        System.out.println(articleDto);
        return Result.ok();
    }
}

嵌套校验

嵌套校验:一个实体中包含另外一个实体,并且这些实体都需要进行参数校验。
如文章的作者,一般也是一个单独的实体。

package com.example.demo.jsr.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import javax.validation.Valid;
import javax.validation.constraints.*;
import java.util.Date;

/**
 * @version 1.0
 * @date 2023/2/13 14:53
 * Description:
 */
@Data
public class ArticleDto {

	// ...文章其它属性...
	
	// 作者信息	
    @Valid
    @NotNull(message = "作者信息不能为空", groups = {UpdateArticleGroup.class, AddArticleGroup.class})
    private AuthorDto author;
}

只需要在嵌套的实体属性标注 @Valid 注解,则其中的属性也将会得到校验,否则不会校验

作者 dto 校验

@Data
public class AuthorDto {

    @NotNull(groups = ArticleDto.UpdateArticleGroup.class)
    @Null(groups = ArticleDto.AddArticleGroup.class)
    private Integer id;

    @NotEmpty(groups = {ArticleDto.AddArticleGroup.class, ArticleDto.UpdateArticleGroup.class})
    private String name;

    public interface AddAuthorGroup{}

    public interface UpdateAuthorGroup{}
}

嵌套校验针对分组校验仍然生效,如果嵌套的实体类中指定的分组与 @Validated 注解指定的分组不同,则不会进行校验。

自定义校验注解

例子:传入的数字要在列举的范围中,否则校验失败

首先,自定义一个校验注解

@Documented
@Constraint(validatedBy = {EnumValuesConstraintValidator.class})
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@NotNull(message = "不能为空")
public @interface EnumValues {

	String message() default "传入的值不在范围内";

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

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

    // 可传入的值
    int[] values() default {};
}

根据 Bean Validation API 规范,message,groups 和 payload 属性是必须的,自定义添加了一个 values 属性来接收限制的范围。

自定义校验注解可以复用内嵌的注解,比如 @EnumValues 上边标注了 @NotNull 注解,这样 @EnumValues 就兼具了 @NotNull 的功能。

然后创建 @Constraint 注解指定的校验器

public class EnumValuesConstraintValidator implements ConstraintValidator<EnumValues, Integer> {

    // 存储枚举的值
    private Set<Integer> ints = new HashSet<>();

    // 初始化方法
    // EnumValues 校验的注解
    @Override
    public void initialize(EnumValues values) {
        for (int item : values.values()) {
            ints.add(item);
        }
    }

    /**
     * @param value 入参传的值
     * @param context
     * @return
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        return ints.contains(value);
    }
}

在 dto 中使用自定义注解校验

@Data
public class AuthorDto {

    @EnumValues(values = {1,2}, message = "性别只能传1或2")
    private Integer gender;
}

标签:Spring,Boot,校验,value,class,private,注解,public
From: https://www.cnblogs.com/wangms821/p/17116979.html

相关文章

  • springboot网站部署方式
    1centos安装java官网下载java8jdk:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html选择x64CompressedArchive(1)mkdir/usr/local/ja......
  • springboot 读取配置 application.yml
    添加配配置信息spring:application:name:dataExChangePlatformdevtools:restart:enabled:trueadditional-paths:src/main/javae......
  • 微信小程序+SpringBoot实现文件上传与下载
    微信小程序+SpringBoot实现文件上传与下载​​1、文件上传​​​​1.1后端部分​​​​1.1.1引入ApacheCommonsFIleUpload组件依赖​​​​1.1.2设置上传文件大小限制......
  • spring 依赖注入DI(三)
    概念依赖注入(DependencyInjection,DI)。依赖:指Bean对象的创建依赖于容器.Bean对象的依赖资源.注入:指Bean对象所依赖的资源,由容器来设置和装配.Set注入(......
  • 【Spring IOC】Spring IOC 容器源码解析文章导读
    1 前言Spring老生常谈,JavaWeb程序员的必备,程序员不看源码不懂源码,路走不长,所以耐心看,边看操作。本文是SpringIOC源码分析系列文章的导读文章,将会着重介绍Spring的......
  • 面试难题:Spring AOP循环依赖,如何解决?
    面试难题:SpringAOP循环依赖,如何解决?问:Spring如何解决循环依赖?答:Spring通过提前曝光机制,利用三级缓存解决循环依赖(这原理还是挺简单的,参考:三级缓存、图解循环依赖原......
  • 【Spring-boot-route(十一)数据库配置信息加密+(十二)整合redis做为缓存】
    spring-boot-route(十一)数据库配置信息加密前言:SpringBoot最大的特点就是自动配置了,大大的减少了传统Spring框架的繁琐配置,通过几行简单的配置就可以完成其他组件的接入。比......
  • Bootstrap-table的客户端分页渲染表格
    文章目录​​一、前言:​​​​1、服务端分页地址:​​​​2、插件下载地址:​​​​二、客户端分页步骤:​​​​1、table标签:​​​​2、js渲染:​​​​2.1、表格初始化​​......
  • 利用bootstrap-table插件自带的打印功能打印表格
    文章目录​​1、前端代码:​​​​2、前端页面:​​​​1、表格数据展示​​​​2、点击打印按钮之后:​​​​3、插件下载地址:​​​​4、碰到的bug​​1、前端代码:<linkhre......
  • POI结合bootstrap-fileinput上传Excel内容到数据库
    文章目录​​一、准备工作​​​​1、POI依赖​​​​2、bootstrap-fileinput插件下载:​​​​二、代码部分​​​​1、前端代码:​​​​2、javascript渲染部分:​​​​3......