前言
以下内容保证都是来自生产一线的经验、客户真实反馈的需求,而不是自己妄想的理论。
仅适合有一定工程经验的人士查看,欢迎交流。
老规矩,有关@ControllerAdvice注解的使用,请自行google学习,这里我分享一下我在使用这个注解进行controller层异常统一处理的一些经验、心得。
前置知识
经典的web三层结构如下:
- dao(数据持久层,封装数据操作)
- service(封装业务逻辑)
- controller(对外服务层,参数检查、封装service结果)
因为controller层基本做的参数检查与结果封装的工作,因此每个controller方法的异常处理基本都是大同小异,无非就是:参数异常、权限异常等等,因此我们使用@ControllerAdvice来统一处理异常,减少代码的冗余。
代码品鉴
private static final Integer MAX_MESSAGE_LEN = 25;
private static final String DEFAULT_MESSAGE = "服务异常";
@ExceptionHandler(Throwable.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
public BaseResponse handleAny(HttpServletRequest req, Throwable ex) {
String message = ex.getMessage().length() > MAX_MESSAGE_LEN ? DEFAULT_MESSAGE : ex.getMessage();
return new BaseResponse(ErrorCode.SYSTEM_ERROR.getCode(), message);
}
复制代码
- 为什么需要一个handleAny方法?
controller层需要一个处理任何异常的方法,避免直接将异常返回给前端
- 为什么要限制message的最大长度?
controller层的异常,一般都是我们自定义的参数异常、权限异常等等,message清晰明了。
但是如果是controller之下的dao层抛出了异常,比如唯一键重复的数据库异常,那message就会令用户比较难懂,会让客户(客户完全不懂技术)觉得一脸懵逼,不知道当前出了啥问题。
我们这样转化一次,对于长度过长的,直接就变成一个简洁的:后端异常。用户看到这个错误信息,心里就有谱了。
需求原因
- 我是什么情况下实现了这么一份代码,对message进行再处理?
后端某一次抛出了唯一键索引冲突的异常,然后大佬看到这个异常信息觉得很懵逼。
- 用户提出这个需求的动机猜测:
大佬们都不太喜欢有超出自己控制、自己不懂的东西。
我在使用这个东西,出现问题我得知道是个啥原因,可以直接跟客服(产品)说,你们后端出bug了,赶紧修。
补充
BaseReponse:
一般controller层结果,我们都会封装成如下的一个统一格式, 便于前端处理:
{
"code":"异常编号",
"message":"返回附加信息,一般就是异常信息",
"data":"返回给前端的数据"
}
复制代码