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;    }    @Override    public 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 {    @Autowired    MockMvc mockMvc;    @Test    void should_return_400_if_param_not_valid() throws Exception {        mockMvc.perform(get("/api/illegalArgumentException"))                .andExpect(status().is(400))                .andExpect(jsonPath("$.message").value("参数错误!"));    }    @Test    void 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 处理异常的几种常见姿势的更多相关文章

  1. Upfile的几种常见姿势

    记录一下文件上传的常见姿势,更全面的可以做upload-labs. 实验环境:win2003 phpstudy 实验平台:upfile 一.准备上传的一句话木马 eval函数将接受的字符串当做代码执行 ...

  2. 补习系列(7)-springboot 实现拦截的五种姿势

    目录 简介 姿势一.使用 Filter 接口 1. 注册 FilterRegistrationBean 2. @WebFilter 注解 姿势二.HanlderInterceptor 姿势三.@Exc ...

  3. C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路

    C#不用union,而是有更好的方式实现   用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C# ...

  4. 适用于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通用)>,现在重新整理一 ...

  5. Python爬虫突破封禁的6种常见方法

    转 Python爬虫突破封禁的6种常见方法 2016年08月17日 22:36:59 阅读数:37936 在互联网上进行自动数据采集(抓取)这件事和互联网存在的时间差不多一样长.今天大众好像更倾向于用 ...

  6. 几种常见RuntimeException

    一般面试java Exception(runtimeException )是个问题必须要问 常见的异常上市45种,它的基本要求.许多其他....需要注意的积累   常见的几种例如以下:   NullP ...

  7. SpringBoot 开发案例之参数传递的正确姿势

    前言 开发这么多年,肯定还有不少小伙伴搞不清各种类型的参数是如何传递的,很多同学都是拿来即用,复制粘贴一把撸,遇到问题还是一脸懵逼. 姿势 学习参数传递的正确姿势,先说怎么做,再说为什么,本质上还是复 ...

  8. SpringBoot 全局异常配置

    在日常web开发中发生了异常,往往是需要通过一个统一的异常处理来保证客户端能够收到友好的提示. 一.默认异常机制 默认异常处理(SpringBoot 默认提供了两种机制,一种是针对于web浏览器访问的 ...

  9. Redis 的几种常见使用方式

    常见使用方式 Redis 的几种常见使用方式包括: Redis 单副本 Redis 多副本(主从) Redis Sentinel(哨兵) Redis Cluster Redis 自研 各种使用方式的优 ...

随机推荐

  1. vscode解决java无法输入(scanner)问题

    vscode解决java无法输入问题 需要先安装java环境,->windows安装java 新建Test.java 输入代码 import java.util.Scanner; public ...

  2. 201771010135 杨蓉庆《面对对象程序设计(java)》第十五周学习总结

    1.实验目的与要求 (1) 掌握Java应用程序的打包操作: (2) 了解应用程序存储配置信息的两种方法: (3) 掌握基于JNLP协议的java Web Start应用程序的发布方法: (5) 掌握 ...

  3. Android如何运行他人工程

    首先新建一个本地的新工程做对比,用记事本打开以下的几个工程文件,把本地工程文件的内容覆盖掉他人工程的文件内容,注意只覆盖两个工程共有的内容条目即可,不要删掉他人工程的其他依赖!(具体哪几个文件本人还没 ...

  4. zookeeper基本使用

    (1)查看节点信息:ls / (2)查看单个节点的状态:stat /zookeeper (3)在Java中使用的zk客户端:zkClient,curator (4)curator是apache的开源的 ...

  5. Shiro入门学习与实战(一)

    一.概述 1.Shiro是什么? Apache Shiro是java 的一个安全框架,主要提供:认证.授权.加密.会话管理.与Web集成.缓存等功能,其不依赖于Spring即可使用: Spring S ...

  6. js 判断素数(质数)

    判断一个数是不是素数 function isPrinme(n) { if(n == 0 || n==1){ return false; } if(n==2){ return true; } for(v ...

  7. SpringBoot 系列

    https://my.oschina.net/xiedeshou?tab=newest&catalogId=5936801 SpringBoot | 第零章:前言 SpringBoot | 第 ...

  8. 例题3_3 回文词(UVa401)

    输入一个字符串,判断它是否为回文串以及镜像串.输入字符串保证不含数字0.所谓回文串,就是反转以后和原串相同,如abba和madam.所有镜像串,就是左右镜像之后和原串相同,如2S和3AIAE.注意,并 ...

  9. java模板字符串功能的简单实现

    package com.Interface.util; import lombok.extern.slf4j.Slf4j; /** * 测试类 * * @author 华文 * @date 2019年 ...

  10. 一大波新款iPhone跟安卓厂商抢夺5G市场

    据外媒最新报道称,苹果已经基本完成了今年iPhone的推新阵容,其发布的多款新机中,将涵盖399美元-1149美元的售价区间,特别是5G手机,起步价可能会很亲民,其目的在于进一步占据市场. 今年苹果将 ...