平时经常在代码里面

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

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

还是看代码吧!
首先是定义了一个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);}}

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

统一异常处理 GlobalExceptionHandler相关推荐

  1. ssm 异常捕获 统一处理_SSM 统一异常处理

    SSM 统一异常处理 spring创建中, 处理异常可以使用try-cache处理, 也可以使用spring提供的统一异常处理 在spring中, 统一处理异常有2中方式 注解方式 @Exceptio ...

  2. Spring Boot中Web应用的统一异常处理

    为什么80%的码农都做不了架构师?>>>    我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛 ...

  3. trycatch抛出异常_Java生鲜电商平台架构中,如何统一异常处理及架构实战

    补充说明:本文讲得比较细,所以篇幅较长.请认真读完,希望读完后能对统一异常处理有一个清晰的认识. 背景 软件开发过程中,不可避免的是需要处理各种异常,就我自己来说,至少有一半以上的时间都是在处理各种异 ...

  4. Springboot对web应用的统一异常处理

    我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来 ...

  5. controller方法要trycatch吗_拜托,别再满屏try catch了,试试统一异常处理吧

    点击蓝色"JavaKeeper"关注我哟 加个"星标",一起成长,做牛逼闪闪的技术人 https://sourl.cn/SLnSKu 背景 软件开发过程中,不可 ...

  6. Java生鲜电商平台-统一异常处理及架构实战

    Java生鲜电商平台-统一异常处理及架构实战 补充说明:本文讲得比较细,所以篇幅较长. 请认真读完,希望读完后能对统一异常处理有一个清晰的认识. 背景 软件开发过程中,不可避免的是需要处理各种异常,就 ...

  7. log中文乱码 springboot_springboot + shiro 权限注解、统一异常处理、请求乱码解决

    springboot + shiro 权限注解.统一异常处理.请求乱码解决 前篇 后台权限管理系统 20200808新版本更新 版本升级及内容优化版本,改动内容: 版本更新,springboot从1. ...

  8. java异常处理封装_Java统一异常处理(配置文件集中化定义)

    0.前言 无论任何项目,都避免不了在运行期间出现的一些异常,并伴随着因业务逻辑的需要而给出相应的提示,使得系统变得更加友好,这类提示处理,我们统称为异常处理(exceptiona handling). ...

  9. SpringBoot实战(十):统一异常处理

    强烈推荐一个大神的人工智能的教程:http://www.captainbed.net/zhanghan [前言] 处理好异常对系统有很好的保护作用同时会大大提高用户的体验,对异常统一处理是一个非常实用 ...

最新文章

  1. 【怎样写代码】函数式编程 -- Lambda表达式(二):C#常用委托
  2. 2020 China Collegiate Programming Contest Changchun F - Strange Memory(dsu on tree + 位运算小技巧)
  3. Ubuntu下使用Anaconda安装opencv 解决无法读取视频
  4. python每行输出8个式子_求大神用python写出算术题的式子和结果。
  5. gaokao--选择开发什么项目
  6. 批次管理的质量跟踪案例分享_食品加工行业
  7. 第一季1:HI3518EV200的体验
  8. 修改默认共享内存tmpfs大小
  9. Object.assign()怎么用?
  10. web安全day35:Linux防火墙进阶
  11. 像写C#一样编写java代码
  12. 时间字段加一秒_面试Java后端却问我时间轮(Time Wheel)算法,面试官没想到我看过Dubbo源码!...
  13. 系统软件内部测试报告模板,软件系统测试报告模板-20210316091936.pdf-原创力文档...
  14. mac电脑出现“XXX” is damaged and can’t be opened. You should move it to the Trash
  15. 仿微博视频边下边播之滑动 TableView 自动播放
  16. 杭州大江东科目三路线经验分享
  17. 执行repo init提示error.GitError: manifests ls-remote解决方案
  18. 大数据预处理之数据集成
  19. MATHTYPE安装出现问题:无法打开要写入的文件;MathType打开word时“安全警告,宏已被禁用”;mathtype与AXmath不能同时使用
  20. Javaweb 聊天室

热门文章

  1. 锁分类 java_java锁的种类
  2. CIO如何控制老板提需求?CIO PLUS
  3. linux安装/卸载docker
  4. 云架构师:云端的舞者
  5. uni-app接入天域验证码
  6. 5G 时代音视频开发前景怎么样?音视频开发需要掌握哪些技术?
  7. CentOS中Xvfb的安装使用
  8. mysql哪些字段适合加索引_【数据库】mysql哪些字段适合加索引
  9. vue3.0生命周期函数
  10. java的switch支持包装类型吗?