目录
第二步:在实体类上添加相应的注解@NotBlank......
第四步: 给校验的bean后紧跟一个BindResult,就可以获得校验的结果
2、@RestControllerAdvice + @ExceptionHandler的实现
JSR303校验注解概念
作用:
用来校验后端实体类的属性是否合法
应用:
直接给Bean类的 属性加上校验注解即可
应用
第一步:添加依赖
<!--校验数据的JSR303依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>2.7.0</version> </dependency>
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency>
二者选一,都可以使用
第二步:在实体类上添加相应的注解@NotBlank......
url 校验 @URL 自定义校验 @Pattern(regexp = 正则表达式",message = "提示信息") 非空校验 @NotBlank ...... 示例: @NotBlank(message = "品牌名不许为空,且必须提交") private String name;
引入: 这么多注解怎么找?
第三步:@Valid开启校验功能,并且会有默认的响应
public R save(@Valid @RequestBody BrandEntity brand){
brandService.save(brand);
return R.ok();
}
拓展:
1、分组校验功能。比如:添加页面和修改页面的校验功能不一样
应用:
第一步:创建分组校验的接口(接口中什么也不用写,相当于一个标识位)
第二步:在实体类中的属性上的注解@NotBlank(message = "品牌名不许为空,且必须提交"),增加一个groups属性,来约定是哪种检验规则(增加,或修改)
第三步: 在接口前添加分组校验注解,并指定使用哪种校验规则
2、自定义校验功能。
第一步:编写一个自定义的校验注解
第二步:编写一个自定义的校验器
第三步:关联自定义的校验器和 校验注解
第四步: 给校验的bean后紧跟一个BindResult,就可以获得校验的结果
public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){
if (result.hasErrors()){
Map<String,String> map = new HashMap<>();
// 1、 获取校验的错误信息
result.getFieldErrors().forEach((item)->{
// 2、 获得校验的错误信息
String message = item.getDefaultMessage();
// 3、获得错误的属性的名字
String field = item.getField();
map.put(field,message);
});
return R.error(400,"提交的数据不合法 ").put("data",map);
}else {
brandService.save(brand);
}
return R.ok();
}
缺点:需要每个类都要加,代码过于复杂化。
解决办法:统一异常处理
第五步: 统一异常处理
1、统一异常的三种实现方式:
介绍:Spring MVC异常统一处理的三种方式 - Louis军 - 博客园
2、@RestControllerAdvice + @ExceptionHandler的实现
在spring框架下实现一个异常处理的类,用 @RestControllerAdvice + @ExceptionHandler
1、首先定义一个枚举类,用于定义错误码和错误信息
/***
* 错误码和错误信息定义类
* 1. 错误码定义规则为5为数字
* 2. 前两位表示业务场景,最后三位表示错误码。例如:100001。10:通用 001:系统未知异常
* 3. 维护错误码后需要维护错误描述,将他们定义为枚举形式
* 错误码列表:
* 10: 通用
* 001:参数格式校验
* 11: 商品
* 12: 订单
* 13: 购物车
* 14: 物流
*
*
*/
public enum BizCodeEnume {
UNKNOW_EXCEPTION(10000,"系统未知异常"),
VAILD_EXCEPTION(10001,"参数格式校验失败");
private int code;
private String msg;
BizCodeEnume(int code,String msg){
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
2、然后定义一个异常处理类
用 @RestControllerAdvice + @ExceptionHandler进行修饰,即@RestControllerAdvice默认会拦截 controller类上抛出的不能处理的异常
一个全局异常处理类需要处理三类异常: 1.业务类异常 (引入:https://www.jb51.net/article/215324.htm),2.运行时异常 ,3.Error
/**
* 异常处理类:集中处理所有异常
**/
@Slf4j// 日志记录
/*
@ResponseBody
@ControllerAdvice(basePackages = "com.atguigu.gulimail.product.controller")
*/
@RestControllerAdvice
public class GuLiMailException {
/**
* 特定异常(运行时异常)
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)// 表示感知所有异常
public R handleValidException (MethodArgumentNotValidException e /*MethodArgumentNotValidException可以更换异常类型*/){
// 控制台错误日志记录输出
log.error("数据校验出现问题{},异常理性{}",e.getMessage(),e.getClass());
// 封装错误信息集合
Map<String,String> map = new HashMap<>();
// 获取绑定的校验的结果
BindingResult bindingResult = e.getBindingResult();
// 1获得所有的校验错误信息进行遍历
bindingResult.getFieldErrors().forEach((item)->{
// 2、 获得校验的错误信息
String message = item.getDefaultMessage();
// 3、获得错误的属性的名字
String field = item.getField();
map.put(field,message);
});
return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(), BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data",map);
}
/**
* 全局异常处理; 不论出现那种异常,都会执行
上面的只是异常中的一个类,不能包含所有的异常体系,还有一大类是叫Error(系统级异常),所以需要有一个兜底的异常捕获:
*/
@ExceptionHandler(value = Throwable.class)
public R handleException(Throwable throwable){
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.VAILD_EXCEPTION.getMsg());
}
}
3、结果示例