以前写过一篇全局异常抓取以及日志log使用的文章, 今天我们再来单独优化一下这个全局异常抓取,并结合统一的接口返回类。
首先,我们先定义一个错误码接口(其实是返回码接口),里面包含返回码和错误描述,BaseErrorInfoInterface.java :
/** * @Author:JCccc * @Description:此接口用于返回码枚举使用 * @Date: created in 15:11 2019/5/3 */ public interface BaseErrorInfoInterface { /** 错误码*/ String getResultCode(); /** 错误描述*/ String getResultMsg(); }
然后是整一个返回码枚举类,CommonEnum.java实现上面的接口:
import com.soelegant.elegantdemo.common.base.BaseErrorInfoInterface; /** * @Author:JCccc * @Description: * @Date: created in 15:13 2019/5/3 */ public enum CommonEnum implements BaseErrorInfoInterface { // 数据操作错误定义 SUCCESS("200", "成功!"), BODY_NOT_MATCH("400", "请求的数据格式不符!"), SIGNATURE_NOT_MATCH("401", "请求的数字签名不匹配!"), NOT_FOUND("404", "未找到该资源!"), INTERNAL_SERVER_ERROR("500", "服务器内部错误!"), SERVER_BUSY("503", "服务器正忙,请稍后再试!"), REQUEST_METHOD_SUPPORT_ERROR("40001","当前请求方法不支持"); /** * 错误码 */ private String resultCode; /** * 错误描述 */ private String resultMsg; CommonEnum(String resultCode, String resultMsg) { this.resultCode = resultCode; this.resultMsg = resultMsg; } @Override public String getResultCode() { return resultCode; } @Override public String getResultMsg() { return resultMsg; } }
然后是响应接口的返回值类,ResultBody.java:
/** * @Author:JCccc * @Description: * @Date: created in 15:19 2019/5/3 */ public class ResultBody { /** * 响应代码 */ private String code; /** * 响应消息 */ private String message; /** * 响应结果 */ private Object result; public ResultBody() { } public ResultBody(BaseErrorInfoInterface errorInfo) { this.code = errorInfo.getResultCode(); this.message = errorInfo.getResultMsg(); } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Object getResult() { return result; } public void setResult(Object result) { this.result = result; } /** * 成功 * * @return */ public static ResultBody success() { return success(null); } /** * 成功 * @param data * @return */ public static ResultBody success(Object data) { ResultBody rb = new ResultBody(); rb.setCode(CommonEnum.SUCCESS.getResultCode()); rb.setMessage(CommonEnum.SUCCESS.getResultMsg()); rb.setResult(data); return rb; } /** * 失败 */ public static ResultBody error(BaseErrorInfoInterface errorInfo) { ResultBody rb = new ResultBody(); rb.setCode(errorInfo.getResultCode()); rb.setMessage(errorInfo.getResultMsg()); rb.setResult(null); return rb; } /** * 失败 */ public static ResultBody error(String code, String message) { ResultBody rb = new ResultBody(); rb.setCode(code); rb.setMessage(message); rb.setResult(null); return rb; } /** * 失败 */ public static ResultBody error( String message) { ResultBody rb = new ResultBody(); rb.setCode("-1"); rb.setMessage(message); rb.setResult(null); return rb; } @Override public String toString() { return JSONObject.toJSONString(this); } }
OK,到此关于返回码的东西以及大致完毕,我们现在开始写关于异常捕捉的。
首先写一个异常类继承RuntimeException, BizException.java:
/** * @Author:JCccc * @Description: * @Date: created in 15:18 2019/5/3 */ public class BizException extends RuntimeException { private static final long serialVersionUID = 1L; /** * 错误码 */ protected String errorCode; /** * 错误信息 */ protected String errorMsg; public BizException() { super(); } public BizException(BaseErrorInfoInterface errorInfoInterface) { super(errorInfoInterface.getResultCode()); this.errorCode = errorInfoInterface.getResultCode(); this.errorMsg = errorInfoInterface.getResultMsg(); } public BizException(BaseErrorInfoInterface 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; } public String getMessage() { return errorMsg; } @Override public Throwable fillInStackTrace() { return this; } }
接着是,全局异常Handler, GlobalExceptionHandler.java:
/** * @Author:JCccc * @Description: * @Date: created in 15:29 2019/5/3 */ @ControllerAdvice public class GlobalExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 处理自定义的业务异常 * @param req * @param e * @return */ @ExceptionHandler(value = BizException.class) @ResponseBody public ResultBody bizExceptionHandler(HttpServletRequest req, BizException e){ logger.error("发生业务异常!原因是:{}",e.getErrorMsg()); return ResultBody.error(e.getErrorCode(),e.getErrorMsg()); } /** * 处理空指针的异常 * @param req * @param e * @return */ @ExceptionHandler(value =NullPointerException.class) @ResponseBody public ResultBody exceptionHandler(HttpServletRequest req, NullPointerException e){ logger.error("发生空指针异常!原因是:",e); return ResultBody.error(CommonEnum.BODY_NOT_MATCH); } /** * 处理请求方法不支持的异常 * @param req * @param e * @return */ @ExceptionHandler(value =HttpRequestMethodNotSupportedException.class) @ResponseBody public ResultBody exceptionHandler(HttpServletRequest req, HttpRequestMethodNotSupportedException e){ logger.error("发生请求方法不支持异常!原因是:",e); return ResultBody.error(CommonEnum.REQUEST_METHOD_SUPPORT_ERROR); } /** * 处理其他异常 * @param req * @param e * @return */ @ExceptionHandler(value =Exception.class) @ResponseBody public ResultBody exceptionHandler(HttpServletRequest req, Exception e){ logger.error("未知异常!原因是:",e); return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR); } }
这里可以手动配置自己想抓取的异常以及处理返回码。
接着写个Controller来模拟一下异常抛出,抓取,使用统一返回码,UserController.java:
/** * @Author:JCccc * @Description: * @Date: created in 15:50 2019/5/20 */ @RestController @RequestMapping("/user") public class UserController { @GetMapping("/test") public boolean test() { System.out.println("开始..."); //这里故意造成一个异常,并且不进行处理 Integer.parseInt("abc123"); return true; } @GetMapping("/testNull") public boolean testNull() { System.out.println("开始..."); //这里故意造成一个空指针的异常,并且不进行处理 String str=null; str.equals("111"); return true; } @PostMapping("/testBizException") public boolean testBizException() { System.out.println("开始..."); //如果姓名为空就手动抛出一个自定义的异常! String userName=null; if(userName==null){ throw new BizException("-1","用户姓名不能为空!"); } return true; } @GetMapping("/testSuccess") public ResultBody testSuccess(){ Map<String,String> map=new HashMap<>(); map.put("A","a"); map.put("B","b"); map.put("C","c"); return ResultBody.success(map); } @RequestMapping("/testError") public ResultBody testError(){ return ResultBody.error("099","错误错误错误"); } }
OK,接口的调用就不一一展示了,到此。