自定义异常枚举类
枚举类用于定义自定义的异常类型,对应自定义错误码,错误信息,状态码
public enum ErrorCodeEnum {
USERINFO_EXCEPTION(10001,HttpStatus.INTERNAL_SERVER_ERROR,"UserInfo Exception"),
AUTHORIZATION_EXCEPTION(10002,HttpStatus.UNAUTHORIZED,"Authorization Exception"),
FILE_EXCEPTION(10003,HttpStatus.INTERNAL_SERVER_ERROR,"File Exception");
private int code;
private HttpStatus status;
private String msg;
ErrorCodeEnum(int code, HttpStatus status, String msg){
this.code=code;
this.status=status;
this.msg=msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
public HttpStatus getStatus() {
return status;
}
@Override
public String toString() {
return "ErrorCodeEnum{" +
"code=" + code +
", status=" + status +
", msg='" + msg + '\'' +
'}';
}
}
自定义异常类
自定义非受检异常类继承于RuntimeException=>Exceptiom=>Throwable,通过引入枚举类指定异常类型
public class CustomException extends RuntimeException{
private ErrorCodeEnum errorCodeEnum;
private int code;
private String msg;
private HttpStatus status;
public CustomException(ErrorCodeEnum errorCodeEnum){
this.errorCodeEnum=errorCodeEnum;
this.code= errorCodeEnum.getCode();
this.msg= errorCodeEnum.getMsg();
this.status=errorCodeEnum.getStatus();
}
public CustomException(ErrorCodeEnum errorCodeEnum,String additionalMsg){
this(errorCodeEnum);
this.msg=this.msg+':'+additionalMsg;
}
public ErrorCodeEnum getErrorCodeEnum() {
return errorCodeEnum;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
public HttpStatus getStatus() {
return status;
}
//重写父类getMessage方法,便于满足后期不同类型的异常类统一执行getMessage的需求
@Override
public String getMessage() {
return this.msg;
}
}
全局异常处理类
全局异常处理类对全局手动指定的错误类进行捕获,可以在捕获后处理、包装信息返回客户端,也可继续抛出异常通过AOP进行日志记录,也可在不继续抛出异常,返回客户端的同时,通过AOP的方法捕获进行异常信息的日志记录
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
/**
* 异常捕获处理,将异常信息包装于自定义结果类,以json返回给客户端
*/
@ExceptionHandler(CustomException.class)
public ResponseEntity<Result> handleFileException(CustomException ex){
return new ResponseEntity<>(new Result(ex.getCode(), ex.getMsg()),ex.getStatus());
}
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<Result> handlerRuntimeException(RuntimeException ex){
return new ResponseEntity<>(new Result(10000, ex.getClass().getSimpleName()+':'+ex.getMessage()),HttpStatus.INTERNAL_SERVER_ERROR);
}
}
自定义结果类
public class Result {
private int code;
private String msg;
private Map<String,?> data;
public Result(int code,String msg){
this.code=code;
this.msg=msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Map<String, ?> getData() {
return data;
}
public Result setData(Map<String, ?> data) {
this.data = data;
return this;
}
}
在上面的基础上通过AOP切入全局异常处理类,进行异常信息的日志记录
-
依赖引入
- pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion><!--排除默认日志框架--> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <!-- Spring AOP --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!-- log4j2--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency>
-
在src/main/resources下新建配置文件log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn"> <Appenders> <!-- 将日志输出到控制台 --> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="INFO"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
-
application.properties
#logging logging.config=classpath:log4j2.xml
-
全局异常类
@ControllerAdvice @ResponseBody public class GlobalExceptionHandler { /** * 异常处理 * AOP切入记录异常日志 */ @ExceptionHandler(CustomException.class) public ResponseEntity<Result> handleFileException(CustomException ex){ return new ResponseEntity<>(new Result(ex.getCode(), ex.getMsg()),ex.getStatus()); } @ExceptionHandler(RuntimeException.class) public ResponseEntity<Result> handlerRuntimeException(RuntimeException ex){ return new ResponseEntity<>(new Result(10000, ex.getClass().getSimpleName()+':'+ex.getMessage()),HttpStatus.INTERNAL_SERVER_ERROR); } }
-
AOP配置类
@Aspect @Component public class ExceptionAspect { private static final Logger logger = LogManager.getLogger(ExceptionAspect.class); //指定AOP切入的具体包和类 @Pointcut(value = "execution(* com.example.space.Advice.GlobalExceptionHandler.*(..))") public void LogPointcut() { } //方法执行后触发 @After("LogPointcut()") public void AfterLog(JoinPoint joinPoint) { //获取异常方法参数 Object[] args = joinPoint.getArgs(); // 获取异常发生的方法和位置信息 for (Object arg : args) { if (arg instanceof RuntimeException) { RuntimeException ex = (RuntimeException) arg; // 获取异常信息 String exceptionMessage = ex.getMessage(); // 获取异常发生的方法和位置信息 StackTraceElement[] stackTrace = ex.getStackTrace(); String exceptionMethod = (stackTrace.length > 0) ? stackTrace[0].getMethodName() : "Unknown Method"; String exceptionLocation = (stackTrace.length > 0) ? stackTrace[0].getClassName() + "." + exceptionMethod : "Unknown Location"; logger.error("Exception in method: " + exceptionLocation + ": " + exceptionMessage); } } } }