在进行设置自己的异常捕获器之前,我先介绍一下怎么记录日志,记录日志可以使用SpringBoot内部的框架logback,不需要引坐标.如果想要生成日志文件方便检查的话就需要配置文件(最好是按天生成日志,可以根据日志查看程序的执行过程)废话不多说直接上代码!!!
在resources添加配置文件:logback-spring.xml
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>logbackcontextName>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%npattern>
encoder>
appender>
<appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<Prudent>falsePrudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>logs/consumer/%d{yyyy-MM-dd}.logFileNamePattern>
rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%npattern>
encoder>
appender>
<root level="info">
<appender-ref ref="console"/>
<appender-ref ref="logFile"/>
root>
configuration>
配置加好后,这个时候重新启动项目,如果在项目列表中发现多了一个文件:
那么说明你的配置已经生效了,那么接下来就开始全局异常捕获器的编写:
首先写一个服务的接口:
/**
* @description 服务的接口
* @author zhangfc
* @2021-04-22 08:38:25
*
*/
public interface BaseErrorInfoInterface {
/**
* 错误码
* @return
*/
public String getResultCode();
/**
* 错误信息
* @return
*/
public String getResultMsg();
}
接下来写一个异常信息的枚举将错误信息进行分类:
/**
*
* @description 异常信息的枚举
* @date 2021-04-22 08:58:01
* @author zhangfc
* @version V0.1
*
*/
public enum ExceptionEnum implements BaseErrorInfoInterface {
SUCCESS("2000","成功!"),
NUM_ERROR("4000","数据计算错误!"),
NULL_ERROR("4001","空指针异常"),
SYS_ERROR("5000","服务器出现错误!"),
SYS_BUSY("5001","服务器繁忙!")
;
//返回的错误状态码
private final String resultCode;
//返回的错误状态信息
private final String resultMsg;
ExceptionEnum(String code,String msg){
this.resultCode = code;
this.resultMsg = msg;
}
@Override
public String getResultCode() {
return this.resultCode;
}
@Override
public String getResultMsg() {
return this.resultMsg;
}
}
接下来写一个自定义的数据传输类:
/**
* @author : zhangfc
* @version : V0.1
* @description : 自定义数据传输
* @date : 2021-04-22 09:22:07
*/
@Setter
@Getter
public class ResultResponse {
//响应码
private String code;
//响应信息
private String msg;
//响应结果
private Object result;
/**
* @return
* @description 成功
*/
public static ResultResponse success() {
return success(null);
}
/**
* @param data
* @return
* @description 成功
*/
public static ResultResponse success(Object data) {
ResultResponse resultResponse = new ResultResponse();
//响应信息加上成功状态码
resultResponse.setCode(ExceptionEnum.SUCCESS.getResultCode());
//响应信息加上成功状态信息
resultResponse.setMsg(ExceptionEnum.SUCCESS.getResultMsg());
//响应信息加上返回数据
resultResponse.setResult(data);
return resultResponse;
}
/**
* @description 失败
* @param baseErrorInfoInterface
* @return
*/
public static ResultResponse error(BaseErrorInfoInterface baseErrorInfoInterface) {
ResultResponse resultResponse = new ResultResponse();
resultResponse.setCode(baseErrorInfoInterface.getResultCode());
resultResponse.setMsg(baseErrorInfoInterface.getResultMsg());
resultResponse.setResult(null);
return resultResponse;
}
/**
* @description 失败
* @param code
* @param msg
* @return
*/
public static ResultResponse error(String code,String msg){
ResultResponse resultResponse = new ResultResponse();
resultResponse.setCode(code);
resultResponse.setMsg(msg);
resultResponse.setResult(null);
return resultResponse;
}
/**
* @description 失败
* @param msg
* @return
*/
public static ResultResponse error(String msg){
ResultResponse resultResponse = new ResultResponse();
resultResponse.setCode("-1");
resultResponse.setMsg(msg);
resultResponse.setResult(null);
return resultResponse;
}
@Override
public String toString() {
return JSONObject.toJSONString(this);
}
}
写一个自己定义的异常类,这个异常主要是在业务逻辑中手动抛出的异常,便于自己快速找到问题的所在:
/**
* @author zhangfc
* @description 自定义的异常类
* @date 2021-04-22 09:02:17
*/
public class VerbException extends RuntimeException implements Serializable {
//序列化
private static final long serialVersionUID = 1L;
//错误状态码
String errorCode;
//错误状态信息
String errorMsg;
public VerbException() {
super();
}
public VerbException(BaseErrorInfoInterface errorInfoInterface) {
super(errorInfoInterface.getResultCode());
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public VerbException(BaseErrorInfoInterface errorInfoInterface, Throwable cause) {
super(errorInfoInterface.getResultCode(), cause);
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public VerbException(String errorMsg) {
super(errorMsg);
this.errorMsg = errorMsg;
}
public VerbException(String errorCode, String errorMsg) {
super(errorCode);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public VerbException(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 synchronized Throwable fillInStackTrace() {
return this;
}
}
接下来写一个全局的异常捕获器用来捕获程序中出现的异常:
/**
*
* @description : 全局异常捕获器
* @author : zhangfc
* @date : 2021-04-21 22:34:34
* @version : V0.1
*
*/
@ControllerAdvice //ControllerAdvice 这个注解就是异常捕获器的注解用来拦截运行时出现的异常
public class MyExceptionHandler {
//日志记录
private static final Logger logger = LoggerFactory.getLogger(MyExceptionHandler.class);
/**
* @description 自定义的异常捕捉
* @param request
* @param verb
* @return
*/
@ExceptionHandler(value = VerbException.class)//这个注解是拦截的value中异常类型可以是多个当多个时格式是{A,B}中间以逗号间隔
@ResponseBody//结果以json格式返回
public ResultResponse verbExceptionHandler(HttpServletRequest request,VerbException verb){
logger.error("业务出现异常错误原因:{}",verb.getErrorMsg());
return ResultResponse.error(verb.getErrorCode(),verb.getErrorMsg());
}
/**
* @description 空指针异常处理
* @param request
* @param e
* @return
*/
@ExceptionHandler(value = NullPointerException.class)//这个注解是拦截的value中异常类型可以是多个
@ResponseBody//结果以json格式返回
public ResultResponse nullExceptionHandler(HttpServletRequest request,NullPointerException e) {
logger.error("空指针异常,异常原因:{}",e.getMessage());
return ResultResponse.error(ExceptionEnum.NULL_ERROR);
}
/**
* @description 捕捉其他的一些异常
* @param request
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)//这个注解是拦截的value中异常类型可以是多个
@ResponseBody//结果以json格式返回
public ResultResponse exceptionHandler(HttpServletRequest request,Exception e){
logger.error("出现其他异常:{}",e.getMessage());
return ResultResponse.error(ExceptionEnum.SYS_BUSY);
}
}
最后就开始验证之前所写的异常捕获器是否有效了:
我在controller层进行测试:
@RestController
@RequestMapping("/order")
public class OrderController {
//记录日志
private static final Logger logger = LoggerFactory.getLogger(OrderController.class);
@GetMapping("/findone/{id}")
public ResultResponse findOnebyId(@PathVariable("id") String id) {
//这里我人为的造出一个空指针异常
String ss = null;
ss.equals("ss");
return ResultResponse.success();
}
}
启动项目测试结果
说明自己的异常捕获器生效!!
接下来再抛出一个自定义的异常:
@RestController
@RequestMapping("/order")
public class OrderController {
//记录日志
private static final Logger logger = LoggerFactory.getLogger(OrderController.class);
@GetMapping("/findone/{id}")
public ResultResponse findOnebyId(@PathVariable("id") String id) {
//这里我人为的抛出一个人为异常
if ("1".equals(id)) {
throw new VerbException("-1", "业务出现错误");
}
return ResultResponse.success();
}
}
测试结果:
这样的错误信息即让自己能快速定位到错误,又能让别人看起来很舒服.