我们在进行Web开发的时候,会经常需要对传入的参数进行校验,比如字段非空,字段长度限制,邮箱格式验证等等.如果数据比较少的时候还比较容易处理,但当数据比较多的时候会显得比较麻烦,而且处理不当的时候,还会造成代码重复.这时候就需要Spring Boot对参数进行校验了,我们可以使用Validation
对数据进行校验.
- 验证代码繁琐,重复劳动;
- 方法内代码显得冗长;
- 每次都要看哪些参数验证是否完整,需要去翻阅验证逻辑代码.
1️⃣. hibernate validator:提供了一套比较完善、便捷的验证实现方式,spring-boot-starter-web
包里面有hibernate-validator
包,不需要引用hibernate validator
依赖;
2️⃣.SpringBoot的Validation
.
比如我们发起一个POST请求,/user
的请求是期望新增一个用户.
@PostMapping("/users")
public void addUser(@Valid @RequestBody User user) {
log.info("用户添加成功:{}", user);
}
假设我们携带以下JSON数据作为请求参数,但是通常我们会期望username和password不能为空.
{
"username":"",
"password":""
}
因此我们期望能得到一个具体的响应,告诉我们参数校验失败的个数及原因.
{
"code": 400,
"message": "BAD_REQUEST",
"data": "参数校验错误(2): 用户名不能为空;密码不能为空"
}
data中的(2) 表示有两处参数校验失败并在其后表明校验失败的原因.
2. 具体实现过程2.1 创建一个新的模块--boot_validation

2.2 创建一个User类,并添加参数注解
在参数上添加声明式注解定义参数需要的校验类型,例如上文的User对象.
package com.syc.boot.bean;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
/**
* 参数校验
*/
@Data
public class User implements Serializable {
//@NotBlank
//@NotEmpty
//@NotNull
@NotNull(message = "用户id不能为空")
private Integer id;
//@Min(value = 1,message = "最低1个字符")
//@Max(value = 10,message = "最长10个字符")
//@Range(min = 3,max = 6,message = "取值只能是3~6之间的数字")
@Length(min = 3,max = 6,message = "姓名字符范围3-6个字符")
//@Pattern(regexp = "^[a-zA-Z_]\\w{4,19}$", message = "用户名必须以字母下划线开头,可由字母数字下划线组成")
private String username;
//@Pattern(regexp = "身份证的正则表达式", message = "请输入合法的身份证号码")
//private String cardNum;
@Range(min = 0,max = 200,message = "年龄范围0-200")
private Integer age;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8",locale = "zh")
private Date birthday;
//在json中忽略该属性
@JsonIgnore
private String other;
}
2.3 创建一个统一的响应结果类--R
package com.syc.boot.bean;
import lombok.Data;
import java.io.Serializable;
/**
* 自定义的响应结果
*/
@Data
public class R implements Serializable {
private String status;
private Object result;
}
2.4 创建Controller,在接口方法的参数前添加@Valid注解
package com.syc.boot.web;
import com.syc.boot.bean.R;
import com.syc.boot.bean.User;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
*
*/
@RestController
public class UserController {
private static Map users = Collections.synchronizedMap(new HashMap());
//@Valid:验证参数对象中的属性是否符合要求
@RequestMapping(value = "user", method = RequestMethod.POST, produces = "application/json; charset=UTF-8")
public ResponseEntity addUser(@RequestBody @Valid User user) {
R r = new R();
try {
users.put(user.getId(), user);
r.setStatus("ok");
r.setResult(user.getId());
} catch (Exception e) {
r.setStatus("error");
r.setResult(e.getClass().getName() + ":" + e.getMessage());
e.printStackTrace();
}
//ok的这个状态,指的是前后端通信是ok的,不代表本接口的业务功能也ok
return ResponseEntity.ok(r);
}
}
2.5 创建应用程序入口类
package com.syc.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ValidationWebApplication {
public static void main(String[] args) {
SpringApplication.run(ValidationWebApplication.class, args);
}
}
注意:如果没有添加@Valid注解是不会对参数进行校验的.
2.6 参数校验结果
正常请求时结果:
非法请求时结果: