2020-08-05
在it技术日益发达的今天,越来越多的人涌入it行业,但在这些人中,大多数的人都会选择做java开发,原因不言而喻,java不仅生态越来越好,而且岗位需求也很大,而一谈到java,那就离不开spring,spring可以说是做java开发所离不开的框架,spring的强大之处,也能在工作中一一体会到,而我们今天所谈论的springboot,就是在spring的基础上进一步封装的更加强大的框架。
在以往的日常开发中,最烦劳的莫过于程序跑着跑着出异常了,然后一步一步去定位找到问题,解决问题,没有一个统一的异常解决方案,这让人很是苦恼,而在有了springboot以后,由于集成了springMVC的功能,加上springboot本身的自动配置,这就让我们的异常处理变的很容易了,以最小的配置去实现功能强大的异常处理,那么,就让我们继续往下看吧。
##环境准备 ** jdk1.8 maven springboot**
首先准备maven的依赖,如下 ##导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
##异常注解介绍
@ControllerAdvice:标注在类上,表明该类是一个全局异常处理类
@RestControllerAdvice:功能同上,只不过多了一个功能,在接收异常时,以json的格式返回错误信息,相似性参考@Controller和@RestControllerAdvice
@ExceptionHandler:该注解标注在方法上,表明该方法用来接受哪个类型的异常
Class<? extends Throwable>[] value() default {};
接受的异常类型数组。写Throwable.class,就是接受接受所有类型的异常
好了,介绍了基本异常处理注解,接下来就是代码的编写和测试了 ##代码编写 先来测试最简单也是最基本的异常处理 ###controller层编写
@GetMapping("/hello")
public String hello(){
System.out.println("hello world");
//假如刚好执行到这一步出现了异常
//模拟一个出现异常的业务场景
int i = 1 / 0;
return "success";
}
###全局异常处理编写 让我们来看看springboot是怎么处理异常的
@Slf4j //lombok的日志记录
//注意:这里如果用的是@ControllerAdvice的话,下面的方法要加@ResponseBody
@RestControllerAdvice(basePackages = //包名,指定controller包所在的位置)
public class GlobalExceptionControllerAdvice {
@ExceptionHandler(value = {Throwable.class})
public CommResult handleException(Throwable throwable //要接收的异常的类,Throwable表示接收所有的异常类型){
log.error("接收到的异常类型为:{}",throwable.getClass());
log.error("接收到的错误信息为:{}:",throwable.getMessage());
//返回json格式的错误信息
return CommResult.error(500,"服务器内部错误");
}
}
好了,一个简单的全局异常处理,就写完了,现在就让我们测试一下吧
现在,一个最基本的全局异常处理就完成了,测试也有了效果,现在开始进入下一个主题 ##JSR303 谈起JSR,不免想起java规范,没错,JSR就是java规范,它里面定义了java的很多规范,既然是规范,那么就要有具体的落地实现,现在就来谈谈JSR303吧 在官网有这么一句描述,对javaBean的验证,简单来说呢,它就是来对javaBean做数据校验的, 它的具体落地实现就是hebernate validation,这是hebernate对它的一种实现,spring对它也进行了实现,两种都可以使用 ###进入正题 让我们来看看一些校验注解
@Null //标注的属性为null
@NotNull //标注的属性值不为null
@NotBlank //标注的属性不能为空
@NotEmpty //同上
@Paattern //传入的参数要和规定的正则想匹配
@Min //指定传入参数的最小值
@Max //指定传入参数的最大值
@URL //传入的参数必须是一个URL地址
@Email //传入的参数必须是一个Email
@Size //指定传入参数的大小
@Future //传入的参数必须是一个未来的时间
除开这些,还有很多的校验注解等等...
这些注解不仅可以标注在JavaBean上,还可以标注在方法、构造器、注解类型等...
好了,介绍完上面一些常用的注解,现在就来使用看看吧,代码如下 ###javaBean
首先定义一个JavaBean,其内容如下
@NotNull(message = "传入的id不能为null")
private Long id;
@NotBlank(message = "姓名不能为空")
private String name;
@NotEmpty(message = "logo不能为空")
@URL(message = "logo必须是一个URL地址")
private String logo;
@NotBlank
private String descript;
上面定义了一个简单的JavaBean,并使用了一些常用的注解,其它和注解也可以参考上面 ###controller
@PostMapping
public CommResult save(@Valid //只需要在提交的参数前加一个注解就行 @RequestBody User user){
//模拟执行保存方法
userService.save(user);
return CommResult.ok();
}
使用数据校验就是这么简单,现在前端传过来的数据都会先校验一遍,所有字段都合法了才会进行下一步操作。 那么,问题来了,在JavaBean上面,除了定义校验注解,还在上面自定义了一些信息,在校验不通过时,如何才能知道,如何才能处理,如何才能拿到自定义的消息呢?接着往下看
BindingResult
@PostMapping
public CommResult save(@Valid //只需要在提交的参数前加一个注解就行 @RequestBody User user,BindingResult bindingResult){
log.error("是否有数据校验错误:{}",bindingResult.hasErrors());
//模拟执行保存方法
userService.save(user);
return CommResult.ok();
}
其实,拿到错误消息,也很简单,只需要在传入的参数位置加一个BindingResult就可以了,通过BindingResult就可以拿到数据校验的错误信息。
但是controller只是来用来处理请求,不做过多的业务处理,所以,BindingResult就不可以放在那里了,这时,就要用到我们的上面所说的全局异常处理了。
##整合环境搭建 javaBean
public class User{
@NotNull(message = "传入的id不能为null")
private Long id;
@NotBlank(message = "姓名不能为空")
private String name;
@NotEmpty(message = "logo不能为空")
@URL(message = "logo必须是一个URL地址")
private String logo;
@NotBlank
private String descript;
}
因为懒,我就直接用上面的了
UserController
@PostMapping
public CommResult save(@Valid @RequestBody User user){
//模拟执行保存方法
userService.save(user);
return CommResult.ok();
}
GlobalExceptionAdvice
@Slf4j
@RestContrllerAdvice(basePackage = {com.lq.controller})
public class GlobalExceptionAdvice{
//这一个方法专门来接收数据校验出现的异常
@ExceptionHandler(value = BindException.class)
public CommonResult exceptionHandl(BindException e){
log.error("出现异常:{},错误类型为:{}",e.getMessage(), e.getClass());
//获取BindingResult
BindingResult bindingResult = e.getBindingResult();
//获取所有出现校验错误的字段
List<FieldError> fieldErrors = bindingResult.getFieldErrors()
Map<String,Object> map = new HashMap<>();
fieldErrors.forEach(fieldError -> {
//把校验错误的字段名作为key,校验的错误信息作为value,一起放入map
map.put(fieldError.getField(), fieldError.getDefaultMessage());
};
return CommonResult.error().put("fieldErrors",map);
}
}
以上,就是JSR303和全局异常处理结合使用起来的效果,一些其它的细节我就不说了,比如,可以用BindingResult获取其它的信息,有兴趣的可以试试,测试我也懒的测试了,拜拜┏(^0^)┛
tips:Your personal homepage URL will be publicly linked, but your email address will not be publicly displayed; your IP address will be saved, but only your current city name will be publicly displayed.
comment