当程序发生错误时,返回错误内容,会搞乱了调用者代码。调用者必须在调用之后即刻检查错误,不幸的是,这个步骤很容易被遗忘。
建议在发生错误时抛出异常,调用代码很整洁,绮逻辑不会被错误处理搞乱。
————–《代码整洁之道》
SpringMVC提供了一个全局异常处理机制,使用比较简单,网上也有很多介绍的文章,本文主要举例说明在我们项目组是如何使用的。
完整的引入全局异常处理机制,包含以下四个类:
- CustomRestExceptionHandler(继承ResponseEntityExceptionHandler)用来监听处理全局异常
- CustomException(继承RuntimeException)自定义异常类
- ExceptionEnum 异常枚举类
- ErrorDTO 异常响应DTO,规范异常发生时的接口返回值
CustomException和ExceptionEnum的配合使用,主要是为了统一管理所有的异常,这对异常码的统一与复用十分重要
异常处理逻辑:
1、开发人员在ExceptionEnum中定义列举所有的异常(异常码、异常信息),这样主要是方便管理所有异常码
2、在代码错误处理逻辑中,new一个CustomException并throw,创建CustomException的参数建议使用ExceptionEnum的值
3、异常如果没有没catch并处理的话,会抛到controller处理层,这时会被CustomRestExceptionHandler捕获到
4、CustomRestExceptionHandler将异常封装到ErrorDTO,并作为接口响应值返回给调用接口者
使用一个简单的工程来举例说明
CustomRestExceptionHandler
使用@ControllerAdvice注解声明全局异常处理类,使用@ExceptionHandler注解声明处理自定义异常,使用@Override覆盖通用异常处理
1 | package com.markey.markeyauth.errorhandle; |
自定义异常类
自定义异常类包括三个参数:请求响应状态码,异常码和异常信息(可根据工程实际情况修改)
1 | package com.markey.markeyauth.errorhandle; |
ExceptionEnum 异常枚举类
异常枚举类和自定义异常类配合使用,参数也是三个:请求响应状态码,异常码和异常信息
1 | package com.markey.markeyauth.errorhandle; |
异常响应DTO
统一接口返回body体的内容,方便接口调用者处理,这里定义了两个字段error_code、error_desc(对应了异常枚举值中的错误码和错误信息)
1 | package com.markey.markeyauth.errorhandle; |
在一个简单的controller中测试一下:
1 | package com.markey.markeyauth.controller; |
测试一下
启动springboot
使用postman访问接口get http://localhost:8080/users/ 预期结果:返回json,包含error_code和error_desc
效果如下:
使用post http://localhost:8080/users/ 预期结果:返回json,包含error_code和error_desc
因为controller自定义了get方法,所以post请求是方法的,在CustomRestExceptionHandler覆盖了原生的请求方法非法处理
效果如下:
备注
上述举例主要是针对restful接口的异常处理,如果想要在捕获异常后返回ModelAndView,而不是json消息,可以让CustomRestExceptionHandler继承HandlerExceptionResolver,并覆盖resolveException()方法