SpringBoot中的实体参数校验及分组校验

目录

[1 前言](#1 前言)

[2 实体参数校验的常用注解及使用方法](#2 实体参数校验的常用注解及使用方法)

[2.1 常用注解](#2.1 常用注解)

[2.2 使用方法](#2.2 使用方法)

[2.2.1 在pom.xml中引入相关依赖](#2.2.1 在pom.xml中引入相关依赖)

[2.2.2 在实体类上添加需要注解](#2.2.2 在实体类上添加需要注解)

[2.2.3 在controller类的相关方法中添加@Validated](#2.2.3 在controller类的相关方法中添加@Validated)

[2.2.4 编写异常处理器](#2.2.4 编写异常处理器)

[3 利用分组校验解决相关bug](#3 利用分组校验解决相关bug)

[3.1 bug的发现](#3.1 bug的发现)

[3.2 解决bug](#3.2 解决bug)

[3.2.1 定义分组](#3.2.1 定义分组)

[3.2.2 为注解分配分组](#3.2.2 为注解分配分组)

[3.2.3 为controller类的方法分配分组](#3.2.3 为controller类的方法分配分组)

[4 利用Default进行优化](#4 利用Default进行优化)

[4.1 对实体类的优化](#4.1 对实体类的优化)

[4.2 controller类的方法的优化](#4.2 controller类的方法的优化)


1 前言

在开发的过程中,我们常常需要对传送过来的参数进行校验,其中就有实体参数校验如下:

java 复制代码
public class UserController {
    //其它代码...
    //这里我们需要对user中的数据进行校验
    public Result update(@RequestBody User user) {
        //其它...
    }
}

在进行实体参数校验的时候,使用注解能极大的简化我们的代码并提升开发速度,接下来我会介绍几种常用的注解及其展示其使用方法,并对相关bug进行解决和优化。

2 实体参数校验的常用注解及使用方法

2.1 常用注解

注解 作用
@NotNull 值不能为Null
@NotEmpty 值不能为Null,且内容不能为空
@Email 满足邮箱格式
@URL 满足链接格式
@Pattern(regexp = "^\\S{x,y}$") 字符串不能为空,且长度范围为[x,y]

2.2 使用方法

2.2.1 在pom.xml中引入相关依赖

XML 复制代码
<dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2.2.2 在实体类上添加需要注解

java 复制代码
public class User {
    @NotNull
    private Integer id;//主键ID
    @NotEmpty
    @Pattern(regexp = "^\\S{1,10}$")
    private String nickname;//昵称
    @NotEmpty
    @Email
    private String email;//邮箱
    @URL
    private String userPic;//用户头像地址
    //其它...
}

2.2.3 在controller类的相关方法中添加@Validated

java 复制代码
public class UserController {
    //其它代码...
    public Result update(@RequestBody @Validated User user) {
        //其它...
    }
}

2.2.4 编写异常处理器

此时如果直接使用,如果前端传送的数据不符合要求,那么就会直接返回一个状态码为500的报错,然而这并不是我们想要的,因此我们必须编写一个异常处理器。在我的这篇文章《浅析SpringBoot的API参数校验》中,除了有异常处理器的编写,另外还有这些常用注解的其它食用方法。请移步。

3 利用分组校验解决相关bug

3.1 bug的发现

完成上述步骤后,我们在使用的时候可能会发现一些bug,如下

这是我们的实体类

java 复制代码
public class Category {
    @NotNull
    private Integer id;//主键ID
    @NotEmpty
    private String categoryName;//分类名称
    @NotEmpty
    private String categoryAlias;//分类别名
    //其它...
}

这是我们的controller类

java 复制代码
public class CategoryController {
    //其它代码...
    //传入的json格式的数据只有categoryName和categoryAlias
    @PostMapping
    public Result add(@RequestBody @Validated Category category) {
        //其它...
    }
    //传入的json格式的数据除了categoryName和categoryAlias,还有id
    @PutMapping
    public Result update(@RequestBody @Validated Category category) {
        //其它..
    }
}

这时候如果我们使用add方法所对应的API接口时就会失败,因为我们的id设置了@NotNull,而add方法传送过来的参数却没有id。

3.2 解决bug

如果我们能对每个注解进行分组,不同方法对应不同分组,那么问题将迎刃而解,具体操作如下:

3.2.1 定义分组

java 复制代码
public class Category {
    @NotNull
    private Integer id;//主键ID
    @NotEmpty
    private String categoryName;//分类名称
    @NotEmpty
    private String categoryAlias;//分类别名

    public interface Add{}

    public interface Update{}
}

3.2.2 为注解分配分组

java 复制代码
public class Category {
    @NotNull(groups = Update.class)
    private Integer id;//主键ID
    @NotEmpty(groups = {Update.class,Add.class})
    private String categoryName;//分类名称
    @NotEmpty(groups = {Update.class,Add.class})
    private String categoryAlias;//分类别名

    public interface Add{}

    public interface Update{}
}

3.2.3 为controller类的方法分配分组

java 复制代码
public class CategoryController {
    //其它代码...
    //传入的json格式的数据只有categoryName和categoryAlias
    @PostMapping
    public Result add(@RequestBody @Validated(Category.Add.class) Category category) {
        //其它...
    }
    //传入的json格式的数据除了categoryName和categoryAlias,还有id
    @PutMapping
    public Result update(@RequestBody @Validated(Category.Update.class) Category category) {
        //其它..
    }
}

这样bug就被解决了,不过如何更优雅的解决问题,还得进行优化

4 利用Default进行优化

如果我们不对实体类中的注解进行分组,那么它们就属于默认分组Default,我们可以利用这一点和继承的方式对分组校验进行优化。

4.1 对实体类的优化

java 复制代码
public class Category {
    @NotNull(groups = Update.class)
    private Integer id;//主键ID
    @NotEmpty//默认分组
    private String categoryName;//分类名称
    @NotEmpty//默认分组
    private String categoryAlias;//分类别名

    //public interface Add{}
    //这里直接由Default代替了

    public interface Update extends Default{}
}

4.2 controller类的方法的优化

java 复制代码
public class CategoryController {
    //其它代码...
    //传入的json格式的数据只有categoryName和categoryAlias
    //默认即Default
    @PostMapping
    public Result add(@RequestBody @Validated Category category) {
        //其它...
    }
    //传入的json格式的数据除了categoryName和categoryAlias,还有id
    @PutMapping
    public Result update(@RequestBody @Validated(Category.Update.class) Category category) {
        //其它..
    }
}

对比优化前,是不是更加优雅和简洁了。

相关推荐
嗨小陈17 小时前
(免费源码)基于springboot的电影院订票系统设计与实现 计算机毕业设计 P10089
springboot·管理系统·计算机毕业设计·源代码·计算机大作业
武子康20 小时前
Java-33 深入浅出 Spring - FactoryBean 和 BeanFactory BeanPostProcessor
java·开发语言·后端·spring·springboot·springcloud
程序猿进阶1 天前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
旭久1 天前
SpringBoot的Thymeleaf做一个可自定义合并td的pdf表格
pdf·html·springboot
王ASC2 天前
SpringMVC的URL组成,以及URI中对/斜杠的处理,解决IllegalStateException: Ambiguous mapping
java·mvc·springboot·web
撒呼呼2 天前
# 起步专用 - 哔哩哔哩全模块超还原设计!(内含接口文档、数据库设计)
数据库·spring boot·spring·mvc·springboot
灰色孤星A2 天前
瑞吉外卖项目学习笔记(四)@TableField(fill = FieldFill.INSERT)公共字段填充、启用/禁用/修改员工信息
java·学习笔记·springboot·瑞吉外卖·黑马程序员·tablefield·公共字段填充
武子康4 天前
Java-31 深入浅出 Spring - IoC 基础 启动IoC XML与注解结合的方式 配置改造 applicationContext.xml
java·大数据·spring·mybatis·springboot
synda@hzy4 天前
MONI后台管理系统-系统三员的设计
java·springboot·等级保护·三员管理
灰色孤星A4 天前
瑞吉外卖项目学习笔记(二)Swagger、logback、表单校验和参数打印功能的实现
springboot·logback·swagger·瑞吉外卖·切面编程·表单校验·黑马程序员