本文就来介绍一下在 SpringBoot 应用中怎么进行参数校验。
1.pom.xml依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
在 SpringBoot 项目中可以引用 spring-boot-starter-validation 实现数据验证。 spring-boot-starter-validation 不仅支持 JSR-303(Bean Validation 1.0)规范,还提供了对 JSR-380(Bean Validation 2.0)规范的全面支持。可以利用 Bean Validation 2.0 的新特性,更灵活地定义验证规则,包括对集合、嵌套对象的验证等。
2.@Validated 和@Valid 的区别
来源
@Validated:Spring 框架特有的注解,是标准 JSR-303 的一个变种,提供了一个分组功能
@Valid:标准 JSR-303 规范的标记型注解。
注解位置
@Validated:作用在类上、方法上、方法参数上,不能作用于成员属性上。
@Valid:方法、构造函数、方法参数、成员属性上。
分组
@Validated:支持分组验证。
@Valid:支持标准的 Bean 验证功能,不支持分组验证。
嵌套验证
@Validated:不支持嵌套验证。
@Valid:支持嵌套验证。
3.常用的参数校验注解以及相关例子
1.1、基本用法 1.@NotNull:校验元素值不能为空,如果为空,则校验失败。
@NotNull(message = "名字不能为空")
private String userName;
2.@NotBlank:校验字符串值不能为null和空字符串,必须包含至少一个非空字符即执行trim(之后不为’‘)。如果元素为null或者’',则验证失败。
@NotBlank(message = "昵称不能为null和空字符串")
private String nickName;
3.@NotEmpty:校验集合或者数组或者字符串是否非空,通常用于集合和数组字段,需要集合和数组元素个数大于0。也可以作用于字符串,此时校验字符串不能为null或空串(可以是一个空格)。
@NotEmpty(message = "postIds不能为空")
private Long[] postIds;
4.@Max:校验数字元素最大值。
@Max(value=100,message = "年龄最大100")
private String age;
5.@Min:校验数字元素最小值。
@Min(value=18,message = "年龄最小100")
private String age;
6.@Past:校验日期或时间元素是否在当前时间之前。即是否是过去时间。作用于Date相关类型的字段。
@Past(message = "")
private Date createTime;
7.@Future:校验日期或时间元素是否在当前时间之前。即是否是过去时间。作用于Date相关类型的字段。
@Future(message = "")
private Date createTime;
8.@Email:校验字符串元素是否为有效的电子邮件地址。
@Email(message = "")
private String email;
9.@Pattern:根据正则表达式校验字符串元素的格式。
@Pattern(regexp = "[a-zA-Z0-9]+")
private String userName;
10.@Size:校验集合元素个数或字符串的长度在指定范围内。
@Size(min = 3, max = 10, message = "长度在3到10之间")
private String username;
11.@Length:校验字符串元素的长度。作用于字符串。
@Length(min = 3, max = 10, message = "长度在3到10之间")
private String username;
以上只是部分注解和他们的功能,需要详细的了解需要查看源码。
具体代码实现
全局异常处理器 捕获参数校验异常
package com.itheima.exception;
import com.itheima.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Objects;
/**
* 全局异常处理器,处理项目中抛出的业务异常
*/
@RestControllerAdvice // 标识当前类是一个全局异常处理器
@Slf4j
public class GlobalExceptionHandler {
/**
* 捕获参数校验异常
*/
@ResponseBody
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handle(MethodArgumentNotValidException e) {
return Result.error(Objects.requireNonNullElse(e.getBindingResult().getFieldError(), new FieldError("target", "field", "参数验证错误")).getDefaultMessage());
}
/**
* 捕获业务异常
*/
@ExceptionHandler
public Result exceptionHandler(BaseException ex){
log.error("通用异常信息:{}", ex.getMessage());
return Result.error(ex.getMessage());
}
/**
* 捕获SQL异常
*/
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error("SQL异常信息:{}", ex.getMessage());
String message = ex.getMessage();
if (message.contains("Duplicate entry")){//如果异常消息中包含 "Duplicate entry" 字样
return Result.error("已存在");
}else {
return Result.error("UNKNOWN_ERROR");
}
}
/**
* 捕获算法异常
*/
@ExceptionHandler
public Result exceptionHandler(ArithmeticException ex){
log.error("计算异常信息:{}", ex.getMessage());
return Result.error(ex.getMessage());
}
}
统一公共返回类
package com.itheima.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Integer code;//响应码,1 代表成功; 0 代表失败
private String msg; //响应信息 描述字符串
private Object data; //返回的数据
//增删改 成功响应
public static Result success(){
return new Result(1,"success",null);
}
//查询 成功响应
public static Result success(Object data){
return new Result(1,"success",data);
}
//失败响应
public static Result error(String msg){
return new Result(0,msg,null);
}
}
控制器
package com.itheima.controller;
import com.itheima.pojo.Result;
import com.itheima.pojo.vo.SysUserVO;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author wuJiaWei
* @version 1.0
*/
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/add")
public Result add(@Validated @RequestBody SysUserVO sysUserVO) {
userService.AddUser(sysUserVO);
return Result.success();
}
}
视图传输数据类
package com.itheima.pojo.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
@Data
public class SysUserVO {
@ApiModelProperty("部门ID")
private Long deptId;
@NotBlank(message = "名字不能为空")
@ApiModelProperty("用户名")
private String userName;
@NotBlank(message = "昵称不能为null和空字符串")
@ApiModelProperty("昵称")
private String nickName;
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("用户性别(0男,1女")
private Integer gender;
@ApiModelProperty("手机号码")
private String phone;
@Email(message = "请填写正确的邮箱地址")
@ApiModelProperty("邮箱")
private String email;
@ApiModelProperty("头像地址")
private String avatarName;
@ApiModelProperty("用户类型(0管理员,1普通用户")
private Integer userType;
@ApiModelProperty("状态:1启用、0禁用")
private Integer status;
@ApiModelProperty("备注")
private String remark;
}
嵌套对象验证、分组验证、自定义验证注解 就不写了。