1.JSR303简介
- 适用于服务器端的数据校验
- Java为Bean数据合法性校验所提供的标准框架
- Spring MVC支持JSR 303标准的校验框架
- JSR 303通过在Bean属性上标注校验注解指定校验规则
- Spring本身没有提供JSR 303的实现,他是由Hibernate Validator 实现与spring整合的
2. JSR303相关常用的注解
@Null(message) | 被注释的元素必须为null |
@NotNull(message) | 被注释的元素必须不为null |
@AssertTrue(message) | 被注释的元素必须为 true |
@AssertFalse(message) | 被注释的元素必须为 false |
@Min(value,message) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value,message) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(value,message) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@DecimalMax(value,message) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Size(max, min,message) | 被注释的元素的大小必须在指定的范围内 |
@Digits(integer,fraction,message) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 |
@Past(message) | 被注释的元素必须是一个过去的日期 |
@Future (message) | 被注释的元素必须是一个将来的日期 |
@Pattern(regexp="正则表达式",message) | 使用正则表达式进行匹配 |
被注释的元素必须是电子邮件地址 | |
@Length(max=5,min=1,message="长度在1~5") | 检查所属的字段的长度是否在min和max之间,只能用于字符串 |
@Range | 被注释的元素必须在合适的范围内 |
@CreditCardNumber | 对信用卡号进行一个大致的验证 |
@NotBlank | 不能为空,检查时会将空格忽略 |
@NotEmpty | 不能为空,这里的空是指空字符串 |
属性:message="验证提示信息" |
3.开发步骤
01.引入相关依赖(没写版本号的时候会默认使用springboot的版本)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
02.使用注解:给需要验证的属性增加相应的校验注解
@NotNull(message = "用户名不能为空")
private String userName; //用户名称
@Pattern(regexp = "^[a-zA-Z0-9]{6,8}$",message = "密码必须是6-8位数字和字母的组合")
private String userPassword; //用户密码
@Past(message = "生日只能是过去的日期")
private Date birthday; //出生日期
@Min(value = 1, message = "年龄最小值为1")
@Max(value = 120, message = "年龄最大值120")
private Integer age;
03.在controller层中的业务方法参数列表前使用@Valid注解,并且在参数值添加BindingResult参数
如果没有BindingResult参数,spring会在校验不通过时出现异常
@PostMapping("/login2")
public ReturnResult login2(@Valid @RequestBody User user, BindingResult result){
。。。
}
04.BindingResult(校验结果对象)常用方法:
hasFieldErrors("属性名") | 判断对应的属性是否符合验证,返回布尔值 有:true |
hasErrors() | 判断使用验证的所有的属性验证是否有错,返回布尔值 有:true |
getFieldError("属性名") | 获取有错误的属性对象,返回FieldError类型 |
fieldError.getDefaultMessage() | 获取错误属性对象的message提示信息,返回String类型 |
fieldError.getField() | 获取错误属性对象的属性名;返回String类型 |
getFieldErrors() | 获取所有不符合验证的属性对象,返回List<FieldError>类型 |
代码演示 :
@PostMapping("/login2")
public ReturnResult login2(@Valid @RequestBody User user, BindingResult result){
ReturnResult returnResult=null;
Map<String,Object> map = new HashMap<>();
//判断birthday是否有错
System.out.println(result.hasFieldErrors("birthday"));
//判断userPassword是否有错
System.out.println(result.hasFieldErrors("userPassword"));
//判断是否有错
if(result.hasErrors()){
//获取所有的错误
result.getFieldErrors().forEach((item)->{
//获取错误信息
String message = item.getDefaultMessage();
//获取错误的属性名
String field = item.getField();
map.put(field,message);
});
}
return map;
}
4.封装统一的返回数据格式:ReturnResult<T>
01.创建ReturnResult类:和前端交互的统一格式类
package com.ck.vo;
import java.io.Serializable;
/***
* created by lxl
* 只要这个类会被用来做数据传递(前端<->后端)
* 和前端接口交互的统一格式
*/
public class ReturnResult implements Serializable{
//用户查询 正确:{code:200,message:操作成功,data:{用户信息}}
//用户查询 错误:{code:500,message:后端服务器出错,data:null}
//状态码 自定义
private Integer code;
//提示信息
private String message;
//返回数据
private Object data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
02.创建ReturnResultUtils 统一返回工具类
package com.ck.vo;
import org.springframework.stereotype.Component;
/***
* created by lxl
*
* 统一返回工具类
*/
@Component
public class ReturnResultUtils{
/***
* 成功 不带数据
* @return ReturnResult
*/
public static ReturnResult returnSuccess(Integer code, String message){
ReturnResult returnResult=new ReturnResult();
returnResult.setCode(code);
returnResult.setMessage(message);
return returnResult;
}
/***
* 成功 带数据
* @return ReturnResult
*/
public static ReturnResult returnSuccess(Integer code, String message, Object data){
ReturnResult returnResult=new ReturnResult();
returnResult.setCode(code);
returnResult.setMessage(message);
returnResult.setData(data);
return returnResult;
}
/***
* 失败 不带数据
* @return ReturnResult
*/
public static ReturnResult returnFail(Integer code, String message){
ReturnResult returnResult=new ReturnResult();
returnResult.setCode(code);
returnResult.setMessage(message);
return returnResult;
}
/***
* 失败 带数据
* @return ReturnResult
*/
public static ReturnResult returnFail(Integer code, String message, Object data){
ReturnResult returnResult=new ReturnResult();
returnResult.setCode(code);
returnResult.setMessage(message);
returnResult.setData(data);
return returnResult;
}
}
03.修改controller返回值
@PostMapping("/login2")
public ReturnResult login2(@Valid @RequestBody User user, BindingResult result){
ReturnResult returnResult=null;
Map<String,Object> map = new HashMap<>();
//判断birthday是否有错
System.out.println(result.hasFieldErrors("birthday"));
//判断userPassword是否有错
System.out.println(result.hasFieldErrors("userPassword"));
//判断是否有错
if(result.hasErrors()){
//获取所有的错误
result.getFieldErrors().forEach((item)->{
//获取错误信息
String message = item.getDefaultMessage();
//获取错误的属性名
String field = item.getField();
map.put(field,message);
});
//使用带参数的方法,传入获取到的校验错误信息map,响应给前端
returnResult= ReturnResultUtils.returnFail(500,"操作失败",map);
}else{
returnResult = ReturnResultUtils.returnSuccess(200,"操作成功");
}
//返回returnResult统一格式类
return returnResult;
}
将ReturnResult类和ReturnResultUtils使用泛型化
ReturnResult类:将响应数据类型使用泛型约束,在controller中可以规定每一个ReturnResult返回的数据date类型
package com.ck.vo;
import java.io.Serializable;
/***
* created by lxl
* 只要这个类会被用来做数据传递(前端<->后端)
* 和前端接口交互的统一格式
*/
public class ReturnResult<T> implements Serializable{
//用户查询 正确:{code:200,message:操作成功,data:{用户信息}}
//用户查询 错误:{code:500,message:后端服务器出错,data:null}
//状态码 自定义
private Integer code;
//提示信息
private String message;
//返回数据
private T data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
ReturnResultUtils工具类
package com.ck.vo;
import org.springframework.stereotype.Component;
/***
* created by lxl
*
* 统一返回工具类
*/
@Component
public class ReturnResultUtils<T>{
/***
* 成功 不带数据
* @return ReturnResult
*/
public ReturnResult<T> returnSuccess(Integer code, String message){
ReturnResult<T> returnResult=new ReturnResult<>();
returnResult.setCode(code);
returnResult.setMessage(message);
return returnResult;
}
/***
* 成功 带数据
* @return ReturnResult
*/
public ReturnResult<T> returnSuccess(Integer code, String message, T data){
ReturnResult<T> returnResult=new ReturnResult<>();
returnResult.setCode(code);
returnResult.setMessage(message);
returnResult.setData(data);
return returnResult;
}
/***
* 失败 不带数据
* @return ReturnResult
*/
public ReturnResult<T> returnFail(Integer code, String message){
ReturnResult<T> returnResult=new ReturnResult<>();
returnResult.setCode(code);
returnResult.setMessage(message);
return returnResult;
}
/***
* 失败 带数据
* @return ReturnResult
*/
public ReturnResult<T> returnFail(Integer code, String message, T data){
ReturnResult<T> returnResult=new ReturnResult<>();
returnResult.setCode(code);
returnResult.setMessage(message);
returnResult.setData(data);
return returnResult;
}
}
———————————跳转全局处理异常&全局数据保存————————————