0、前言

  任何系统,我们不会傻傻的在每一个地方进行异常捕获和处理,整个系统一般我们会在一个的地方统一进行异常处理,spring boot全局异常处理很简单;

  介绍前先说点题外话,我们现在开发系统,都是前后端完全分离的,后端只提供RESTfull API,禁止涉及任何界面,什么thymeleaf、JSP那些后端模板,是绝对禁止使用的,那些东西请扔垃圾箱,不要浪费大好青春去研究,那是堕落;前端则负责界面相关,常用Vue;如果公司还没前后端分离,还在thymeleaf还在前后端一起写,那你还是早做跳槽打算吧,他们养不起你,更养不起你的家人;

  前后端分离,后端API,一般对于异常处理,要做得无非两件事,

    1是记录日志及相应通知处理,这是对内的,

    2是给出返回结果给API调用者,这是对外的;

对API调用者来说,他只需要一个返回结果(包含错误代码、提示信息),其他的他不关心

对后端来说,他只需要记录日志,通知或者给发布相应消息给其他队列处理相关事项;

所以:看到过不少人封装了很多个自定义异常类,其实,完全没有必要,只需要一个异常处理来处理所有异常即可,然后封装一个错误识别码和提示消息的枚举,用于返回给API调用者;然后后端的处理,直接在一个异常处理方法中全部处理就行了,完全没必要封装N多个自定义异常,那没有任何意义;

0-1、关于异常的思想认识

  我们应该认识到,一切异常,对系统来说,都是不正常的表现,都是属于缺陷,都属于BUG,尽管有些异常是我们主动抛出的;

  我们要做的,是应该尽量提高系统可用性,最大限度避免任何异常的出现,而不是去指望完善异常处理来完善系统;

  异常处理,是异常无法避免的出现了而采取的一种应急措施,主要目的是对外增加友好性,对内提供补救线索;

  不要认为完善的异常处理是系统核心,他不是,不要指望异常处理尽善尽美,不要指望异常处理来给系统缺陷擦屁股;

  如果系统异常过多,那么你要做的不是去完善异常处理机制,而是要好好去反思:系统架构设计是否合理,系统逻辑设计是否合理;

1、全局异常处理

使用@ControllerAdvice、@ExceptionHandler注解封装一个异常处理类即可
package com.anson.common.exception;

import com.anson.common.result.ResultBody;
import com.anson.common.result.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; /**
* @description: 全局异常处理类
* @author: anson
* @Date: 2019/12/17 20:56
*/ @ControllerAdvice
public class GlobalExceptionHandler
{
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /**
* 所有异常处理
* @param e
* @return
*/
@ExceptionHandler(value =Exception.class)
@ResponseBody
public ResultBody exceptionHandler(Exception e)
{
//1、写日志及其他处理,对内
logger.error("未知异常!原因是:",e);
System.out.println("未知异常!原因是:"+e); //2、返回错误识别码和提示给API调用者、对外
return ResultBody.failed(ResultCode.FAILED);
}
}

这样就可以了,

ResultBody、ResultCode这个我们下节会说到;

-------------------华丽丽的分割线--------------------------

2、自定义异常

  上面的异常处理可以处理所有异常了,但是有时候,比如在拦截器、AOP、侦听器中,我们要主动抛出特定异常,比如没有权限、登录过期等,这个时候,我们可以增加一个自动以异常来统一处理,如下:

2.1、增加一个自定义异常类:

package com.anson.common.exception;

import com.anson.common.result.IErrorCode;

/**
* @description: 自定义异常类
* @author: anson
* @Date: 2019/12/30 9:14
*/
public class BizException extends RuntimeException
{
private static final long serialVersionUID = 1L; protected long errorCode; //错误码
protected String errorMsg; //错误信息 //构造1
public BizException()
{
super();
}
//构造2
public BizException(IErrorCode errorInfoInterface) {
super(String.valueOf(errorInfoInterface.getCode()));
this.errorCode = errorInfoInterface.getCode();
this.errorMsg = errorInfoInterface.getMessage();
} public BizException(IErrorCode errorInfoInterface, Throwable cause) {
super(String.valueOf(errorInfoInterface.getCode()), cause);
this.errorCode = errorInfoInterface.getCode();
this.errorMsg = errorInfoInterface.getMessage();
} public BizException(String errorMsg) {
super(errorMsg);
this.errorMsg = errorMsg;
} public BizException(long errorCode, String errorMsg) {
super(String.valueOf(errorCode));
this.errorCode = errorCode;
this.errorMsg = errorMsg;
} public BizException(long errorCode, String errorMsg, Throwable cause) {
super(String.valueOf(errorCode), cause);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
} public long getErrorCode() {
return errorCode;
} public void setErrorCode(long errorCode) {
this.errorCode = errorCode;
} public String getErrorMsg() {
return errorMsg;
} public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
} public String getMessage() {
return errorMsg;
} @Override
public Throwable fillInStackTrace() {
return this;
} }

2.2、在全局异常处理中增加处理自定义异常:

package com.anson.common.exception;

import com.anson.common.result.ResultBody;
import com.anson.common.result.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; /**
* @description: 全局异常处理类
* @author: anson
* @Date: 2019/12/10 20:56
*/ @ControllerAdvice
public class GlobalExceptionHandler
{
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /**
* 1、处理自定义的业务异常
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = BizException.class)
@ResponseBody
public ResultBody bizExceptionHandler(HttpServletRequest req, BizException e){
logger.error("发生业务异常!原因是:{}",e.getErrorMsg());
return ResultBody.failed(e.getErrorCode(),e.getErrorMsg());
} /**
* 2、处理其他异常
* @param e
* @return
*/
@ExceptionHandler(value =Exception.class)
@ResponseBody
public ResultBody exceptionHandler(Exception e)
{
//1、写日志及其他处理,对内 logger.error("未知异常!原因是:",e);
System.out.println("未知异常!原因是:"+e); logger.trace("trace level");
logger.debug("debug level");
logger.info("info level");
logger.warn("warn level");
logger.error("error level"); long beginTime = System.currentTimeMillis();
logger.info("请求处理结束,耗时:{}毫秒", (System.currentTimeMillis() - beginTime)); //第一种用法
logger.info("请求处理结束,耗时:" + (System.currentTimeMillis() - beginTime) + "毫秒"); //第二种用法
//------------------------------ //2、返回错误识别码和提示给API调用者、对外
return ResultBody.failed(ResultCode.FAILED);
}
}

2.3、然后,在需要的地方上抛异常即可

        //主动抛出自定义异常
throw new BizException(ResultCode.UNAUTHORIZED.getCode(),ResultCode.UNAUTHORIZED.getMessage());

运行后即可看到上抛了自定义异常:

小白的springboot之路(十)、全局异常处理的更多相关文章

  1. 小白的springboot之路(一)、环境搭建、第一个实例

    小白的springboot之路(一).环境搭建.第一个实例 0- 前言 Spring boot + spring cloud + vue 的微服务架构技术栈,那简直是爽得不要不要的,怎么爽法,自行度娘 ...

  2. 小白的springboot之路(十四)、AOP

    0.前言 1.什么是AOP AOP(面向切面编程),是一种横切技术,是对OOP的补充和完善: 使用AOP的横切,可以对系统进行无侵入性的日志监听.事务.权限管理等: 思想上跟拦截器其实类似;拦截器是对 ...

  3. 小白的springboot之路(十二)、集成log4j2日志

    0.前言 日志记录对系统来说必不可少,spring boot中常用的日志组件有log4j.logback.log4j2,其中logback是spring boot默认的,已自带:选用log4j2就可以 ...

  4. 小白的springboot之路(十五)、mybatis的PageHelper分页插件使用

    0.前言 用mybatis,那么分页必不可少,基本都是用PageHelper这个分页插件,好用方便: 1.实现 1.1.添加依赖: <!-- 3.集成 mybatis pagehelper--& ...

  5. 小白的springboot之路(十六)、mybatis-plus 的使用

    0-前言 mybatis plus是对mybatis的增强,集成mybatis plus后,简单的CRUD和分页就不用写了,非常方便,五星推荐: 1-集成 1-1.添加依赖 <!-- .集成my ...

  6. 小白的springboot之路(十八)、i18n多语言支持(后端篇)

    0-前言 在有些系统中,比如网站,往往需要支持多国语言,英文版中文版什么的,这个其实也不难: 今天我们就来介绍spring boot中用i18n在后端支持多语言: 当然,也可以直接在前端用i18n直接 ...

  7. 小白的springboot之路(十九)、集成swagger(com.spring4all篇)

    0-前言 集成swagger,有两种方式: 一种在前面已经介绍过了,直接集成官方的springfox-swagger2的方式,这种方式需要在配置类中配置 第二种方式是这里要介绍的方式,国人写的com. ...

  8. 小白的springboot之路(二)、集成swagger

    0-前言 现在的项目开发,基本都是前后端分离,后端专注于API接口开发,都需要编写和维护API接口文档.如果你还在用Word来编写接口文档,那你就out了,这个时候,当当当当~神兵利器swagger隆 ...

  9. 小白的springboot之路(七)、事务支持

    0-前言 事务管理对于企业级应用来说必不可少,用来确保数据的完整性和一致性: 1-开启事务 spring boot支持编程式事务和声明式事务,用声明式事务即可: spring boot开启事务非常简单 ...

随机推荐

  1. PhpStudy BackDoor2019 深度分析

    笔者<Qftm>原文发布<合天>:https://mp.weixin.qq.com/s?__biz=MjM5MTYxNjQxOA==&mid=2652852661&am ...

  2. ReactJS中的自定义组件

    可控自定义组件: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...

  3. windows版的mysql主从复制环境搭建

    背景 最近在学习用Spring Aop来实现数据库读写分离的功能. 在编写代码之前,首先是要部署好mysql的环境,因为要实现读写分离,所以至少需要部署两个mysql实例,一主一从,并且主从实例之间能 ...

  4. Rio手把手教学:如何打造容器化应用程序的一站式部署体验

    11月19日,业界应用最为广泛的Kubernetes管理平台创建者Rancher Labs(以下简称Rancher)宣布Rio发布了beta版本,这是基于Kubernetes的应用程序部署引擎.它于今 ...

  5. &#128293;《手把手》系列基础篇之2-python+ selenium-打开和关闭浏览器(详细)

    1. 简介 本节介绍如何初始化一个webdriver实例对象driver,然后打开和关闭firefox浏览器.要用selenium打开fiefox浏览器.首先需要去下载一个driver插件geckod ...

  6. Hadoop之HDFS文件系统

    概念 HDFS,它是一个文件系统,用于存储文件,通过目录树来定位文件:其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色. HDFS的设计适合一次写入,多次读出的场景,且不 ...

  7. Acquistion Location Confidence for accurate object detection

    Acquistion Location Confidence for accurate object detection 本论文主要是解决一下两个问题: 1.分类得分高的预测框与IOU不匹配,(我猜应 ...

  8. 【论文阅读】TextSnake: A Flexible Representation for Detecting Text of Arbitrary Shapes

    TextSnake: A Flexible Representation for Detecting Text of Arbitrary Shapes ECCV2018 北京大学.face++ 思路: ...

  9. Paramiko的SSH和SFTP使用

    目录 1. 概述 2. Paramiko的基本使用 2.1 SSHClient关键参数介绍 2.2 SSHClient常用示例 2.2.1 通过用户名和密码方式登陆: 2.2.2 通过用户名和密码方式 ...

  10. scikit-learn网格搜索来进行高效的参数调优

    内容概要¶ 如何使用K折交叉验证来搜索最优调节参数 如何让搜索参数的流程更加高效 如何一次性的搜索多个调节参数 在进行真正的预测之前,如何对调节参数进行处理 如何削减该过程的计算代价 1. K折交叉验 ...