springboot2.1.1版本实现统一异常处理并记录到日志文件中

因业务的需要,需要实现对后端进行统一异常处理,并返回统一的返回值;并将异常信息需要保存到今天的文本日志中;冲冲冲,步骤如下,跟着我走就能实现:

第一步:

在springboot项目的resources目录下新建file文件,文件名为:logback-spring.xml该文件的目录如下:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>

    <appender name="consoleApp" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>
                %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
            </pattern>
        </layout>
    </appender>

    <appender name="fileInfoApp" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <encoder>
            <pattern>
                %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
            </pattern>
        </encoder>
        <!-- 滚动策略 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 路径 -->
            <fileNamePattern>./app_log/log/app.info.%d.log</fileNamePattern>
        </rollingPolicy>
    </appender>

    <appender name="fileErrorApp" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>
                %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n
            </pattern>
        </encoder>

        <!-- 设置滚动策略 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 路径 -->
            <fileNamePattern>app_log/log/app.err.%d.log</fileNamePattern>

            <!-- 控制保留的归档文件的最大数量,超出数量就删除旧文件,假设设置每个月滚动,
            且<maxHistory> 是1,则只保存最近1个月的文件,删除之前的旧文件 -->
            <MaxHistory>1</MaxHistory>

        </rollingPolicy>
    </appender>
    <root level="INFO">
        <appender-ref ref="consoleApp"/>
        <appender-ref ref="fileInfoApp"/>
        <appender-ref ref="fileErrorApp"/>
    </root>
</configuration>

这样就会在项目组的当前文件实现这个文件目录,每天还会生成两个文件一个是error文件,一个是info文件,后面统一异常的信息就会出现在这个error文件里面;

第二步:利用springboot的aop特性进行切入,首先pom文件增加如果代码

   <!--使用AspectJ方式注解需要相应的包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

第三步:新建Log接口类,代码如下:

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface Log {
}

这个的作用是自定义的一个注解,用于后面实现的功能是只需要我们在要实现统一异常的方法上加上@Log这个注解就可以实现.好了,接下来我们就利用aop来切进去了

第四步:新建切面类,我这里使用的是ViewApect.java类,代码如下:

@Aspect
@Component
public class ViewAspect {
    private static final Logger log= LoggerFactory.getLogger(ViewAspect.class);
    @Pointcut("@annotation(com.xxxx.demo.config.Log)")
    public void logPointcut(){}
    @Around("logPointcut()")
    public Object logHandler(ProceedingJoinPoint process) throws Throwable{
          String exception="";
        long startTime=System.currentTimeMillis();
        MethodSignature methodSignature= (MethodSignature) process.getSignature();
        Method method=methodSignature.getMethod();
        String methodName=method.getName();
        String className= method.getDeclaringClass().getName();
        Object[] args=process.getArgs();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        StringBuilder params=new StringBuilder();
        for (int i = 0; i < args.length; i++) {
            params.append(args[i].toString());
            params.append(";");
        }
        Object result= null;
        try {
            result = process.proceed();
            System.out.println(result);
        } catch (Exception throwable) {
            SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String catchtime=  df1.format(new Date());
            long costTime=System.currentTimeMillis()-startTime;
            log.error("请求时间:{},请求耗时:{},请求类名:{},请求方法:{},请求参数:{},请求结果:{}",catchtime,costTime,className,methodName,params.toString(),throwable.getClass()+":"+throwable.getMessage());
             for (int i=0;i<throwable.getStackTrace().length;i++){
            log.error(String.valueOf(throwable.getStackTrace()[i]));
             }
         }
        finally {

            Map<String,Object>map=new HashMap<>();

           return map;
       }


   }
}

这里的finally里面的返回值,这个根据你们需要进行改造,好了,这样就可以实现了,只需要在方法上面增加@Log注解,就可以了;

注意:我这里用的是throwable.getStackTrace()这个方法来获取异常信息,这是个坑来着,这个返回的是数组来着,需要对该数组进行遍历,我看网上使用的很多都是throwable.getMessage()这个,这个只能获取到报错信息的第一行,虽然说这个能知道报错的大概信息,但是对于调试的话就很难实现了;因为没有具体的异常信息;而.getStackTrace()这个恰恰就刚好从异常的第二行开始进行的,所以结合getMessage()和getStackTrace()就可以实现完整的异常信息的记录;之前使用的是throwable.getCause().getMessage(),这个方法一搞,返回直接500了,所以这个不可取;调试到最后使用的是这个方法

ps:如果有更好的方法,欢迎交流.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值