今日推荐编程大佬是否能记住代码,不用百度就能啪啪啪敲出来么?在 IDEA 中的各种调试技巧,轻松定位 Bug(超级全面)

后端接口如何提高性能?

16 个写代码的好习惯

为什么不推荐使用BeanUtils属性转换工具

盘点阿里巴巴 34 个牛逼 GitHub 项目

来源:cnblogs.com/xuwujing/p/10933082.html

前言

本篇文章主要介绍的是SpringBoot项目进行全局异常的处理。

SpringBoot全局异常准备

说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程代码。

开发准备

环境要求

  • JDK:1.8

  • SpringBoot:1.5.17.RELEASE

首先还是Maven的相关依赖:

  <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.17.RELEASE</version><relativePath /></parent><dependencies><!-- Spring Boot Web 依赖 核心 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Test 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.41</version></dependency></dependencies>

配置文件这块基本不需要更改,全局异常的处理只需在代码中实现即可。

代码编写

SpringBoot的项目已经对有一定的异常处理了,但是对于我们开发者而言可能就不太合适了,因此我们需要对这些异常进行统一的捕获并处理。

SpringBoot中有一个ControllerAdvice的注解,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用ExceptionHandler注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。

我们根据下面的这个示例来看该注解是如何使用吧。

示例代码:

@ControllerAdvice
public class MyExceptionHandler {@ExceptionHandler(value =Exception.class)public String exceptionHandler(Exception e){System.out.println("未知异常!原因是:"+e);return e.getMessage();}
}

上述的示例中,我们对捕获的异常进行简单的二次处理,返回异常的信息,虽然这种能够让我们知道异常的原因,但是在很多的情况下来说,可能还是不够人性化,不符合我们的要求。

那么我们这里可以通过自定义的异常类以及枚举类来实现我们想要的那种数据吧。

自定义基础接口类

首先定义一个基础的接口类,自定义的错误描述枚举类需实现该接口。

代码如下:

public interface BaseErrorInfoInterface {/** 错误码*/String getResultCode();/** 错误描述*/String getResultMsg();
}

自定义枚举类

然后我们这里在自定义一个枚举类,并实现该接口。

代码如下:

public enum CommonEnum implements BaseErrorInfoInterface {// 数据操作错误定义SUCCESS("200", "成功!"), BODY_NOT_MATCH("400","请求的数据格式不符!"),SIGNATURE_NOT_MATCH("401","请求的数字签名不匹配!"),NOT_FOUND("404", "未找到该资源!"), INTERNAL_SERVER_ERROR("500", "服务器内部错误!"),SERVER_BUSY("503","服务器正忙,请稍后再试!");/** 错误码 */private String resultCode;/** 错误描述 */private String resultMsg;CommonEnum(String resultCode, String resultMsg) {this.resultCode = resultCode;this.resultMsg = resultMsg;}@Overridepublic String getResultCode() {return resultCode;}@Overridepublic String getResultMsg() {return resultMsg;}}

自定义异常类

然后我们在来自定义一个异常类,用于处理我们发生的业务异常。

代码如下:

public class BizException extends RuntimeException {private static final long serialVersionUID = 1L;/*** 错误码*/protected String errorCode;/*** 错误信息*/protected String errorMsg;public BizException() {super();}public BizException(BaseErrorInfoInterface errorInfoInterface) {super(errorInfoInterface.getResultCode());this.errorCode = errorInfoInterface.getResultCode();this.errorMsg = errorInfoInterface.getResultMsg();}public BizException(BaseErrorInfoInterface errorInfoInterface, Throwable cause) {super(errorInfoInterface.getResultCode(), cause);this.errorCode = errorInfoInterface.getResultCode();this.errorMsg = errorInfoInterface.getResultMsg();}public BizException(String errorMsg) {super(errorMsg);this.errorMsg = errorMsg;}public BizException(String errorCode, String errorMsg) {super(errorCode);this.errorCode = errorCode;this.errorMsg = errorMsg;}public BizException(String errorCode, String errorMsg, Throwable cause) {super(errorCode, cause);this.errorCode = errorCode;this.errorMsg = errorMsg;}public String getErrorCode() {return errorCode;}public void setErrorCode(String errorCode) {this.errorCode = errorCode;}public String getErrorMsg() {return errorMsg;}public void setErrorMsg(String errorMsg) {this.errorMsg = errorMsg;}public String getMessage() {return errorMsg;}@Overridepublic Throwable fillInStackTrace() {return this;}}

自定义数据格式

顺便这里我们定义一下数据的传输格式。

代码如下:

public class ResultBody {/*** 响应代码*/private String code;/*** 响应消息*/private String message;/*** 响应结果*/private Object result;public ResultBody() {}public ResultBody(BaseErrorInfoInterface errorInfo) {this.code = errorInfo.getResultCode();this.message = errorInfo.getResultMsg();}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Object getResult() {return result;}public void setResult(Object result) {this.result = result;}/*** 成功* * @return*/public static ResultBody success() {return success(null);}/*** 成功* @param data* @return*/public static ResultBody success(Object data) {ResultBody rb = new ResultBody();rb.setCode(CommonEnum.SUCCESS.getResultCode());rb.setMessage(CommonEnum.SUCCESS.getResultMsg());rb.setResult(data);return rb;}/*** 失败*/public static ResultBody error(BaseErrorInfoInterface errorInfo) {ResultBody rb = new ResultBody();rb.setCode(errorInfo.getResultCode());rb.setMessage(errorInfo.getResultMsg());rb.setResult(null);return rb;}/*** 失败*/public static ResultBody error(String code, String message) {ResultBody rb = new ResultBody();rb.setCode(code);rb.setMessage(message);rb.setResult(null);return rb;}/*** 失败*/public static ResultBody error( String message) {ResultBody rb = new ResultBody();rb.setCode("-1");rb.setMessage(message);rb.setResult(null);return rb;}@Overridepublic String toString() {return JSONObject.toJSONString(this);}}

自定义全局异常处理类

最后我们在来编写一个自定义全局异常处理的类。

代码如下:

@ControllerAdvice
public class GlobalExceptionHandler {private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);/*** 处理自定义的业务异常* @param req* @param e* @return*/@ExceptionHandler(value = BizException.class)  @ResponseBody  public  ResultBody bizExceptionHandler(HttpServletRequest req, BizException e){logger.error("发生业务异常!原因是:{}",e.getErrorMsg());return ResultBody.error(e.getErrorCode(),e.getErrorMsg());}/*** 处理空指针的异常* @param req* @param e* @return*/@ExceptionHandler(value =NullPointerException.class)@ResponseBodypublic ResultBody exceptionHandler(HttpServletRequest req, NullPointerException e){logger.error("发生空指针异常!原因是:",e);return ResultBody.error(CommonEnum.BODY_NOT_MATCH);}/*** 处理其他异常* @param req* @param e* @return*/@ExceptionHandler(value =Exception.class)@ResponseBodypublic ResultBody exceptionHandler(HttpServletRequest req, Exception e){logger.error("未知异常!原因是:",e);return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);}
}

因为这里我们只是用于做全局异常处理的功能实现以及测试,所以这里我们只需在添加一个实体类和一个控制层类即可。

实体类

又是万能的用户表 (▽)

代码如下:

public class User implements Serializable{private static final long serialVersionUID = 1L;/** 编号 */private int id;/** 姓名 */private String name;/** 年龄 */private int age;public User(){}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String toString() {return JSONObject.toJSONString(this);}
}

Controller 控制层

控制层这边也比较简单,使用Restful风格实现的CRUD功能,不同的是这里我故意弄出了一些异常,好让这些异常被捕获到然后处理。

这些异常中,有自定义的异常抛出,也有空指针的异常抛出,当然也有不可预知的异常抛出(这里我用类型转换异常代替),那么我们在完成代码编写之后,看看这些异常是否能够被捕获处理成功吧!

代码如下:

@RestController
@RequestMapping(value = "/api")
public class UserRestController {@PostMapping("/user")public boolean insert(@RequestBody User user) {System.out.println("开始新增...");//如果姓名为空就手动抛出一个自定义的异常!if(user.getName()==null){throw  new BizException("-1","用户姓名不能为空!");}return true;}@PutMapping("/user")public boolean update(@RequestBody User user) {System.out.println("开始更新...");//这里故意造成一个空指针的异常,并且不进行处理String str=null;str.equals("111");return true;}@DeleteMapping("/user")public boolean delete(@RequestBody User user)  {System.out.println("开始删除...");//这里故意造成一个异常,并且不进行处理Integer.parseInt("abc123");return true;}@GetMapping("/user")public List<User> findByUser(User user) {System.out.println("开始查询...");List<User> userList =new ArrayList<>();User user2=new User();user2.setId(1L);user2.setName("xuwujing");user2.setAge(18);userList.add(user2);return userList;}}

App 入口

和普通的SpringBoot项目基本一样。

代码如下:

@SpringBootApplication
public class App
{public static void main( String[] args ){SpringApplication.run(App.class, args);System.out.println("程序正在运行...");}
}

功能测试

我们成功启动该程序之后,使用Postman工具来进行接口测试。

首先进行查询,查看程序正常运行是否ok,使用GET 方式进行请求。

GET http://localhost:8181/api/user

返回参数为:

{"id":1,"name":"xuwujing","age":18}

示例图:

可以看到程序正常返回,并没有因自定义的全局异常而影响。

然后我们再来测试下自定义的异常是否能够被正确的捕获并处理。

使用POST方式进行请求

POST http://localhost:8181/api/user

Body参数为:

{"id":1,"age":18}

返回参数为:

{"code":"-1","message":"用户姓名不能为空!","result":null}

示例图:

可以看出将我们抛出的异常进行数据封装,然后将异常返回出来。

然后我们再来测试下空指针异常是否能够被正确的捕获并处理。在自定义全局异常中,我们除了定义空指针的异常处理,也定义最高级别之一的Exception异常,那么这里发生了空指针异常之后,它是回优先使用哪一个呢?这里我们来测试下。

使用PUT方式进行请求。

PUT http://localhost:8181/api/user

Body参数为:

{"id":1,"age":18}

返回参数为:

{"code":"400","message":"请求的数据格式不符!","result":null}

示例图:

我们可以看到这里的的确是返回空指针的异常护理,可以得出全局异常处理优先处理子类的异常。

那么我们在来试试未指定其异常的处理,看该异常是否能够被捕获。

使用DELETE方式进行请求。

DELETE http://localhost:8181/api/user

Body参数为:

{"id":1}

返回参数为:

{"code":"500","message":"服务器内部错误!","result":null}

这里可以看到它使用了我们在自定义全局异常处理类中的Exception异常处理的方法。

到这里,测试就结束了。顺便再说一下,自义定全局异常处理除了可以处理上述的数据格式之外,也可以处理页面的跳转,只需在新增的异常方法的返回处理上填写该跳转的路径并不使用ResponseBody 注解即可。

细心的同学也许发现了在GlobalExceptionHandler类中使用的是ControllerAdvice注解,而非RestControllerAdvice注解,如果是用的RestControllerAdvice注解,它会将数据自动转换成JSON格式,这种于Controller和RestController类似,所以我们在使用全局异常处理的之后可以进行灵活的选择处理。

其它

关于SpringBoot优雅的全局异常处理的文章就讲解到这里了,如有不妥,欢迎指正!

项目地址

SpringBoot全局异常的处理项目工程地址:

https://github.com/xuwujing/springBoot-study/tree/master/springboot-exceptionHandler

推荐文章
  • 14个项目!

  • 一款小清新的 SpringBoot+ Mybatis 前后端分离后台管理系统项目

  • 47K Star 的SpringBoot+MyBatis+docker电商项目,附带超详细的文档!

  • 写博客能月入10K?

  • 一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)

更多项目源码
  • 这或许是最美的Vue+Element开源后台管理UI

  • 推荐一款高颜值的 Spring Boot 快速开发框架

  • 一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)

  • 13K点赞都基于 Vue+Spring 前后端分离管理系统ELAdmin,大爱

  • 想接私活时薪再翻一倍,建议根据这几个开源的SpringBoot

看看别人家 SpringBoot 的全局异常处理,多么优雅....相关推荐

  1. 看看人家 SpringBoot 的全局异常处理多么优雅...

    1 SpringBoot全局异常准备 说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程代码. 开发准备 环境要求JDK:1.8SpringBoot:1.5.17.RELEASE 首先还是 ...

  2. SpringBoot的全局异常处理的优雅吃法!要进来学习下吗

    SpringBoot的全局异常处理的优雅吃法!要进来学习下吗 SpringBoot全局异常准备 开发准备 环境要求 JDK :1.8 SpringBoot :1.5.17.RELEASE 首先还是Ma ...

  3. SpringBoot集成全局异常处理

    2019独角兽企业重金招聘Python工程师标准>>> SpringBoot集成全局异常处理 前言 对于通常的MVC项目,大量的异常需要我们去处理,如此一来,我们的 Controll ...

  4. 看看人家 SpringBoot 的全局异常处理,多么优雅...

    点击关注公众号,Java干货及时送达 本篇文章主要介绍的是SpringBoot项目进行全局异常的处理. SpringBoot全局异常准备 说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程 ...

  5. springboot定义全局异常处理类GlobalExceptionHandler

    全局异常处理:GlobalExceptionHandler 定义全局异常处理类 以下为扩展部分 返回参数封装 引用示例 定义全局异常处理类 注意:如果需要返回页面,则要删掉@ResponseBody注 ...

  6. Springboot 自定义全局异常处理

    在项目根包目录下新建 exception.base 包 新建BaseException 继承 RuntimeException package com.ddz.errordemo.handler;/* ...

  7. springboot基于全局异常处理的简单日志打印

    log.error() Logger类下有多个不同的error方法,根据传入参数的个数及类型的不同,自动选择不同的重载方法. 当error(Object obj)只传入一个参数时会将异常对象作为Obj ...

  8. 看看人家Java 集合处理/ 空值处理/ 异常处理多么优雅,一看就经验丰富!

    作者:LeiLeiChen https://llchen60.com/Java-集合处理-和-空值处理/ 1. Arrays.asList 业务开发当中,我们常常会将原始的数组转换为List类数据结构 ...

  9. springBoot 全局异常处理 报错 : Could not resolve method parameter at index 0 in public .....

    在学习 springboot 的全局异常处理时   ,我写了一个处理异常类 @ControllerAdvice public class ErrorCatchController {@Exceptio ...

最新文章

  1. 【电信增值业务学习笔记】7 USSD增值业务提供技术
  2. jquery之ajax请求工具类
  3. 【C++学习】String类的基本用法
  4. 一篇文章搞定面试中的二叉树
  5. ret2shellcdoe
  6. 如何看CentOS系统是32位还是64位的?
  7. Hadoop初步简介
  8. 浙大计算机基础知识2,[精选资料]14年浙大远程计算机基础2Windows知识题高起专 作业题2答案...
  9. -rw-r--r--@ what's @
  10. c语言打字游戏程序设计报告,2016打字游戏程序设计报告.doc
  11. 基于Java在线学习系统设计与实现
  12. 学习问题:图像内插-最近邻内插法
  13. 空手套白狼的典型案例,不花一分钱,整合别家产品,赚自己的钱
  14. matlab chan算法定位,求Chan算法解析
  15. 秒杀系统架构设计与分析
  16. 为什么usb计算机连接无法识别,无法识别usb设备,教您电脑出现无法识别usb设备怎么办...
  17. Android逆向学习(1)--记一次破解某直播盒子App
  18. linux环境下的进程
  19. 20220524 深度学习技术点
  20. android atlas,Atlas接入及使用教程

热门文章

  1. 查看SSID的mac地址
  2. 双曲线和直线联立公式_高中圆锥曲线解题技巧之齐次化联立(四)
  3. PKI/CA (6)双证书
  4. Bitcoin0.21版 公链开发(3) 网关PHP windows上安装
  5. 近世代数--外直积--外直积是什么?关于阶的性质?
  6. 劳动力工资调整模型的探讨——数学建模
  7. [How TO]-在ubuntu20.10上搭建SVN Server
  8. Kali-Linux虚拟机安装提示
  9. CMap在用CString做key类型时,ARG_KEY要选LPCTSTR
  10. RecyclerView点击事件监听