如何优雅的处理异常,并将异常优雅的封装到返回中进行统一返回?如果让我们专注于业务代码的书写呢,这篇就够了,加油。一起干饭!
本章主要内容
- 统一异常
- 统一返回
1.统一异常处理
原理:在独立的某个地方,比如单独一个类,定义一套对各种异常的处理机制,然后在该类的签名加上注解@ControllerAdvice,统一对 不同阶段的、不同异常 进行处理。这就是统一异常处理的原理。
1.1 异常按阶段进行分类
异常按阶段进行分类,大体可以分成:进入Controller前的异常 和 Service 层异常,具体可以参考下图:

1.2 全局异常处理编码
定义基础接口类、枚举类、自定义异常类、全局异常处理类、统一返回类
- 自定义基础接口类
package com.dylan.mall.error;
/**
* @author Administrator
*/
public interface BaseException {
/** 错误码 */
String getResultCode();
/** 错误描述*/
String getResultMsg();
}
- 自定义枚举类
package com.dylan.mall.error;
/**
* @author Administrator
*/
public enum BaseExceptionEnum implements BaseException {
// 数据操作错误定义
SUCCESS("200", "成功!"),
BODY_NOT_MATCH("400","请求的数据格式不符!"),
SIGNATURE_NOT_MATCH("401","请求的数字签名不匹配!"),
NOT_FOUND("404", "未找到该资源!"),
INTERNAL_SERVER_ERROR("500", "服务器内部错误!"),
SERVER_BUSY("503","服务器正忙,请稍后再试!")
;
/** 错误码 */
private String resultCode;
/**
* 错误描述
*/
private String resultMsg;
BaseExceptionEnum(String resultCode, String resultMsg) {
this.resultCode = resultCode;
this.resultMsg = resultMsg;
}
@Override
public String getResultCode() {
return resultCode;
}
@Override
public String getResultMsg() {
return resultMsg;
}
}
- 自定义异常类
package com.dylan.mall.error;
/**
* @author Administrator
*/
public class BizException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
protected String errorCode;
/**
* 错误信息
*/
protected String errorMsg;
public BizException() {
super();
}
public BizException(BaseException errorInfoInterface) {
super(errorInfoInterface.getResultCode());
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public BizException(BaseException errorInfoInterface, Throwable cause) {
super(errorInfoInterface.getResultCode(), cause);
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public BizException(String errorMsg) {
super(errorMsg);
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg) {
super(errorCode);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg, Throwable cause) {
super(errorCode, cause);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
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;
}
@Override
public String getMessage() {
return errorMsg;
}
@Override
public Throwable fillInStackTrace() {
return this;
}
}
- 自定义全局异常处理类
package com.dylan.mall.error;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
/**
* @author Administrator
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理自定义的业务异常
*
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = BizException.class)
@ResponseBody
public R bizExceptionHandler(HttpServletRequest req, BizException e) {
log.error("发生业务异常!原因是:{}", e.getErrorMsg());
return R.error(e.getErrorCode(), e.getErrorMsg());
}
/**
* 处理空指针的异常
*
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = NullPointerException.class)
@ResponseBody
public R exceptionHandler(HttpServletRequest req, NullPointerException e) {
log.error("发生空指针异常!原因是:", e);
return R.error(BaseExceptionEnum.BODY_NOT_MATCH);
}
/**
* 处理其他异常
*
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
public R exceptionHandler(HttpServletRequest req, Exception e) {
log.error("未知异常!原因是:", e);
return R.error(BaseExceptionEnum.INTERNAL_SERVER_ERROR);
}
}
统一异常配置后,如果有异常就会走这里,那么,为什么会走这里呢?以及异常处理器是什么原理呢?下次补充。
1.3 如何优雅的判定异常情况并抛异常。
2.统一返回处理
- 自定义数据格式
package com.dylan.mall.error;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class R {
/**
* 响应代码
*/
private String code;
/**
* 响应消息
*/
private String message;
/**
* 响应结果
*/
private Object result;
public R(BaseException baseException) {
this.code = baseException.getResultCode();
this.message = baseException.getResultMsg();
}
/**
* 成功
*
* @return
*/
public static R success() {
return success(null);
}
/**
* 成功
* @param data
* @return
*/
public static R success(Object data) {
return R.builder().code(BaseExceptionEnum.SUCCESS.getResultCode()).message(BaseExceptionEnum.SUCCESS.getResultMsg()).result(data).build();
}
/**
* 失败
*/
public static R error(BaseException baseException) {
return R.builder().code(baseException.getResultCode()).message(baseException.getResultMsg()).result(null).build();
}
/**
* 失败
*/
public static R error(String code, String message) {
return R.builder().code(code).message(message).result(null).build();
}
/**
* 失败
*/
public static R error(String message) {
return R.builder().code("-1").message(message).result(null).build();
}
@Override
public String toString() {
return JSONObject.toJSONString(this);
}
}
3. 异常处理器说明
3. java异常问题归集
不要以为每天把功能完成了就行了,这种思想是要不得的,互勉~!
网友评论