SpringBoot 处理异常的几种常见姿势
SpringBoot 处理异常的几种常见姿势
1. 使用 @ControllerAdvice 和 @ExceptionHandler 处理全局异常
这是目前很常用的一种方式,非常推荐。测试代码中用到了 Junit 5,如果你新建项目验证下面的代码的话,记得添加上相关依赖。
1. 新建异常信息实体类
非必要的类,主要用于包装异常信息。
src/main/java/com/twuc/webApp/exception/ErrorResponse.javapublic class ErrorResponse private String message;
private String errorTypeName;public ErrorResponse(Exception e) {this(e.getClass().getName(), e.getMessage());}public ErrorResponse(String errorTypeName, String message) {this.errorTypeName = errorTypeName;this.message = message;}省略getter/setter方法}
2. 自定义异常类型
src/main/java/com/twuc/webApp/exception/ResourceNotFoundException.java
一般我们处理的都是 RuntimeException ,所以如果你需要自定义异常类型的话直接集成这个类就可以了。
/*自定义异常类型*/public class ResourceNotFoundException extends RuntimeException {private String message;public ResourceNotFoundException() {super();}public ResourceNotFoundException(String message) {super(message);this.message = message;}@Overridepublic String getMessage() {return message;}public void setMessage(String message) {this.message = message;}}
3. 新建异常处理类
我们只需要在类上加上@ControllerAdvice注解这个类就成为了全局异常处理类,当然你也可以通过 assignableTypes指定特定的 Controller 类,让异常处理类只处理特定类抛出的异常。
src/main/java/com/twuc/webApp/exception/GlobalExceptionHandler.java
@ControllerAdvice(assignableTypes = {ExceptionController.class})@ResponseBodypublic class GlobalExceptionHandler {ErrorResponse illegalArgumentResponse = new ErrorResponse(new IllegalArgumentException("参数错误!"));ErrorResponse resourseNotFoundResponse = new ErrorResponse(new ResourceNotFoundException("Sorry, the resourse not found!"));@ExceptionHandler(value = Exception.class)// 拦截所有异常, 这里只是为了演示,一般情况下一个方法特定处理一种异常public ResponseEntity<ErrorResponse> exceptionHandler(Exception e) {if (e instanceof IllegalArgumentException) {return ResponseEntity.status(400).body(illegalArgumentResponse);} else if (e instanceof ResourceNotFoundException) {return ResponseEntity.status(404).body(resourseNotFoundResponse);}return null;}}
4. controller模拟抛出异常
src/main/java/com/twuc/webApp/web/ExceptionController.java
@RestController@RequestMapping("/api")public class ExceptionController {@GetMapping("/illegalArgumentException")public void throwException() {throw new IllegalArgumentException();}@GetMapping("/resourceNotFoundException")public void throwException2() {throw new ResourceNotFoundException();}}
使用 Get 请求 localhost:8080/api/resourceNotFoundException,服务端返回的 JSON 数据如下:
{"message": "Sorry, the resourse not found!","errorTypeName": "com.twuc.webApp.exception.ResourceNotFoundException"}
5. 编写测试类
MockMvc 由org.springframework.boot.test包提供,实现了对Http请求的模拟,一般用于我们测试 controller 层。
@AutoConfigureMockMvc@SpringBootTestpublic class ExceptionTest {@AutowiredMockMvc mockMvc;@Testvoid should_return_400_if_param_not_valid() throws Exception {mockMvc.perform(get("/api/illegalArgumentException")).andExpect(status().is(400)).andExpect(jsonPath("$.message").value("参数错误!"));}@Testvoid should_return_404_if_resourse_not_found() throws Exception {mockMvc.perform(get("/api/resourceNotFoundException")).andExpect(status().is(404)).andExpect(jsonPath("$.message").value("Sorry, the resourse not found!"));}}
2. @ExceptionHandler 处理 Controller 级别的异常
我们刚刚也说了使用@ControllerAdvice注解 可以通过 assignableTypes指定特定的类,让异常处理类只处理特定类抛出的异常。所以这种处理异常的方式,实际上现在使用的比较少了。
我们把下面这段代码移到 src/main/java/com/twuc/webApp/exception/GlobalExceptionHandler.java 中就可以了。
@ExceptionHandler(value = Exception.class)// 拦截所有异常public ResponseEntity<ErrorResponse> exceptionHandler(Exception e) {if (e instanceof IllegalArgumentException) {return ResponseEntity.status(400).body(illegalArgumentResponse);} else if (e instanceof ResourceNotFoundException) {return ResponseEntity.status(404).body(resourseNotFoundResponse);}return null;}
3. ResponseStatusException
研究 ResponseStatusException 我们先来看看,通过 ResponseStatus注解简单处理异常的方法(将异常映射为状态码)。
src/main/java/com/twuc/webApp/exception/ResourceNotFoundException.java
@ResponseStatus(code = HttpStatus.NOT_FOUND)public class ResourseNotFoundException2 extends RuntimeException {public ResourseNotFoundException2() {}public ResourseNotFoundException2(String message) {super(message);}}
src/main/java/com/twuc/webApp/web/ResponseStatusExceptionController.java
@RestController@RequestMapping("/api")public class ResponseStatusExceptionController {@GetMapping("/resourceNotFoundException2")public void throwException3() {throw new ResourseNotFoundException2("Sorry, the resourse not found!");}}
使用 Get 请求 localhost:8080/api/resourceNotFoundException2[2] ,服务端返回的 JSON 数据如下:
{"timestamp": "2019-08-21T07:11:43.744+0000","status": 404,"error": "Not Found","message": "Sorry, the resourse not found!","path": "/api/resourceNotFoundException2"}
这种通过 ResponseStatus注解简单处理异常的方法是的好处是比较简单,但是一般我们不会这样做,通过ResponseStatusException会更加方便,可以避免我们额外的异常类。
@GetMapping("/resourceNotFoundException2")public void throwException3() {throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Sorry, the resourse not found!", new ResourceNotFoundException());}
使用 Get 请求 localhost:8080/api/resourceNotFoundException2[3] ,服务端返回的 JSON 数据如下,和使用 ResponseStatus 实现的效果一样:
{"timestamp": "2019-08-21T07:28:12.017+0000","status": 404,"error": "Not Found","message": "Sorry, the resourse not found!","path": "/api/resourceNotFoundException3"}
ResponseStatusException 提供了三个构造方法:
public ResponseStatusException(HttpStatus status) {this(status, null, null);}public ResponseStatusException(HttpStatus status, @Nullable String reason) {this(status, reason, null);}public ResponseStatusException(HttpStatus status, @Nullable String reason, @Nullable Throwable cause) {super(null, cause);Assert.notNull(status, "HttpStatus is required");this.status = status;this.reason = reason;}
构造函数中的参数解释如下:
•status :http status
•reason :response 的消息内容
•cause :抛出的异常
SpringBoot 处理异常的几种常见姿势的更多相关文章
- Upfile的几种常见姿势
记录一下文件上传的常见姿势,更全面的可以做upload-labs. 实验环境:win2003 phpstudy 实验平台:upfile 一.准备上传的一句话木马 eval函数将接受的字符串当做代码执行 ...
- 补习系列(7)-springboot 实现拦截的五种姿势
目录 简介 姿势一.使用 Filter 接口 1. 注册 FilterRegistrationBean 2. @WebFilter 注解 姿势二.HanlderInterceptor 姿势三.@Exc ...
- C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路
C#不用union,而是有更好的方式实现 用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C# ...
- 适用于app.config与web.config的ConfigUtil读写工具类 基于MongoDb官方C#驱动封装MongoDbCsharpHelper类(CRUD类) 基于ASP.NET WEB API实现分布式数据访问中间层(提供对数据库的CRUD) C# 实现AOP 的几种常见方式
适用于app.config与web.config的ConfigUtil读写工具类 之前文章:<两种读写配置文件的方案(app.config与web.config通用)>,现在重新整理一 ...
- Python爬虫突破封禁的6种常见方法
转 Python爬虫突破封禁的6种常见方法 2016年08月17日 22:36:59 阅读数:37936 在互联网上进行自动数据采集(抓取)这件事和互联网存在的时间差不多一样长.今天大众好像更倾向于用 ...
- 几种常见RuntimeException
一般面试java Exception(runtimeException )是个问题必须要问 常见的异常上市45种,它的基本要求.许多其他....需要注意的积累 常见的几种例如以下: NullP ...
- SpringBoot 开发案例之参数传递的正确姿势
前言 开发这么多年,肯定还有不少小伙伴搞不清各种类型的参数是如何传递的,很多同学都是拿来即用,复制粘贴一把撸,遇到问题还是一脸懵逼. 姿势 学习参数传递的正确姿势,先说怎么做,再说为什么,本质上还是复 ...
- SpringBoot 全局异常配置
在日常web开发中发生了异常,往往是需要通过一个统一的异常处理来保证客户端能够收到友好的提示. 一.默认异常机制 默认异常处理(SpringBoot 默认提供了两种机制,一种是针对于web浏览器访问的 ...
- Redis 的几种常见使用方式
常见使用方式 Redis 的几种常见使用方式包括: Redis 单副本 Redis 多副本(主从) Redis Sentinel(哨兵) Redis Cluster Redis 自研 各种使用方式的优 ...
随机推荐
- tp5 rewrite apache 配置
emmmmm,本来还是nginx服务器,突然换成了apache ubuntu系统,apache2服务器,tp5, 1.首先还是运行phpinfo.php,搜一下“Loaded Modules”这里面是 ...
- 移动端 vue + mintUI 实现头部页签切换,按需加载~
记录~记录~~有时候,我们会遇到一个页面有两个页签切换需求,但是为了避免同时加载两个页面,我们要做到的就是当前进入的是那个页面,就先加载哪一个页面,并且也不会造成浏览器地址的变化.一开始我使用的方法是 ...
- [踩坑记录] runtime error: load of null pointer of type 'const int' (leetcode)
leetcode上面做题遇到的错误 原因: 在调用函数时,如果返回值如果是一个常量则没问题.如果返回值若为指针则可能会出现该错误,假如返回的指针地址指向函数内的局部变量,在函数退出时,该变量的存储空间 ...
- 基于springboot实现轮询线程自动执行任务
本文使用: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时 ...
- Message Queue的使用目的
为什么要用Message Queue 摘录自博客:http://dataunion.org/9307.html?utm_source=tuicool&utm_medium=referral ...
- 「CF1142B」Lynyrd Skynyrd
传送门 Luogu 解题思路 发现一个性质: 对于排列的任何一个循环位移,排列中的同一个数的前驱肯定是不变的. 而且,如果一个排列的循环位移是某一个区间的子序列,那么这个循环位移的结尾的 \(n-1\ ...
- 【笔记8-Redis分布式锁】从0开始 独立完成企业级Java电商网站开发(服务端)
Redis分布式锁 Redis分布式锁命令 setnx当且仅当 key 不存在.若给定的 key 已经存在,则 setnx不做任何动作.setnx 是『set if not exists』(如果不存在 ...
- POJ-1087 A Plug for UNIX (网络流)
思路 电器数1 ~ 100,附带100种接口,注意题目:You notice that some of the devices use plugs for which there is no rece ...
- js HTML 年月日星期 时间的
效果格式:2019 年 04 月 13 日 星期六 13 : 24 : 49上面的类名有多余的 因为这是之前项目中的 方便以后使用 <!DOCTYPE html> <html> ...
- Golang 函数以及函数和方法的区别
在接触到go之前,我认为函数和方法只是同一个东西的两个名字而已(在我熟悉的c/c++,python,java中没有明显的区别),但是在golang中者完全是两个不同的东西.官方的解释是,方法是包含了接 ...