springboot 全局异常捕获,异常流处理业务逻辑
前言
上一篇文章说到,参数校验,往往需要和全局的异常拦截器来配套使用,使得返回的数据结构永远是保持一致的。参数异常springboot默认的返回结构:
{
"timestamp": "2019-04-25T13:09:02.196+0000",
"status": 400,
"error": "Bad Request",
"errors": [
{
"codes": [
"Pattern.param.birthday",
"Pattern.birthday",
"Pattern.java.lang.String",
"Pattern"
],
"arguments": [
{
"codes": [
"param.birthday",
"birthday"
],
"arguments": null,
"defaultMessage": "birthday",
"code": "birthday"
},
[],
{
"defaultMessage": "\d{4}-\d{2}-\d{2}",
"codes": [
"\d{4}-\d{2}-\d{2}"
],
"arguments": null
}
],
"defaultMessage": "需要匹配正则表达式"\d{4}-\d{2}-\d{2}"",
"objectName": "param",
"field": "birthday",
"rejectedValue": "apple",
"bindingFailure": false,
"code": "Pattern"
}
],
"message": "Validation failed for object='param'. Error count: 1",
"path": "/validate/notblank"
}
不管是正常的情况,还是异常的情况,对于前端(或者app)来说,最好返回值的结构都是一致的,这样才方便解释。
定义一个BaseResult类,定义返回值的数据结构
public class BaseResult {
private int code;
private String message;
private Object data;
// 省略getter setter方法,全参构造方法
}
不管什么接口,都采用这样的数据结构返回给前端。比如约定code为0时是成功,其他错误定义出具体的错误码,message放错误信息,data对象放相应的数据。
定义全局异常处理器GlobalExceptionHandlerAdvice
@RestControllerAdvice
public class GlobalExceptionHandlerAdvice { }
使用RestControllerAdvice可以标识一个类为异常捕获类。
捕获异常
通过参数异常的测试,可以知道参数有异常时会抛出org.springframework.web.bind.MethodArgumentNotValidException。我们现在手动捕获 这个异常,并且返回一个BaseResult格式的响应。
@ExceptionHandler(MethodArgumentNotValidException.class)
public BaseResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
BindingResult result = e.getBindingResult();
FieldError fieldError = result.getFieldError();
String defaultMessage = fieldError.getDefaultMessage();
return new BaseResult(11000, defaultMessage, null);
}
使用ExceptionHandler可以捕获异常类型。这里捕获了参数错误会抛出的异常,然后返回了自定义的结果。这里错误码为随便填写,真实开发,建议定义一个错误码枚举类。
效果如下:
返回的结果就比较友好了,前端处理起来也方便。
异常流处理业务逻辑
使用异常来处理业务逻辑,会使代码写起来更加流畅。比如说,一个删除用户数据的方法,返回值为void(无返回值),但是当传入的用户id不存在的时候,就应该返回一个用户不存在的结果,这对于void返回值的方法来说,显得无能为力。但是,使用异常流来处理该业务逻辑,会变得非常简单。我们直接抛出一个自定义异常,然后在异常捕获器上捕获该异常,再把结果返回给前端即可。
定义一个WebException
public class WebException extends RuntimeException {
private int code;
private String errorMsg;
public WebException(int code, String errorMsg) {
super(errorMsg);
this.code = code;
this.errorMsg = errorMsg;
}
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
// 省略getter setter方法
}
这里定义了一个运行时异常,重写了fillInStackTrace方法,重写该方法是不保留异常信息栈。因为我们使用该异常来处理业务逻辑,都是我们手动抛出的,所以也不需要保存异常信息栈了,这会提升性能。
在异常捕获器添加WebException异常捕获
@ExceptionHandler(WebException.class)
public BaseResult handleWebException(WebException e) {
return new BaseResult(e.getCode(), e.getErrorMsg(), null);
}
模拟一段业务逻辑,抛出WebException
在之前的UserController类,修改之前写的deleteUser方法,如下:
@DeleteMapping(value = "/{userId}")
public Object deleteUser(@PathVariable(value = "userId") Integer userId) {
if (userId == 0) {
throw new WebException(-1, "用户不存在");
}
return new BaseResult(1, "成功", null);
}
这里定义一个delete请求的接口,接收一个userId参数,如果userId等于0,则返回该用户不存在。测试结果如下:
当userId为0时,提示用户不存在
当userId为1时,提示成功.
总结
这里实现了全局异常捕获,并且介绍了异常流处理业务逻辑。这里只是一个小demo,还有很多待改进的地方。比如说,我没有定义一个错误码枚举类。在定义了错误码枚举类的前提下,修改构造BaseResult的模式,可以采用静态工厂模式来构造等。这里就不展开讨论了
springboot 全局异常捕获,异常流处理业务逻辑的更多相关文章
- 【快学springboot】5.全局异常捕获,异常流处理业务逻辑
前言 上一篇文章说到,参数校验,往往需要和全局的异常拦截器来配套使用,使得返回的数据结构永远是保持一致的.参数异常springboot默认的返回结构: { "timestamp": ...
- JavaScript异常捕获
理论准备 ★ 异常捕获 △ 异常:当JavaScript引擎执行JavaScript代码时,发生了错误,导致程序停止运行: △ 异常抛出:当异常产生,并且这个异常生成一个错误信息: △ 异常捕获: ...
- [javaSE] 异常捕获
异常:程序在运行时出现的不正常现象 Throwable |——Error |——Exception 严重级别:Error类和Exception类 异常的处理:try{}catch{}finally{} ...
- python异常处理-异常捕获-抛出异常-断言-自定义异常-UDP通信-socketserver模块应用-3
异常捕获 异常:程序在运行过程中出现了不可预知的错误,并且该错误没有对应的处理机制,那么就会以异常的形式表现出来 影响:整个程序无法再正常运行 异常的结构 异常的类型 NameError 异常的信息 ...
- springboot(二 如何访问静态资源和使用模板引擎,以及 全局异常捕获)
在我们开发Web应用的时候,需要引用大量的js.css.图片等静态资源. 默认配置 Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则: /static / ...
- SpringBoot图文教程15—项目异常怎么办?「跳转404错误页面」「全局异常捕获」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1-Spr ...
- 4、springboot之全局异常捕获
1.新建一个springboot项目 添加一个全局异常的类 import org.springframework.web.bind.annotation.ControllerAdvice; impor ...
- springboot上传文件过大,全局异常捕获,客户端没有返回值
最近在项目里进行全局异常处理时,上传文件超过配置大小,异常被捕获,但是接口直接报500错误,且没有任何返回值. 从后台报错日志来看,异常已经被全局异常处理捕获到了,并且也已经完成响应,为什么前端看不到 ...
- springboot编程之全局异常捕获
springboot编程之全局异常捕获 1.创建GlobalExceptionHandler.java,在类上注解@ControllerAdvice, 在方法上注解@ExceptionHandler( ...
随机推荐
- 关于python切片操作笔记
一. Python可切片对象的索引方式 包括:正索引和负索引两部分,如下图所示,以a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]为例: python索引方式.jpg 二. P ...
- 【AICC】2019训练营笔记
1.AI 人工的方法在机器上实现智能:机器学习.计算机视觉.规划决策.自然语言处理.认知推理.高效搜索 2.三大学派 符号主义 连接主义:CNN 行为主义 3.两条路线 结构模仿 功能模仿 4.AI芯 ...
- 19-C#笔记-多态性
# 静态多态性 --- ## 1 函数重载 和C++一样. --- ## 2 运算符重载 public static operator public static Box operator+ (Box ...
- 07-cmake语法-MATCHES
如果给定的字串或变量值域给定的正则表达式匹配的话,表达式返回真. IF (CMAKE_SYSTEM_NAME MATCHES "Linux") MESSAGE(STATUS &qu ...
- iptables man手册翻译
概要 iptables [-t table] -[AD] chain rule-specification [options]iptables [-t table] -I chain [rulenum ...
- [Noip2018]填数游戏
传送门 Description 耳熟能详,就不多说了 Solution 对于一个不会推式子的蒟蒻,如何在考场优雅地通过此题 手玩样例,发现对于 \(n=1\) , \(ans=2^m\) .对于 \( ...
- 我对网络IO的理解
Unix/Linux系统下IO主要分为磁盘IO,网络IO,我今天主要说一下对网络IO的理解,网络IO主要是socket套接字的读(read).写(write),socket在Linux系统被抽象为流( ...
- curl用法详解
前言 昨天现场的浏览器崩溃了,楼主苦逼,就临时用了curl测试了下图片请求接口.今天总结下. 一.what? curl is a tool to transfer data from or to a ...
- Computer-Hunters——项目需求分析
Computer-Hunters--项目需求分析 前言 本次作业属于2019秋福大软件工程实践Z班 本次作业要求 团队名称: Computer-Hunters 本次作业目标:撰写一份针对团队项目的需求 ...
- python 之类的继承
#类的继承 class As1(): def As2(self): print("he11...") class As2(As1): def As2(self): print(&q ...