In the actual project, not only the front-end needs to check the required items, but also the back-end needs to check the relevant parameters to prevent illegal parameters from affecting the business. Next, let’s learn how to check the parameters in the Springboot project. . The version of Springboot in this article is 2.6.8
Introduce dependencies
If Springboot
the version is less than 2.3.x
, the dependency spring-boot-starter-web
will be imported automatically hibernate-validator
. If the Springboot version is greater than that 2.3.x
, you need to manually introduce dependencies: Reminder: Version 7.xx may not work
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.2.0.Final</version>
</dependency>
复制代码
Or directly introduce the scene starter of springboot
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.7.0</version>
</dependency>
复制代码
The difference between @Validated and @Valid
** Secondary encapsulation @Validated
of@Valid
** has been carried out, but the two have the following differences:
- **
@Validated
Provide the grouping function, and different verification mechanisms can be adopted according to different groups during parameter verification.@Valid
**No grouping function - **
@Validated
Used on types, methods, and method parameters. But it cannot be used for member attributes (field),@Valid
** can be used for methods, constructors, method parameters and member attributes (field) - A pojo class to be verified, which also includes the object properties to be verified, needs to be annotated ** on the object to be verified
@Valid
, in order to verify the member properties in the object to be verified,@Validated
** cannot be used here
Unified exception handling
If the verification fails, it will report MethodArgumentNotValidException or ConstraintViolationException
@RestControllerAdvice
public class ParamException {
@ExceptionHandler({MethodArgumentNotValidException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResultReturn handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
BindingResult bindingResult = ex.getBindingResult();
StringBuilder sb = new StringBuilder("校验失败:");
for (FieldError fieldError : bindingResult.getFieldErrors()) {
sb.append(fieldError.getField()).append(":").append(fieldError.getDefaultMessage()).append(", ");
}
String msg = sb.toString();
return ResultReturnUtil.fail(ErrorCodeEnum.PARAM_ERROR.getCode(),msg);
}
@ExceptionHandler({ConstraintViolationException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResultReturn handleConstraintViolationException(ConstraintViolationException ex) {
return ResultReturnUtil.fail(ErrorCodeEnum.PARAM_ERROR.getCode(),ex.getMessage());
}
}
复制代码
We can define the error information to be returned in the enumeration
@Getter
@ToString
public enum ErrorCodeEnum {
PARAM_ERROR(10001,"参数错误");
private Integer code;
private String msg;
ErrorCodeEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
复制代码
Another unified return format
@Data
public class ResultReturn implements Serializable {
private static final long serialVersionUID = 5805792987639183304L;
private Integer code;
private String msg;
private Object data;
public ResultReturn(){
super();
}
public ResultReturn(Integer code, String msg){
this.code = code;
this.msg = msg;
}
public ResultReturn(Integer code, String msg, Object data){
this.code = code;
this.msg = msg;
this.data = data;
}
}
复制代码
public class ResultReturnUtil {
/**
* 成功 返回默认码值
* @param msg
* @return
*/
public static ResultReturn success(String msg){
return new ResultReturn(0,msg);
}
/**
* 成功 返回自定义码值
* @param code
* @param msg
* @return
*/
public static ResultReturn success(Integer code, String msg){
return new ResultReturn(code,msg);
}
public static ResultReturn success(String msg, Object data){
return new ResultReturn(0,msg,data);
}
public static ResultReturn fail(String msg){
return new ResultReturn(-1,msg);
}
public static ResultReturn fail(Integer code, String msg){
return new ResultReturn(code,msg);
}
}
复制代码
RequestBody parameter verification
当我们使用POST、PUT请求时会使用 @RequestBody+实体类 来接收参数。此时只需要给实体类加上**@Validated
**注解就能实现自动参数校验。
@RestController
public class TestController {
@PostMapping("/addUser")
public Boolean addUser(@RequestBody @Validated User user){
//忽略service处理相关业务
return true;
}
}
复制代码
那么具体到每个参数的校验则需要在实体类中处理。
@Data
public class User {
private Long id;
@NotBlank(message = "用户账号不能为空")
@Length(min = 4, max = 10,message = "账号长度为4-10位")
private String userName;
@NotBlank(message = "密码不能为空")
@Length(min = 6,max = 12,message = "密码长度为6-12位")
private String password;
@NotNull(message = "邮箱不能为空")
@Email(message = "邮箱格式错误")
private String email;
/**
* 性别 1为男生 2为女生
*/
@Min(value = 1,message = "最小值为1")
@Max(value = 2,message = "最大值为2")
private Integer sex;
}
复制代码
先请求一次试试
requestParam/PathVariable参数校验
这种方式下参数都较少,必须在Controller
类上标注**@Validated
**注解,并在入参上声明约束注解
接下来请求试一下
特殊情况
也是上文提到的,pojo参数中有对象属性,那么要对这个对象中的属性校验该怎么做?
比如我这里有个学生类
@Data
public class Student {
@NotBlank(message = "用户名不能为空")
private String name;
@Min(value = 10, message = "年龄不能小于10岁")
private Integer age;
@Email(message = "邮箱格式错误")
private String email;
@NotBlank(message = "班级名不能为空")
private String className;
@NotEmpty(message = "任课老师不能为空")
@Size(min = 1, message = "至少有一个老师")
private List<Teacher> teachers;
}
复制代码
@Data
public class Teacher {
@NotBlank(message = "老师姓名不能为空")
private String teacherName;
@Min(value = 1, message = "学科类型从1开始计算")
private Integer type;
}
复制代码
测试一下
很明显这个type的值并不符合要求, 需要在学生类的教师属性上加上**@Valid**注解
参数校验注解大全
注解
作用类型
解释
null是否
能通过验证
@AssertFalse
Boolean、boolean
该字段值为false时,验证才能通过
YES
@AssertTrue
Boolean、boolean
该字段值为true时,验证才能通过
YES
@DecimalMax
数字类型(原子和包装)
验证小数的最大值
@DecimalMax(value = "12.35")
private double money;
复制代码
YES
@DecimalMin
数字类型(原子和包装)
验证小数的最小值
YES
@Digits
数字类型(原子和包装)
验证数字的整数位和小数位的位数是否超过指定的长度
@Digits(integer = 2, fraction = 2)
private double money;
复制代码
YES
String
该字段为Email格式,才能通过
YES
@Future
时期、时间
验证日期是否在当前时间之后,否则无法通过校验
@Future
private Date date;
复制代码
YES
@FutureOrPresent
时期、时间
时间在当前时间之后 或者等于此时
YES
@Max
数字类型(原子和包装)
//该字段的最大值为18,否则无法通过验证
@Max(value = 18)
private Integer age;
复制代码
YES
@Min
数字类型(原子和包装)
同上,不能低于某个值否则无法通过验证
YES
@Negative
数字<0
YES
@NegativeOrZero
数字=<0
YES
@NotBlank
String 该注解用来判断字符串或者字符,只用在String上面
字符串不能为null,字符串trim()后也不能等于“”
NO
@NotEmpty
String、集合、数组、Map、链表List
不能为null,不能是空字符,集合、数组、map等size()不能为0;字符串trim()后可以等于“”
NO
@NotNull
任何类型
The value of the field using this annotation cannot be null, otherwise the verification will fail
NO
@Null
The modified field must be null during validation, otherwise the validation will fail
YES
@Past
time, date
Verify whether the date is before the current time, otherwise it cannot pass the verification, it must be a past time or date
YES
@PastOrPresent
time, date
Verify if date is before or equal to current time
YES
@Pattern
Used to verify whether the field matches the given regular
@Pattern(regexp = "正则")
private String name;
复制代码
YES
@Positive
Number > 0
YES
@PositiveOrZero
number>=0
YES
@Size
String String, collection Set, array Array, Map, List
修饰的字段长度不能超过5或者低于1
@Size(min = 1, max = 5)
private String name;
复制代码
The size() value of collections, arrays, maps, etc. must be within the specified range
//只能一个
@Size(min = 1, max = 1)
private List<String> names;
复制代码
YES