SpringCloud统一异常及日志处理(一)
- 前言
- 一、异常处理
- 二、日志处理
- 1.引入依赖
- 2.配置log4j2
- 总结
前言
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,简单来说,一个SpringCloud包含了N个SpringBoot。在各项服务之间相互分离为不同的jar包的时候,各服务内部异常和日志的统一处理将会显得尤为重要和困难,在这里笔者将利用自己的实际项目举例,记录当前项目中是如何进行以上所述操作的。
笔者在阅读较多类似文章后,总结出一套较为适合本项目的处理机制,各位看官酌情参考。如果各位有更好的解决思路,还请不吝赐教。
一、异常处理
由于我在系统中单独做了数据接口,所以以下将会由该服务举例,其他服务类似。
- 将每个服务中涉及到的所有的状态码单独划分为一个枚举体,BaseStatus。
public enum BaseStatus {
SYSTEM_ERROR(5100, "系统错误"),
PARAM_ERROR(5101, "参数错误"),
INSERT_FAIL(5102,"新增失败"),
DELETE_FAIL(5103,"删除失败"),
UPDATE_FAIL(5104,"更新失败"),
SELECT_FAIL(5105,"查询失败")
;
private final Integer status;
private final String message;
public Integer getStatus() {
return this.status;
}
public String getMessage() {
return this.message;
}
BaseStatus(Integer status, String message) {
this.status = status;
this.message = message;
}
}
- 对服务进行异常分类,这里我只展示基类,其他异常类extends BaseException
public class BaseException extends RuntimeException{
private static final long serialVersionUID = -3872700496475775551L;
private final BaseStatus baseStatus;
private final String extMsg;
public BaseException(BaseStatus baseStatus, String extMsg) {
super(baseStatus.getMessage() + (extMsg == null ? "" : ('@' + extMsg)));
this.baseStatus = baseStatus;
this.extMsg = extMsg;
}
public BaseStatus getBaseStatus() {
return this.baseStatus;
}
public String getExtMsg() {
return extMsg;
}
}
- 单独建立一个异常的处理类,针对不同的异常进行不同的处理。这里要添加@RestControllerAdvice的注解,所有控制器中的抛出异常将会由该类进行处理。 @ExceptionHandler注解将会用来选择哪些异常进入到哪些方法中,这里进行简单举例。
@ResponseBody
@RestControllerAdvice
public class ExceptionsHandler {
@ExceptionHandler({UserException.class})
public <T extends BaseException> ResponseEntity<JSONObject> warnException(T exception) {
log.warn(exception);
return new ResponseEntity<JSONObject>(HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler({Exception.class, Error.class})
public <T extends Throwable> ResponseEntity<JSONObject> errorException(T exception) {
log.error(exception);
return new ResponseEntity<JSONObject>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
二、日志处理
1.引入依赖
maven依赖如下,这里使用了log4j2,使用log4j2时需要在其他依赖中排除:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.4.1</version>
</dependency>
2.配置log4j2
log4j2的具体配置请参考官方文档,这里需要重点提的是,我的日志选择了异步处理的方式,当系统抛出异常后,首先将会交由log4j2进行收集,然后将会将异常信息通过Socket发送到logstash,进行第二步的收集、解析、转换,之后将会通过管道发送到Elasticsearch,以达到日志的统一处理的目的。ELK stack将会在下一章进行详细说明,这里暂时先不赘述了:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} -%5p ${PID:-} [%15.15t] %-30.30C{1.} : %m%n</property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${LOG_PATTERN}" />
</Console>
<Socket name="logstash-tcp" host="10.159.xxx.xxx" port="8501" protocol="TCP">
<PatternLayout pattern="${LOG_PATTERN}" />
</Socket>
</Appenders>
<Loggers>
<!-- 如果使用<asyncRoot> 或 <asyncLogger>,includeLocation="true"是必须要设置才会有类路径等一些信息打印出来 -->
<AsyncLogger name="com.MultiTec.HikAc.OracleService" level="warn" includeLocation="true" >
<appender-ref ref="logstash-tcp" />
</AsyncLogger>
<Root level="INFO">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
总结
以上就是今天要分享的内容,好的系统一定是多种优秀的工具相互搭配,互相成就,发挥出最好的效果来,作为程序员,不仅要对代码有足够高的敏感性,更要对不同的实现方式、工具的组合使用永远抱有充分的好奇心,如果您喜欢我的文章,请点赞收藏,如果您有更好的实现思路,请不吝赐教。