SpringBoot + AOP + ロギング フレームワーク ログバックの統合

SpringBoot + AOP + ロギング フレームワーク ログバックの統合

Logback には 5 つのログ レベルがあります。つまり、TRACE < DEBUG < INFO < WARN < ERROR

プロジェクト統合ログフレームワーク(logback)

jar パッケージをインポートする

        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>6.6</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

logback-spring.xml ファイルを構成する

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
    <!--<include resource="org/springframework/boot/logging/logback/base.xml"
        /> -->
    <contextName>Logback For Boss</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="D:/log"/>
    <!-- 定义日志文件 输入位置 -->
    <property name="logDir" value="D:/log"/>
    <!-- 日志最大的历史 30天 -->
    <property name="maxHistory" value="30"/>


    <!-- 控制台输出日志 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>


    <!-- ERROR级别日志 -->
    <appender name="ERROR"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logDir}\%d{yyyyMMdd}\error.log</fileNamePattern>
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger -
                %msg%n
            </pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
        <append>false</append>
        <prudent>false</prudent>
    </appender>

    <!-- WARN级别日志 -->
    <appender name="WARN"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logDir}\%d{yyyyMMdd}\warn.log</fileNamePattern>
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
        <append>false</append>
        <prudent>false</prudent>
    </appender>

    <!-- INFO级别日志 -->
    <appender name="INFO"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logDir}\%d{yyyyMMdd}\info.log</fileNamePattern>
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
        <append>false</append>
        <prudent>false</prudent>
    </appender>

    <!-- DEBUG级别日志 -->
    <appender name="DEBUG"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logDir}\%d{yyyyMMdd}\debug.log</fileNamePattern>
            <maxHistory>${maxHistory}</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
        <append>false</append>
        <prudent>false</prudent>
    </appender>

    <!--文件日志, 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${logDir}/%d{yyyyMMdd}/%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!-- 异步输出 -->
    <appender name="dayLogAsyncAppender" class="ch.qos.logback.classic.AsyncAppender">
        <includeCallerData>true</includeCallerData>
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>512</queueSize>
        <appender-ref ref="FILE"/>
    </appender>

    <!--    &lt;!&ndash;专为 spring 定制-->
    <!--     &ndash;&gt;-->
    <!--    <logger name="org.springframework" level="info"/>-->
    <!--    &lt;!&ndash; show parameters for hibernate sql 专为 Hibernate 定制 &ndash;&gt;-->
    <!--    <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" />-->
    <!--    <logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG" />-->
    <!--    <logger name="org.hibernate.SQL" level="DEBUG" />-->
    <!--    <logger name="org.hibernate.engine.QueryParameters" level="DEBUG" />-->
    <!--    <logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" />-->

    <!--myibatis log configure-->
    <!--
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>
     -->
    <!-- root级别 DEBUG -->
    <root level="INFO">
        <!-- 控制台输出 -->
        <appender-ref ref="STDOUT"/>
        <!-- 文件输出 -->
        <appender-ref ref="ERROR"/>
        <appender-ref ref="INFO"/>
        <appender-ref ref="WARN"/>
        <appender-ref ref="DEBUG"/>
    </root>
</configuration>

ログの出力が必要なクラスで LOGGER オブジェクトをインスタンス化します。

public static final Logger LOGGER = LoggerFactory.getLogger(xxx.class);

ログ出力

LOGGER.error("error");
LOGGER.warn("wring");
LOGGER.info("info"); 
LOGGER.debug("debug");
LOGGER.trace("trace");

カスタム注釈 + AOP によるログ出力の実装

カスタムアノテーションを宣言する

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解:自动进行日志打印
 */
@Target({
    
    ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoLogAnnotation {
    
    
    String methodDesc() default "";//方法描述
}

ログ jar パッケージの依存関係をインポートし、xml ファイルを構成します。

カスタム注釈 + AOP ログ印刷の実装

import com.example.demo.annotation.AutoLogAnnotation;
import com.google.gson.Gson;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 切面AOP
 */
@Aspect
@Component
public class AutoLogAspect {
    
    

    private static final Logger LOGGER = LoggerFactory.getLogger(AutoLogAspect.class);

    @Pointcut("@annotation(com.example.demo.annotation.AutoLogAnnotation)")
    public void logPointCut() {
    
    
    }

    //环绕注入
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
    
    
        long startTime = System.currentTimeMillis();//记录目标方法的开始执行时间
        Object result = point.proceed();//执行目标方法
        long methodExecuteTime = System.currentTimeMillis() - startTime;

        //日志信息记录
        try {
    
    
            MethodSignature methodSignature = (MethodSignature) point.getSignature();
            Method method = methodSignature.getMethod();
            AutoLogAnnotation systemLog = method.getDeclaredAnnotation(AutoLogAnnotation.class);
            String className = point.getTarget().getClass().getName();//类名
            String methodName = method.getName();//方法名

            //入参信息
            Object[] args = point.getArgs();
            List<String> list = new ArrayList<String>();
            for (Object obj : args) {
    
    
                list.add(new Gson().toJson(obj));
            }
            LOGGER.info(className + "." + methodName + "," + systemLog.methodDesc() + ",入参:" + list.toString());
            LOGGER.info(className + "." + methodName + "," + systemLog.methodDesc() + ",耗时:" + methodExecuteTime + "ms");
        } catch (Exception e) {
    
    
            LOGGER.error("日志切入出错");
        }
        return result;
    }
}

おすすめ

転載: blog.csdn.net/asdf12388999/article/details/127106080