统一异常处理 GlobalExceptionHandler

平时经常在代码里面

try {...
} catch (Exception e) {...
}

这样子代码繁琐而且也不好看。特别是还有一些需要自己new一个map封装业务的异常信息,是在是难看。
所以就需要引出全局异常。经过一些封装,就可以实现这样的效果了。
image.png

还是看代码吧!
首先是定义了一个GlobalExceptionHandler组件,通过添加@RestControllerAdvice注解,作为默认的Controller全局异常处理增强组件,在这个组件中分别对 系统级别未知系统、客户端异常、服务端异常 都分别做了统一处理。

/*** 默认的Controller全局异常处理增强组件**/
@Slf4j
@RestControllerAdvice
@Order
public class GlobalExceptionHandler {// =========== 系统级别未知异常 =========@ExceptionHandler(value = Exception.class)public JsonResult<Object> handle(Exception e) {log.error("[ 系统未知错误 ]", e);return JsonResult.buildError(CommonErrorCodeEnum.SYSTEM_UNKNOWN_ERROR);}// =========== 客户端异常 =========/*** 1001 HTTP请求方法类型错误** @param e* @return*/@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)public JsonResult<Object> handle(HttpRequestMethodNotSupportedException e) {log.error("[客户端HTTP请求方法错误]", e);return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_HTTP_METHOD_ERROR);}/*** 1002 客户端请求体参数校验不通过** @param e* @return*/@ExceptionHandler(value = MethodArgumentNotValidException.class)public JsonResult<Object> handle(MethodArgumentNotValidException e) {log.error("[客户端请求体参数校验不通过]", e);String errorMsg = this.handle(e.getBindingResult().getFieldErrors());return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_REQUEST_BODY_CHECK_ERROR.getErrorCode(), errorMsg);}private String handle(List<FieldError> fieldErrors) {StringBuilder sb = new StringBuilder();for (FieldError obj : fieldErrors) {sb.append(obj.getField());sb.append("=[");sb.append(obj.getDefaultMessage());sb.append("]  ");}return sb.toString();}/*** 1003 客户端请求体JSON格式错误或字段类型不匹配** @param e* @return*/@ExceptionHandler(value = HttpMessageNotReadableException.class)public JsonResult<Object> handle(HttpMessageNotReadableException e) {log.error("[客户端请求体JSON格式错误或字段类型不匹配]", e);return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_REQUEST_BODY_FORMAT_ERROR);}/*** 1004 客户端URL中的参数类型错误** @param e* @return*/@ExceptionHandler(value = BindException.class)public JsonResult<Object> handle(BindException e) {log.error("[客户端URL中的参数类型错误]", e);FieldError fieldError = e.getBindingResult().getFieldError();String errorMsg = null;if (fieldError != null) {errorMsg = fieldError.getDefaultMessage();if (errorMsg != null && errorMsg.contains("java.lang.NumberFormatException")) {errorMsg = fieldError.getField() + "参数类型错误";}}if (errorMsg != null && !"".equals(errorMsg)) {return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_PATH_VARIABLE_ERROR.getErrorCode(), errorMsg);}return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_PATH_VARIABLE_ERROR);}/*** 1005 客户端请求参数校验不通过** @param e* @return*/@ExceptionHandler(value = ConstraintViolationException.class)public JsonResult<Object> handle(ConstraintViolationException e) {log.error("[客户端请求参数校验不通过]", e);Iterator<ConstraintViolation<?>> it = e.getConstraintViolations().iterator();String errorMsg = null;if (it.hasNext()) {errorMsg = it.next().getMessageTemplate();}if (errorMsg != null && !"".equals(errorMsg)) {return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_REQUEST_PARAM_CHECK_ERROR.getErrorCode(), errorMsg);}return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_REQUEST_PARAM_CHECK_ERROR);}/*** 1006 客户端请求缺少必填的参数** @param e* @return*/@ExceptionHandler(value = MissingServletRequestParameterException.class)public JsonResult<Object> handle(MissingServletRequestParameterException e) {log.error("[客户端请求缺少必填的参数]", e);String errorMsg = null;String parameterName = e.getParameterName();if (!"".equals(parameterName)) {errorMsg = parameterName + "不能为空";}if (errorMsg != null) {return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_REQUEST_PARAM_REQUIRED_ERROR.getErrorCode(), errorMsg);}return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_REQUEST_PARAM_REQUIRED_ERROR);}// =========== 服务端异常 =========/*** 2001 业务方法参数检查不通过** @param e* @return*/@ExceptionHandler(value = IllegalArgumentException.class)public JsonResult<Object> handle(IllegalArgumentException e) {log.error("[业务方法参数检查不通过]", e);return JsonResult.buildError(CommonErrorCodeEnum.SERVER_ILLEGAL_ARGUMENT_ERROR);}/*** 系统自定义业务异常** @param e* @return*/@ExceptionHandler(value = BaseBizException.class)public JsonResult<Object> handle(BaseBizException e) {log.error("[ 业务异常 ]", e);return JsonResult.buildError(e.getErrorCode(), e.getErrorMsg());}

其次是BaseBizException自定义基础业务异常类

/*** 基础自定义业务异常*/
public class BaseBizException extends RuntimeException {/*** 默认错误码*/private static final String DEFAULT_ERROR_CODE = "-1";private String errorCode;private String errorMsg;public BaseBizException(String errorMsg) {super(errorMsg);this.errorCode = DEFAULT_ERROR_CODE;this.errorMsg = errorMsg;}public BaseBizException(String errorCode, String errorMsg) {super(errorMsg);this.errorCode = errorCode;this.errorMsg = errorMsg;}public BaseBizException(BaseErrorCodeEnum baseErrorCodeEnum) {super(baseErrorCodeEnum.getErrorMsg());this.errorCode = baseErrorCodeEnum.getErrorCode();this.errorMsg = baseErrorCodeEnum.getErrorMsg();}public BaseBizException(String errorCode, String errorMsg, Object... arguments) {super(MessageFormat.format(errorMsg, arguments));this.errorCode = errorCode;this.errorMsg = MessageFormat.format(errorMsg, arguments);}public BaseBizException(BaseErrorCodeEnum baseErrorCodeEnum, Object... arguments) {super(MessageFormat.format(baseErrorCodeEnum.getErrorMsg(), arguments));this.errorCode = baseErrorCodeEnum.getErrorCode();this.errorMsg = MessageFormat.format(baseErrorCodeEnum.getErrorMsg(), arguments);}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 interface BaseErrorCodeEnum {String getErrorCode();String getErrorMsg();
}

系统通用的业务异常错误码枚举

/*** 系统通用的业务异常错误码枚举* @version 1.0*/
public enum CommonErrorCodeEnum implements BaseErrorCodeEnum {// =========== 系统级别未知异常 =========/*** 系统未知错误*/SYSTEM_UNKNOWN_ERROR("-1", "系统未知错误"),// =========== 客户端异常 =========/*** 客户端HTTP请求方法错误* org.springframework.web.HttpRequestMethodNotSupportedException*/CLIENT_HTTP_METHOD_ERROR("1001", "客户端HTTP请求方法错误"),/*** 客户端request body参数错误* 主要是未能通过Hibernate Validator校验的异常处理* <p>* org.springframework.web.bind.MethodArgumentNotValidException*/CLIENT_REQUEST_BODY_CHECK_ERROR("1002", "客户端请求体参数校验不通过"),/*** 客户端@RequestBody请求体JSON格式错误或字段类型错误* org.springframework.http.converter.HttpMessageNotReadableException* <p>* eg:* 1、参数类型不对:{"test":"abc"},本身类型是Long* 2、{"test":}  test属性没有给值*/CLIENT_REQUEST_BODY_FORMAT_ERROR("1003", "客户端请求体JSON格式错误或字段类型不匹配"),/*** 客户端@PathVariable参数错误* 一般是类型不匹配,比如本来是Long类型,客户端却给了一个无法转换成Long字符串* org.springframework.validation.BindException*/CLIENT_PATH_VARIABLE_ERROR("1004", "客户端URL中的参数类型错误"),/*** 客户端@RequestParam参数校验不通过* 主要是未能通过Hibernate Validator校验的异常处理* javax.validation.ConstraintViolationException*/CLIENT_REQUEST_PARAM_CHECK_ERROR("1005", "客户端请求参数校验不通过"),/*** 客户端@RequestParam参数必填* 入参中的@RequestParam注解设置了必填,但是客户端没有给值* javax.validation.ConstraintViolationException*/CLIENT_REQUEST_PARAM_REQUIRED_ERROR("1006", "客户端请求缺少必填的参数"),// =========== 服务端异常 =========/*** 通用的业务方法入参检查错误* java.lang.IllegalArgumentException*/SERVER_ILLEGAL_ARGUMENT_ERROR("2001", "业务方法参数检查不通过"),;private String errorCode;private String errorMsg;CommonErrorCodeEnum(String errorCode, String errorMsg) {this.errorCode = errorCode;this.errorMsg = errorMsg;}@Overridepublic String getErrorCode() {return errorCode;}public void setErrorCode(String errorCode) {this.errorCode = errorCode;}@Overridepublic String getErrorMsg() {return errorMsg;}public void setErrorMsg(String errorMsg) {this.errorMsg = errorMsg;}
}

在业务代码的开发中,可以直接抛出这个异常类,也可以在具体的业务代码工程新建一个类继承BaseBizException,然后抛出自定义的异常类。比如如在客户模块中,新建一个CustomerBizException自定义类,然后继承BaseBizException,


public class CustomerBizException extends BaseBizException {public CustomerBizException(String errorMsg) {super(errorMsg);}public CustomerBizException(String errorCode, String errorMsg) {super(errorCode, errorMsg);}public CustomerBizException(BaseErrorCodeEnum baseErrorCodeEnum) {super(baseErrorCodeEnum);}public CustomerBizException(String errorCode, String errorMsg, Object... arguments) {super(errorCode, errorMsg, arguments);}public CustomerBizException(BaseErrorCodeEnum baseErrorCodeEnum, Object... arguments) {super(baseErrorCodeEnum, arguments);}
}
/*** 异常错误码枚举值* 前三位代表服务,后三位代表功能错误码*/
public enum CustomerErrorCodeEnum implements BaseErrorCodeEnum {CUSTOMER_AUDIT_REPEAT("200000", "客服审核重复"),;private String errorCode;private String errorMsg;CustomerErrorCodeEnum(String errorCode, String errorMsg) {this.errorCode = errorCode;this.errorMsg = errorMsg;}@Overridepublic String getErrorCode() {return errorCode;}public void setErrorCode(String errorCode) {this.errorCode = errorCode;}@Overridepublic String getErrorMsg() {return errorMsg;}public void setErrorMsg(String errorMsg) {this.errorMsg = errorMsg;}}

最后在业务代码中抛出 CustomerBizException即可。如下:

@RestController
@RequestMapping("/exception")
public class ExceptionController {@GetMapping("/test")public JsonResult<String> exceptionTest(String num) {if (num.equals("22")) {throw new CustomerBizException(CustomerErrorCodeEnum.CUSTOMER_AUDIT_REPEAT);}}

image.png

spring:# 出现错误时, 直接抛出异常(便于异常统一处理,否则捕获不到404)mvc:throw-exception-if-no-handler-found: true# 不要为工程中的资源文件建立映射web:resources:add-mappings: false

如果你是Spring Boot 2.4.0 以下的版本,配置需要这样写

spring:# 出现错误时, 直接抛出异常(便于异常统一处理,否则捕获不到404)mvc:throw-exception-if-no-handler-found: true# 不要为工程中的资源文件建立映射resources:add-mappings: false

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.4.0-Configuration-Changelog

有了这个全局异常处理,就有多种玩法了。可以写一个参数的校验的工具类。比如这样子的,不用自己写if…return;

欢迎评论私信交流!!

也可以看看sprainkle大佬的这两篇文章
https://www.jianshu.com/p/3f3d9e8d1efa
https://www.jianshu.com/p/179daa24ef52

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/64955.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

王者转服务器显示未登录,王者荣耀账号异常请重新登录怎么解决呢 账号异常请重新登录是什么原因[多图]...

王者荣耀账号异常请重新登录怎么才能解决&#xff1f;账号登陆异常还是非常少见的&#xff0c;这次更新后好玩玩家都出现了账号登陆异常请重新登陆。下面就为大家带来详细的解决方案&#xff0c;让你轻松解决。 王者荣耀账号异常请重新登录解决方法&#xff1a; 1、 出现这个情…

微信提醒对方账号异常应该怎么办

微信提醒对方账号异常?平常我们在操作微信时,哪些行为会被界定为操作异常呢?简单的讲,就是用户一般不会去做的行为就会被界定为操作异常,下面是整理的微信提醒对方账号异常教程,一起去看看吧! 微信提醒对方账号异常 1.在软件上生成的号被检测是非法注册 2.经常进行集赞…

异常分发(用户异常)

文章目录 内容回顾&#xff1a;用户异常的处理流程&#xff1a;总结 内容回顾&#xff1a; 异常如果发送在内核层&#xff0c;处理起来比较简单&#xff0c;因为异常处理函数也在0环&#xff0c;不用切换堆栈&#xff0c;但是如果异常发生在3环&#xff0c;就意味着必须要切换…

账号异常分析

看了一篇文章&#xff0c;感觉全篇都是干货。具体参见如何分析账号异常&#xff1f;看这里&#xff01; 购物、支付、游戏、社交软件帐号被盗的新闻屡见不鲜&#xff0c;危害之大可想而知! 常用的网络帐号&#xff0c;主机帐号被盗可能会造成信息泄露&#xff0c;资金被转走&a…

用户账号异常分析

看了一篇文章&#xff0c;感觉全篇都是干货 学习ing 转载自https://baijiahao.baidu.com/s?id1570344881808397&wfrspider&forpc 购物、支付、游戏、社交软件帐号被盗的新闻屡见不鲜&#xff0c;危害之大可想而知! 常用的网络帐号&#xff0c;主机帐号被盗可能会造…

Google邮箱账号登陆存在异常活动怎么办?

注册或是其他QU道弄好谷歌账号之后&#xff0c;就可以使用谷歌账号登录了。登陆使用一段时间&#xff0c;过段时间就会提醒你“尝试登录的账户有异常活动&#xff0c;”这时候输入你绑定的号码不管用&#xff0c;然后换号码&#xff0c;国内手机号都不管用。 谷歌账号登陆异常此…

ChatGPT 对手 Claude2 发布新版本,代码、GRE 成绩超越 GPT-4,使用体验如何?

Claude 2的更新。Claude作为 ChatGPT的竞争对手,其版本迭代确实值得关注。 从您的描述来看,Claude 2在语言理解和知识推理方面有所提升,并提供了免费试用和合理定价,这些确实都是重要的升级。 同时,我注意到您提到它被许多网友称为“ChatGPT 最强竞品”,这可能过于主观和绝对化…

GPT-4最强竞争对手Claude 2震撼发布,据说超过GPT-4?

OpenAI 发布了 GPT-4 的 API 和令人兴奋的“最强插件”代码解释器&#xff0c;这无疑给竞争对手们敲响了警钟。而最近&#xff0c;Anthropic 旗下的 Claude 揭开了它的第二代面纱。免费使用Claude 2请加微信wyxyellow 相较于之前的版本&#xff0c;Claude 2 在代码、数学和推理…

GPT-4 最强竞争对手,Claude 杀疯了!

公众号关注 “GitHubDaily” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 在今年早些时候&#xff0c;ChatGPT、Bard、Claude 等大语言模型&#xff0c;在 AI 领域呈三权鼎立之势&#xff0c;无人能出其右&#xff0c;被视为是能力表现最为卓越的 3 款 AI 聊天机器…

chatgpt赋能Python-python_conut

Python Count - 用于计数的重要功能 Python是一种广泛使用的高级编程语言&#xff0c;自称为简单、易学、易读和易推广&#xff0c;适合新手和高级程序员使用。在这篇文章中&#xff0c;我们将讨论Python中一个非常重要的功能 - Count&#xff08;计数&#xff09;。 什么是P…

chatgpt赋能python:Python中怎么分段?

#Python中怎么分段&#xff1f; ##介绍 Python是一种高级编程语言&#xff0c;它被广泛用于各种任务&#xff0c;包括数据分析、Web开发、人工智能、游戏开发等等。对于Python的初学者来说&#xff0c;其中有一个重要的问题是如何正确地分段。在这篇文章中&#xff0c;我们将…

【案例】Python金融分析-CAPM模型对股票进行分析

前言 在2009年巴菲特给股东们的信中写道&#xff1a; Investors should be skeptical of history-based models. Constructed by a nerdy-sounding priesthood using esoteric terms such as beta, gamma, sigma, and the like, these models tend to look impressive. Too of…

微软 Build 2023:人工智能重新定义软件开发与工作的未来

2023年5月23日&#xff0c;美国华盛顿州西雅图 —— 微软年度开发者大会Build 2023在西雅图开幕&#xff0c;面对当今由AI引领的技术趋势&#xff0c;微软向超过20万名注册参会的开发者集中展示人工智能如何给软件开发的对象、过程和工具带来巨大变革&#xff0c;并重新定义工作…

chatgpt赋能python:Python到底要怎么删干净?

Python 到底要怎么删干净&#xff1f; 介绍 Python 是一门广泛使用的编程语言。由于其简单易学、可扩展和跨平台特性&#xff0c;目前越来越多的程序员和公司开始在其项目中采用 Python。然而&#xff0c;由于初学者较多&#xff0c;可能会遇到 Python 删干净的问题&#xff…

chatgpt赋能python:Python怎么删除库

Python怎么删除库 如果你有一些不再需要的Python库&#xff0c;可能会想要将它们删除以释放硬盘空间或简化项目环境。那么&#xff0c;Python怎么删除库呢&#xff1f; 一级标题&#xff1a;使用pip命令卸载库 Python语言中&#xff0c;有一个常用的工具pip&#xff0c;它是…

chatgpt赋能python:Python彻底删除指南:保障您的数据不被误操作删除

Python彻底删除指南&#xff1a;保障您的数据不被误操作删除 Python是一种简单易学且功能强大的编程语言&#xff0c;因此被广泛应用于各种应用程序的开发和数据分析。然而&#xff0c;当我们在使用Python时&#xff0c;难免会遇到删除数据的情况。 误操作删除数据可谓是一场…

chatgpt赋能python:Python如何删除数据:完整指南

Python如何删除数据&#xff1a;完整指南 如果你是一名Python开发者&#xff0c;你肯定需要删除不必要的数据。删除数据是很重要的&#xff0c;因为它可以帮助你保持你的数据库或文件系统的清洁和可读性。本文将详细介绍Python中删除数据的各种方法&#xff0c;让你轻松地管理…

chatgpt赋能python:Python彻底删除指南:为什么需要彻底删除Python?

Python彻底删除指南&#xff1a;为什么需要彻底删除Python&#xff1f; Python是一种高级编程语言&#xff0c;它广泛用于各种应用程序的开发。但是&#xff0c;对于某些开发者来说&#xff0c;可能需要从他们的计算机中彻底删除Python。这可能是因为他们需要将Python版本更新…

chatgpt赋能python:如何彻底删除Python软件?

如何彻底删除Python软件&#xff1f; Python是一种非常流行的编程语言&#xff0c;经常被用于开发应用程序、网站、数据分析和机器学习等。但是&#xff0c;有时候你可能需要删除Python软件&#xff0c;可能是因为你需要卸载旧版本的Python&#xff0c;或者因为你需要清理磁盘…

chatgpt赋能python:Python如何彻底删除软件

Python如何彻底删除软件 Python是一种非常流行的高级编程语言&#xff0c;可用于构建各种不同类型的软件和网络应用程序。但是&#xff0c;在某些情况下&#xff0c;我们可能需要卸载不再需要的软件&#xff0c;并希望能够从系统中完全删除软件。在本文中&#xff0c;我们将探…