操作日誌記錄(包括輸出至自定義日誌檔案)

深藍格調_發表於2020-10-16

1.日誌部分

1.1日誌依賴


<dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.2.3</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.30</version>
</dependency>

1.2logback.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!-- configuration file for LogBack (slf4J implementation)
See here for more details: http://gordondickens.com/wordpress/2013/03/27/sawing-through-the-java-loggers/ -->
<!--code generator-->
<!--author Steven-->
<!--version 1.0.0-->
<configuration scan="true" scanPeriod="30 seconds">

    <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <resetJUL>true</resetJUL>
    </contextListener>

    <!-- To enable JMX Management -->
    <jmxConfigurator/>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/log.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- Daily rollover with compression -->
            <fileNamePattern>logs/log-%d{yyyy-MM-dd}.gz</fileNamePattern>
            <!-- keep 30 days worth of history -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/error-%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %thread %X{invokeNo} %logger{40} %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只列印錯誤日誌 -->
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--不同業務邏輯的日誌列印到不同檔案-->
    <appender name="operationLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>logs/operation.log</File>
        <append>true</append>
        <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>logs/operation-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder charset="UTF-8">
            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %level [%thread] %file:%line - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 不同的業務邏輯日誌列印到指定資料夾-->
    <logger name="operation" additivity="false" level="INFO">
        <appender-ref ref="operationLog"/>
    </logger>

    <!-- Specify logging levels -->
    <logger name="org.springframework" level="info"/>
    <logger name="org.hibernate" level="info"/>
    <logger name="com.jpxx.admin" level="debug"/>
    <logger name="com.jpxx.base" level="info"/>
    <!--<logger name="org.springframework.transaction" level="DEBUG" />-->
    <!--<logger name="org.springframework.jdbc.datasource" level="DEBUG" />-->
    <!--<logger name="org.springframework.orm.jpa" level="DEBUG" />-->

    <root level="info">
        <appender-ref ref="console"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="errorAppender"/>
    </root>
</configuration>

2.自定義註解配合aop實現攔截記錄使用者操作

2.1aop依賴

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

2.2開啟aop配置

spring:
  #切面啟用
  aop:
    proxy-target-class: true
    auto: true

2.3自定義註解

@Target({ElementType.PARAMETER, ElementType.METHOD})//作用在引數和方法上
@Retention(RetentionPolicy.RUNTIME)//執行時註解
@Documented//表明這個註解應該被 javadoc工具記錄
public @interface OperationLog  {
    String description() default "";
}

2.4切面類


import com.alibaba.fastjson.JSON;
import com.jpxx.admin.common.util.LoggerUtils;
import com.jpxx.admin.system.service.api.SysUserService;

import com.jpxx.base.utils.jwt.JwtSubject;
import com.jpxx.base.utils.jwt.JwtUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Enumeration;

/**
 * @ClassName SystemLogAspect
 * @Description
 * @Author Administrator
 * @Date 2020/10/15 0015 16:49
 * @Version 1.0
 */
@Aspect
@Component
@SuppressWarnings("all")
public class SystemLogAspect {


    //本地日誌記錄物件
    private static final Logger logger = LoggerUtils.Logger("operation");


    //api切點
    @Pointcut("@annotation(com.jpxx.admin.system.web.annotation.OperationLog)")
    public void operationAspect() {
    }

    /**
     * @Description 前置通知 
     */
    @Before("operationAspect()")
    public void doBefore(JoinPoint joinPoint) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        //讀取使用者資訊
        String token = request.getHeader("token");
        JwtSubject decode = JwtUtils.decode(token);
        Long usId = decode.getUsId();
        String ip = request.getRemoteHost();
        try {
            //*========控制檯輸出=========*//
            System.out.println("==============前置通知開始==============");
            System.out.println("請求方法" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName()));
            System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));
            System.out.println("請求人id:" + usId);
            System.out.println("請求ip:" + ip);

            //日誌記錄
            logger.info("請求方法" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName()));
            logger.info("方法描述:" + getControllerMethodDescription(joinPoint));
            logger.info("請求人id:" + usId);
            logger.info("請求ip:" + ip);
        } catch (Exception e) {
            //記錄本地異常日誌
            logger.error("==前置通知異常==");
            logger.error("異常資訊:{}", e.getMessage());
        }
    }

   

    /**
     * @Description 獲取方法描述
     */
    public static String getServiceMethodDescription(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String description = "";
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    description = method.getAnnotation(SystemServiceLog.class).description();
                    break;
                }
            }
        }
        return description;
    }

}

2.5測試新增註解的介面

執行後:

控制檯:

 日誌:

相關文章