aop實現記錄日誌
阿新 • • 發佈:2018-12-30
1、建立springboot專案
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <classifier>jdk15</classifier> </dependency> </dependencies> </project>
log4j.xml
# LOG4J配置 log4j.rootCategory=INFO, stdout, file, errorfile //級別,控制檯,檔案,錯誤的日誌 log4j.category.com.yy=DEBUG, bootfile //com.yy包底下所有產生的日誌都會給它一個檔案 my.log log4j.logger.error=errorfile # 控制檯輸出 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n # root日誌輸出 log4j.appender.file=org.apache.log4j.DailyRollingFileAppender //每天會產生一個日誌檔案 log4j.appender.file.file=D:/logs/all.log log4j.appender.file.DatePattern='.'yyyy-MM-dd //年月日的命名檔案 log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n # error下的日誌輸出 log4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender log4j.appender.errorfile.file=D:/logs/error.log log4j.appender.errorfile.DatePattern='.'yyyy-MM-dd log4j.appender.errorfile.Threshold = ERROR log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout log4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n # com.newer下的日誌輸出 log4j.appender.bootfile=org.apache.log4j.DailyRollingFileAppender log4j.appender.bootfile.file=D:/logs/my.log log4j.appender.bootfile.DatePattern='.'yyyy-MM-dd log4j.appender.bootfile.layout=org.apache.log4j.PatternLayout log4j.appender.bootfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L ---- %m%n
application.properties
server.port=8088
logging.level.*=debug
2、切面:
package com.example.demo.common.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; 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 java.util.Arrays; /** * web請求日誌切面類---專門針對控制層,如誰被請求了,花了多少時間,請求傳送的引數,返回得值等 * @author yy */ @Aspect // 表示一個切面bean @Component // bean容器的元件註解。雖然放在contrller包裡,但它不是控制器。如果注入service,但我們又沒有放在service包裡 @Order(3) // 有多個日誌時,ORDER可以定義切面的執行順序(數字越大,前置越後執行,後置越前執行) public class WebLogAspect { //定義一個日誌記錄器 Logger logger=LoggerFactory.getLogger(this.getClass()); //定義一個執行緒本地變數,記錄各個執行緒開始的時間 ThreadLocal<Long> starttime=new ThreadLocal<Long>(); /** * 定義一個切入點 */ @Pointcut("execution(public * com.*.*.controller.*.*(..))") public void weblog(){ } @Before("weblog()") public void doBefore(JoinPoint joinPoint){ logger.info("前置通知"); starttime.set(System.currentTimeMillis()); //獲取servlet請求物件---因為這不是控制器,這裡不能注入HttpServletRequest,但springMVC本身提供ServletRequestAttributes可以拿到 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); logger.info("URL:"+request.getRequestURL().toString()); logger.info("Method:"+request.getMethod()); logger.info("CLASS_METHOD:"+joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName()); logger.info("ARGS:"+ Arrays.toString(joinPoint.getArgs())); } //方法的返回值注入ret @AfterReturning(returning = "ret",pointcut = "weblog()") public void doafter(Object ret) { logger.info("後置通知:"); logger.info("RESPONSE:" + ret); // 響應的內容---方法的返回值responseEntity logger.info("SPEND:" + (System.currentTimeMillis() - starttime.get())); } }
3、目標:
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SampleController {
@RequestMapping("/home")
public String home() {
return "Hello World!";
}
}