Spring的Aop日志管理实现

1. 首先引入aop面向切面编程的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. logback的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--
       说明:
       1、日志级别及文件
           日志记录采用分级记录,级别与日志文件名相对应,不同级别的日志信息记录到不同的日志文件中
           例如:error级别记录到log_error_xxx.log或log_error.log(该文件为当前记录的日志文件),而log_error_xxx.log为归档日志,
           日志文件按日期记录,同一天内,若日志文件大小等于或大于2M,则按012...顺序分别命名
           例如log-level-2013-12-21.0.log
           其它级别的日志也是如此。
       3Appender
           FILEERROR对应error级别,文件名以log-error-xxx.log形式命名
           FILEWARN对应warn级别,文件名以log-warn-xxx.log形式命名
           FILEINFO对应info级别,文件名以log-info-xxx.log形式命名
           stdout将日志信息输出到控制上,为方便开发测试使用
    -->
    <!-- 自己的项目名字 -->
    <contextName>shop</contextName>
    <property name="LOG_PATH" value="D:\\logs2"/>
    <!--设置系统日志目录-->
    <property name="APPDIR" value="shop"/>

    <!-- 日志记录器,日期滚动记录 错误-->
    <appender name="FILEERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/${APPDIR}/log_error.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,
            可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
            而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/${APPDIR}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 日志保存15天,超过15天自动删除 -->
            <maxHistory>15</maxHistory>
            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
            命名日志文件,例如log-error-2013-12-21.0.log -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>50MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志文件的格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>11===%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!--111111111111111111111111111111111111111111111111111111111111111111111111111-->
    <!-- 日志记录器,日期滚动记录  警告-->
    <appender name="FILEWARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/${APPDIR}/log_warn.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
            而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/${APPDIR}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 日志保存15天,超过15天自动删除 -->
            <maxHistory>15</maxHistory>
            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
            命名日志文件,例如log-error-2013-12-21.0.log -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>50MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志文件的格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>22===%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!--222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222-->
    <!-- 日志记录器,日期滚动记录 信息-->
    <appender name="FILEINFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/${APPDIR}/log_info.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
            而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/${APPDIR}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 日志保存15天,超过15天自动删除 -->
            <maxHistory>15</maxHistory>
            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
            命名日志文件,例如log-error-2013-12-21.0.log -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>50MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志文件的格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>33==%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!--33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333-->
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!--encoder 默认配置为PatternLayoutEncoder-->
        <encoder>
            <pattern>44==%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>info</level>
        </filter>
    </appender>
    <!--44444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444-->
    <!--就是这个监控了mybatis日志输出,配合上面的“dao”-->
    <logger name="mapper" level="debug" additivity="false">
        <appender-ref ref="FILEINFO"/>
    </logger>
    <logger name="mapper" level="debug" additivity="false">
        <appender-ref ref="FILEWARN"/>
    </logger>
    <logger name="mapper" level="debug" additivity="false">
        <appender-ref ref="FILEERROR"/>
    </logger>
    <logger name="mapper" level="debug" additivity="false">
        <appender-ref ref="STDOUT"/>
    </logger>

    <!--这个是管理mybatis映射类的加载的跟事物管理的-->
    <logger name="org.mybatis" level="debug" additivity="false">
        <appender-ref ref="FILEINFO"/>
        <appender-ref ref="STDOUT"/>
        <!--<appender-ref ref="FILEERROR"/>-->
        <!--<appender-ref ref="FILEWARN"/>-->
    </logger>

    <root level="info">
        <appender-ref ref="FILEERROR"/>
        <appender-ref ref="FILEWARN"/>
        <appender-ref ref="FILEINFO"/>
        <!-- 生产环境将请stdout去掉 -->
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

3. 新建一个切面类

package com.example.tmshop.tm.common;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.MethodArgumentNotValidException;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;

@Aspect
@Component
public class LogBackAop {

    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final Logger LOG = LoggerFactory.getLogger(LogBackAop.class);

    private Object runAndSaveLog(ProceedingJoinPoint pjp){
        Long beginTime =System.currentTimeMillis();
        Object result = null;
        //用户访问的controller(用户访问的controller)
        String target = pjp.getTarget().getClass().getName();
        //方法名(用户访问的方法名)
        String signature = pjp.getSignature().getName();
        try{
            result  = pjp.proceed(); //这个方法就是我们实际执行的方法
        }catch (Throwable e){
            //一旦上面的controller方法遇到问题,提取错误信息
            LOG.error("用户在"+new Date(beginTime)+"遇到问题:"+e.getMessage()+e.getStackTrace());
            ResultController result1 = ResultController.ERROR(CodeEnum.ERROR);
            return result1;
        }
        Long endTime = System.currentTimeMillis();
        Date data=new Date();
        LOG.info("(------用户xxx在"+sdf.format(data)+"访问了"+target+"中的"+signature+"方法,方法用时:"+(endTime-beginTime)+"毫秒------)");
       //result就是controller层方法的返回值,可以根据result对象来判断方法是否执行成功和状态码
        return result;
    }

    @Around("@within(org.springframework.stereotype.Controller)")
    Object aroundController(ProceedingJoinPoint pjp){
        return runAndSaveLog(pjp);
    }

    @Around("@within(org.springframework.web.bind.annotation.RestController)")
    Object aroundRestController(ProceedingJoinPoint pjp){

        return runAndSaveLog(pjp);
    }

}
    return runAndSaveLog(pjp);
    }

    @Around("@within(org.springframework.web.bind.annotation.RestController)")
    Object aroundRestController(ProceedingJoinPoint pjp){

        return runAndSaveLog(pjp);
    }

}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值