導入依賴
<!--引入AOP依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 用於日誌切面中,以 json 格式打印出入參(本來使用阿里的 FASTJSON, 但是對於文件上傳的接口,打印參數會報錯,換爲 Gson) -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<!-- 日誌 start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
Controller層的日誌
/***
* 1.controller方法耗時
* 2.打印入參
* 3.打印異常信息
*/
@Component
@Aspect
@Slf4j
public class ControllerAop {
//切入點
@Pointcut("execution(public * com.yfy.study.controller..*.*(..))")
public void point() {
}
/**
* 在切點之前織入
* @param joinPoint
* @throws Throwable
*/
@Before("point()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 開始打印請求日誌
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 打印請求相關參數
log.info("========================================== Start ==========================================");
// 打印請求 url
log.info("URL : {}", request.getRequestURL().toString());
// 打印 Http method
log.info("HTTP Method : {}", request.getMethod());
// 打印調用 controller 的全路徑以及執行方法
log.info("Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
// 打印請求的 IP
log.info("IP : {}", request.getRemoteAddr());
// 打印請求入參
log.info("Request Args : {}", new Gson().toJson(joinPoint.getArgs()));
}
/**
* 環繞
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("point()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
// 打印出參
log.info("Response Args : {}", new Gson().toJson(result));
// 執行耗時
log.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
return result;
}
/**
* 在切點之後織入
* @throws Throwable
*/
@After("point()")
public void doAfter() throws Throwable {
log.info("=========================================== End ===========================================");
// 每個請求之間空一行
log.info("");
}
}
Service層日誌
/***
* 1.service方法
* 2.打印入參
* 3.打印異常信息
*/
@Component
@Aspect
@Slf4j
public class ServiceAop {
//切入點
@Pointcut("execution(public * com.yfy.study.service.impl..*.*(..))")
public void point() {
}
/**
* 在切點之前織入
* @param joinPoint
* @throws Throwable
*/
@Before("point()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 打印調用 service 的全路徑以及執行方法
log.info(" Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
// 打印請求入參
log.info(" Request Args : {}", new Gson().toJson(joinPoint.getArgs()));
}
/**
* 環繞
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("point()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object result = proceedingJoinPoint.proceed();
// 打印出參
log.info(" Response Args : {}", new Gson().toJson(result));
return result;
}
/**
* 在切點之後織入
* @throws Throwable
*/
@After("point()")
public void doAfter() throws Throwable {
// 每個請求之間空一行
log.info("");
}
}
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds" debug="false">
<contextName>logback</contextName>
<property name="log_path" value="log"/><!-- 如果在Windows環境下使用/開頭的路徑,將會被指定到項目所在的盤符 -->
<property name="log_pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%thread] %logger{50} - %msg%n"/>
<property name="log_fileNamePattern" value="%d{yyyy-MM-dd}.%i.log"/>
<property name="log_maxFileSize" value="100MB"/>
<property name="log_maxHistory" value="30"/>
<!-- 輸出到控制檯 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder charset="UTF-8">
<pattern>${log_pattern}</pattern>
</encoder>
</appender>
<!-- 輸出到paopao-push.log文件 -->
<appender name="APP" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log_path}/paopao-push.log</file>
<encoder charset="UTF-8">
<pattern>${log_pattern}</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_path}/paopao-push-${log_fileNamePattern}</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${log_maxFileSize}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>${log_maxHistory}</maxHistory>
</rollingPolicy>
</appender>
<!-- 輸出到sql.log文件 -->
<appender name="SQL" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log_path}/sql.log</file>
<encoder charset="UTF-8">
<pattern>${log_pattern}</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_path}/sql-${log_fileNamePattern}</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${log_maxFileSize}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>${log_maxHistory}</maxHistory>
</rollingPolicy>
</appender>
<!-- mapper的sql配置 -->
<logger name="com.yfy.study.persistence.dao" level="DEBUG" additivity="false">
<appender-ref ref="SQL" />
<appender-ref ref="CONSOLE" />
</logger>
<!-- 自定義包或者類輸出的級別和策略 -->
<logger name="com.yfy.study" level="INFO" additivity="false">
<appender-ref ref="SQL" />
<appender-ref ref="APP" />
<appender-ref ref="CONSOLE" />
</logger>
<!-- root用來指定最基礎的日誌輸出級別 -->
<root level="INFO">
<appender-ref ref="APP"/>
<appender-ref ref="CONSOLE" />
<appender-ref ref="SQL" />
</root>
</configuration>