本章结束后对应的节选代码文件:
Gangbb-Vue-08-ResAndException
项目地址:
https://github.com/Gang-bb/Gangbb-Vue
历史遗留TODO:
- 第四章
- 登录日志还未实现。(到登录和权限模块完成)
LogAspect
从缓存获取当前的用户信息使用模拟的数据(到登录和权限模块完成)
本章将留下TODO:
- 无
本章将解决TODO:
- 无
这章节若依讲得还算清楚,不过也不难。大概的具体思路就是:
-
定义一个统一返回对象
ApiRestResponse
(若依中是
AjaxResult
),用来统一请求成功和请求失败返回的json信息。 -
在我们的应用中给我们希望一些异常情况,抛出时为我们自定义的异常
ApiException
,有自己的状态码和自定义message,这样方便排错和易于管理。 -
全局异常处理
GlobalExceptionHandler
,拦截你想拦截的异常,并调用返回
ApiRestResponse
。
1. 定义统一返回对象
若依中是
AjaxResult
类。
/**
* @author : Gangbb
* @ClassName : ApiRestResponse
* @Description : 统一结果返回
* @Date : 2021/3/9 19:35
*/
public class ApiRestResponse extends LinkedHashMap<String, Object>
{
private static final long serialVersionUID = 1L;
/** 系统自定义状态码 */
public static final String CODE = "code";
/** 返回信息 */
public static final String MSG_TAG = "msg";
/** 数据对象 */
public static final String DATA_TAG = "data";
/** 请求url */
public static final String REQUEST_TAG = "request";
/** 系统成功 默认code 20000 */
public static final String SYSTEM_SUCCESS = "20000";
/** 系统默认异常 默认code 50000 */
public static final String SYSTEM_FAIL = "B0001";
/**
* 初始化一个新创建的 ApiRestResponse 对象(成功时使用)
*
* @param code 状态码
* @param msg 返回内容
* @param data 数据对象
*/
public ApiRestResponse(String code, String msg, Object data)
{
super.put(CODE, code);
super.put(MSG_TAG, msg);
if (StringUtils.isNotNull(data))
{
super.put(DATA_TAG, data);
}
}
/**
* exception专用返回(错误时使用)
* @param code 系统自定义状态码
* @param msg 错误信息
*/
public ApiRestResponse(String code, String msg)
{
super.put(CODE, code);
super.put(MSG_TAG, msg);
super.put(REQUEST_TAG, ServletUtils.getRequest().getRequestURI());
}
/**
* 返回成功数据
*
* @return 成功消息
*/
public static ApiRestResponse success()
{
return ApiRestResponse.success(null);
}
/**
* 返回成功数据
*
* @return 成功消息
*/
public static ApiRestResponse success(Object data)
{
String message = "操作成功(success)";
return new ApiRestResponse(SYSTEM_SUCCESS, message, data);
}
/**
* 返回错误消息
* @param code 错误信息
* @return
*/
public static ApiRestResponse error(String code)
{
return new ApiRestResponse(code, MessageUtils.getMessageByCode(code));
}
/**
* 返回错误消息
* @param code 系统自定义状态码
* @param msg 错误信息
* @return
*/
public static ApiRestResponse error(String code, String msg)
{
return new ApiRestResponse(code, msg);
}
}
2. 自定义异常类及错误码规范
若依中的实现是,按几个大类根据相应场景有不同的自定义异常,个人不太喜欢这种实现方案,感觉很繁琐,日后有点难维护!如图:
我自己的实现思路是只定义一个自定义异常类,抛出时传入不同的状态码 ,通过不同状态码获取到
messages.properties
中的不同错误信息,只要对状态码有一个统一定义规范就能有效区分不同异常进行管理
此处用
阿里巴巴
定义状态码的思想,感觉还不错:
2.1 自定义异常类ApiException
若依中是
BaseException
类
public class ApiException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
private String code;
/**
* 错误消息
*/
private String message;
public ApiException(String code, String message)
{
this.code = code;
this.message = message;
}
public ApiException(String code)
{
this(code, MessageUtils.getMessageByCode(code));
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
2.2 错误状态码示例
3. 全局异常处理
暂时先捕捉这几个异常日后有什么再补上
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 自定义异常捕捉
*/
@ExceptionHandler(ApiException.class)
public ApiRestResponse baseException(ApiException e)
{
return ApiRestResponse.error(e.getCode(), e.getMessage());
}
/**
* 基础异常捕捉
*/
@ExceptionHandler(Exception.class)
public ApiRestResponse exception(Exception e)
{
log.error("Exception: ", e);
return ApiRestResponse.error(e.getMessage());
}
}
4. 测试
本节所有测试例子都在
TestExceptionController
中
成功示例:
异常示例: