Browse Source

日志模块之 aop日志拦截 案例完成

3.x
Yangkai.Shen 2 years ago
parent
commit
b0f5a88151
16 changed files with 447 additions and 528 deletions
  1. +0
    -25
      demo-log-aop/.gitignore
  2. +0
    -281
      demo-log-aop/README.md
  3. +0
    -76
      demo-log-aop/pom.xml
  4. +0
    -77
      demo-log-aop/src/main/resources/logback-spring.xml
  5. +0
    -16
      demo-log-aop/src/test/java/com/xkcoding/log/aop/SpringBootDemoLogAopApplicationTests.java
  6. +209
    -0
      demo-log/demo-log-aop/README.md
  7. +69
    -0
      demo-log/demo-log-aop/pom.xml
  8. +4
    -4
      demo-log/demo-log-aop/src/main/java/com/xkcoding/log/aop/LogAopApplication.java
  9. +7
    -44
      demo-log/demo-log-aop/src/main/java/com/xkcoding/log/aop/aspectj/AopLog.java
  10. +4
    -4
      demo-log/demo-log-aop/src/main/java/com/xkcoding/log/aop/controller/TestController.java
  11. +63
    -0
      demo-log/demo-log-aop/src/main/java/com/xkcoding/log/aop/model/LogData.java
  12. +0
    -0
      demo-log/demo-log-aop/src/main/resources/application.yml
  13. +77
    -0
      demo-log/demo-log-aop/src/main/resources/logback-spring.xml
  14. +13
    -0
      demo-log/demo-log-aop/src/test/java/com/xkcoding/log/aop/LogAopApplicationTests.java
  15. +1
    -0
      demo-log/pom.xml
  16. +0
    -1
      pom.xml

+ 0
- 25
demo-log-aop/.gitignore View File

@@ -1,25 +0,0 @@
/target/
!.mvn/wrapper/maven-wrapper.jar

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

+ 0
- 281
demo-log-aop/README.md View File

@@ -1,281 +0,0 @@
# spring-boot-demo-log-aop

> 此 demo 主要是演示如何使用 aop 切面对请求进行日志记录,并且记录 UserAgent 信息。

## pom.xml

```xml
<?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>

<artifactId>spring-boot-demo-log-aop</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>spring-boot-demo-log-aop</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>com.xkcoding</groupId>
<artifactId>spring-boot-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</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-aop</artifactId>
</dependency>

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

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>

<!-- 解析 UserAgent 信息 -->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
</dependency>
</dependencies>

<build>
<finalName>spring-boot-demo-log-aop</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
```

## AopLog.java

```java
/**
* <p>
* 使用 aop 切面记录请求日志信息
* </p>
*
* @author yangkai.shen
* @author chen qi
* @date Created in 2018-10-01 22:05
*/
@Aspect
@Component
@Slf4j
public class AopLog {
/**
* 切入点
*/
@Pointcut("execution(public * com.xkcoding.log.aop.controller.*Controller.*(..))")
public void log() {

}

/**
* 环绕操作
*
* @param point 切入点
* @return 原方法返回值
* @throws Throwable 异常信息
*/
@Around("log()")
public Object aroundLog(ProceedingJoinPoint point) throws Throwable {

// 开始打印请求日志
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

// 打印请求相关参数
long startTime = System.currentTimeMillis();
Object result = point.proceed();
String header = request.getHeader("User-Agent");
UserAgent userAgent = UserAgent.parseUserAgentString(header);

final Log l = Log.builder()
.threadId(Long.toString(Thread.currentThread().getId()))
.threadName(Thread.currentThread().getName())
.ip(getIp(request))
.url(request.getRequestURL().toString())
.classMethod(String.format("%s.%s", point.getSignature().getDeclaringTypeName(),
point.getSignature().getName()))
.httpMethod(request.getMethod())
.requestParams(getNameAndValue(point))
.result(result)
.timeCost(System.currentTimeMillis() - startTime)
.userAgent(header)
.browser(userAgent.getBrowser().toString())
.os(userAgent.getOperatingSystem().toString()).build();

log.info("Request Log Info : {}", JSONUtil.toJsonStr(l));

return result;
}

/**
* 获取方法参数名和参数值
* @param joinPoint
* @return
*/
private Map<String, Object> getNameAndValue(ProceedingJoinPoint joinPoint) {

final Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
final String[] names = methodSignature.getParameterNames();
final Object[] args = joinPoint.getArgs();

if (ArrayUtil.isEmpty(names) || ArrayUtil.isEmpty(args)) {
return Collections.emptyMap();
}
if (names.length != args.length) {
log.warn("{}方法参数名和参数值数量不一致", methodSignature.getName());
return Collections.emptyMap();
}
Map<String, Object> map = Maps.newHashMap();
for (int i = 0; i < names.length; i++) {
map.put(names[i], args[i]);
}
return map;
}

private static final String UNKNOWN = "unknown";

/**
* 获取ip地址
*/
public static String getIp(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
String comma = ",";
String localhost = "127.0.0.1";
if (ip.contains(comma)) {
ip = ip.split(",")[0];
}
if (localhost.equals(ip)) {
// 获取本机真正的ip地址
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
log.error(e.getMessage(), e);
}
}
return ip;
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
static class Log {
// 线程id
private String threadId;
// 线程名称
private String threadName;
// ip
private String ip;
// url
private String url;
// http方法 GET POST PUT DELETE PATCH
private String httpMethod;
// 类方法
private String classMethod;
// 请求参数
private Object requestParams;
// 返回参数
private Object result;
// 接口耗时
private Long timeCost;
// 操作系统
private String os;
// 浏览器
private String browser;
// user-agent
private String userAgent;
}
}
```

## TestController.java

```java
/**
* <p>
* 测试 Controller
* </p>
*
* @author yangkai.shen
* @author chen qi
* @date Created in 2018-10-01 22:10
*/
@Slf4j
@RestController
public class TestController {

/**
* 测试方法
*
* @param who 测试参数
* @return {@link Dict}
*/
@GetMapping("/test")
public Dict test(String who) {
return Dict.create().set("who", StrUtil.isBlank(who) ? "me" : who);
}

/**
* 测试post json方法
* @param map 请求的json参数
* @return {@link Dict}
*/
@PostMapping("/testJson")
public Dict testJson(@RequestBody Map<String, Object> map) {

final String jsonStr = JSONUtil.toJsonStr(map);
log.info(jsonStr);
return Dict.create().set("json", map);
}
}
```


+ 0
- 76
demo-log-aop/pom.xml View File

@@ -1,76 +0,0 @@
<?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>

<artifactId>demo-log-aop</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>demo-log-aop</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>com.xkcoding</groupId>
<artifactId>spring-boot-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</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-aop</artifactId>
</dependency>

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

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>

<!-- 解析 UserAgent 信息 -->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
</dependency>
</dependencies>

<build>
<finalName>demo-log-aop</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

+ 0
- 77
demo-log-aop/src/main/resources/logback-spring.xml View File

@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>

<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--如果只是想要 Info 级别的日志,只是过滤 info 还是会输出 Error 日志,因为 Error 的级别高, 所以我们使用下面的策略,可以避免输出 Error 的日志-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!--过滤 Error-->
<level>ERROR</level>
<!--匹配到就禁止-->
<onMatch>DENY</onMatch>
<!--没有匹配到就允许-->
<onMismatch>ACCEPT</onMismatch>
</filter>
<!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。-->
<!--<File>logs/info.demo-log-aop.log</File>-->
<!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
<FileNamePattern>logs/demo-log-aop/info.created_on_%d{yyyy-MM-dd}.part_%i.log</FileNamePattern>
<!--只保留最近90天的日志-->
<maxHistory>90</maxHistory>
<!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
<!--<totalSizeCap>1GB</totalSizeCap>-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- maxFileSize:这是活动文件的大小,默认值是10MB,本篇设置为1KB,只是为了演示 -->
<maxFileSize>2MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!--<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">-->
<!--<maxFileSize>1KB</maxFileSize>-->
<!--</triggeringPolicy>-->
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
</appender>

<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>Error</level>
</filter>
<!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。-->
<!--<File>logs/error.demo-log-aop.log</File>-->
<!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
<FileNamePattern>logs/demo-log-aop/error.created_on_%d{yyyy-MM-dd}.part_%i.log</FileNamePattern>
<!--只保留最近90天的日志-->
<maxHistory>90</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- maxFileSize:这是活动文件的大小,默认值是10MB,本篇设置为1KB,只是为了演示 -->
<maxFileSize>2MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
</appender>

<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE_INFO"/>
<appender-ref ref="FILE_ERROR"/>
</root>
</configuration>

+ 0
- 16
demo-log-aop/src/test/java/com/xkcoding/log/aop/SpringBootDemoLogAopApplicationTests.java View File

@@ -1,16 +0,0 @@
package com.xkcoding.log.aop;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootDemoLogAopApplicationTests {

@Test
public void contextLoads() {
}

}

+ 209
- 0
demo-log/demo-log-aop/README.md View File

@@ -0,0 +1,209 @@
## spring-boot-demo-log-aop

> 此 demo 主要是演示如何使用 aop 切面对请求进行日志记录,并且记录 UserAgent 信息。

### 1.开发步骤

#### 1.1.添加依赖

```xml
<dependencies>
<dependency>
<groupId>com.xkcoding</groupId>
<artifactId>common-tools</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-aop</artifactId>
</dependency>

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

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- 解析 UserAgent 信息 -->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
<version>1.21</version>
</dependency>
</dependencies>
```

#### 1.2.添加切面拦截

```java
@Slf4j
@Aspect
@Component
public class AopLog {
/**
* 切入点
*/
@Pointcut("execution(public * com.xkcoding.log.aop.controller.*Controller.*(..))")
public void log() {

}

/**
* 环绕操作
*
* @param point 切入点
* @return 原方法返回值
* @throws Throwable 异常信息
*/
@Around("log()")
public Object aroundLog(ProceedingJoinPoint point) throws Throwable {
// 开始打印请求日志
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

// 打印请求相关参数
long startTime = System.currentTimeMillis();
Object result = point.proceed();
String header = request.getHeader("User-Agent");
UserAgent userAgent = UserAgent.parseUserAgentString(header);

LogData logData = LogData.builder()
.threadId(Long.toString(Thread.currentThread().getId()))
.threadName(Thread.currentThread().getName())
.ip(getIp(request))
.url(request.getRequestURL().toString())
.classMethod(String.format("%s.%s", point.getSignature().getDeclaringTypeName(),
point.getSignature().getName()))
.httpMethod(request.getMethod())
.requestParams(getNameAndValue(point))
.result(result)
.timeCost(System.currentTimeMillis() - startTime)
.userAgent(header)
.browser(userAgent.getBrowser().toString())
.os(userAgent.getOperatingSystem().toString()).build();

log.info("Request Log Info : {}", JSONUtil.toJsonStr(logData));

return result;
}

/**
* 获取方法参数名和参数值
*/
private Map<String, Object> getNameAndValue(ProceedingJoinPoint joinPoint) {
final Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
final String[] names = methodSignature.getParameterNames();
final Object[] args = joinPoint.getArgs();

if (ArrayUtil.isEmpty(names) || ArrayUtil.isEmpty(args)) {
return Collections.emptyMap();
}
if (names.length != args.length) {
log.warn("{}方法参数名和参数值数量不一致", methodSignature.getName());
return Collections.emptyMap();
}
Map<String, Object> map = Maps.newHashMap();
for (int i = 0; i < names.length; i++) {
map.put(names[i], args[i]);
}
return map;
}

private static final String UNKNOWN = "unknown";

/**
* 获取ip地址
*/
public static String getIp(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
String comma = ",";
String localhost = "127.0.0.1";
if (ip.contains(comma)) {
ip = ip.split(",")[0];
}
if (localhost.equals(ip)) {
// 获取本机真正的ip地址
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
log.error(e.getMessage(), e);
}
}
return ip;
}

}
```

### 2.测试

#### 2.1.添加测试接口
```java
@Slf4j
@RestController
public class TestController {

/**
* 测试方法
*
* @param who 测试参数
* @return {@link Dict}
*/
@GetMapping("/test")
public Dict test(String who) {
return Dict.create().set("who", StrUtil.isBlank(who) ? "me" : who);
}

/**
* 测试post json方法
*
* @param map 请求的json参数
* @return {@link Dict}
*/
@PostMapping("/testJson")
public Dict testJson(@RequestBody Map<String, Object> map) {

final String jsonStr = JSONUtil.toJsonStr(map);
log.info(jsonStr);
return Dict.create().set("json", map);
}
}
```

启动 `LogAopApplication`,使用 postman 分别测试
- GET请求

method: GET

url: `http://127.0.0.1:8080/test?who=xkcoding`

- POST请求

method: POST

url: `http://127.0.0.1:8080/testJson`

header: `ContentType:application/json`

data: `{"id":"xxxx","content":"test"}`

+ 69
- 0
demo-log/demo-log-aop/pom.xml View File

@@ -0,0 +1,69 @@
<?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">
<parent>
<groupId>com.xkcoding</groupId>
<artifactId>demo-log</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>demo-log-aop</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>demo-log-aop</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>17</java.version>
</properties>

<dependencies>
<dependency>
<groupId>com.xkcoding</groupId>
<artifactId>common-tools</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-aop</artifactId>
</dependency>

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

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- 解析 UserAgent 信息 -->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
<version>1.21</version>
</dependency>
</dependencies>

<build>
<finalName>demo-log-aop</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

demo-log-aop/src/main/java/com/xkcoding/log/aop/SpringBootDemoLogAopApplication.java → demo-log/demo-log-aop/src/main/java/com/xkcoding/log/aop/LogAopApplication.java View File

@@ -5,16 +5,16 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* <p>
* 启动
* 启动
* </p>
*
* @author yangkai.shen
* @date Created in 2018-10-01 22:05
* @date Created in 2022-08-26 11:58
*/
@SpringBootApplication
public class SpringBootDemoLogAopApplication {
public class LogAopApplication {

public static void main(String[] args) {
SpringApplication.run(SpringBootDemoLogAopApplication.class, args);
SpringApplication.run(LogAopApplication.class, args);
}
}

demo-log-aop/src/main/java/com/xkcoding/log/aop/aspectj/AopLog.java → demo-log/demo-log-aop/src/main/java/com/xkcoding/log/aop/aspectj/AopLog.java View File

@@ -3,11 +3,9 @@ package com.xkcoding.log.aop.aspectj;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Maps;
import com.xkcoding.log.aop.model.LogData;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
@@ -19,7 +17,6 @@ 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.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
@@ -33,11 +30,11 @@ import java.util.Objects;
*
* @author yangkai.shen
* @author chen qi
* @date Created in 2018-10-01 22:05
* @date Created in 2022-08-26 11:58
*/
@Slf4j
@Aspect
@Component
@Slf4j
public class AopLog {
/**
* 切入点
@@ -56,7 +53,6 @@ public class AopLog {
*/
@Around("log()")
public Object aroundLog(ProceedingJoinPoint point) throws Throwable {

// 开始打印请求日志
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
@@ -67,7 +63,7 @@ public class AopLog {
String header = request.getHeader("User-Agent");
UserAgent userAgent = UserAgent.parseUserAgentString(header);

final Log l = Log.builder()
LogData logData = LogData.builder()
.threadId(Long.toString(Thread.currentThread().getId()))
.threadName(Thread.currentThread().getName())
.ip(getIp(request))
@@ -82,18 +78,15 @@ public class AopLog {
.browser(userAgent.getBrowser().toString())
.os(userAgent.getOperatingSystem().toString()).build();

log.info("Request Log Info : {}", JSONUtil.toJsonStr(l));
log.info("Request Log Info : {}", JSONUtil.toJsonStr(logData));

return result;
}

/**
* 获取方法参数名和参数值
* @param joinPoint
* @return
* 获取方法参数名和参数值
*/
private Map<String, Object> getNameAndValue(ProceedingJoinPoint joinPoint) {

final Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
final String[] names = methodSignature.getParameterNames();
@@ -145,34 +138,4 @@ public class AopLog {
return ip;
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
static class Log {
// 线程id
private String threadId;
// 线程名称
private String threadName;
// ip
private String ip;
// url
private String url;
// http方法 GET POST PUT DELETE PATCH
private String httpMethod;
// 类方法
private String classMethod;
// 请求参数
private Object requestParams;
// 返回参数
private Object result;
// 接口耗时
private Long timeCost;
// 操作系统
private String os;
// 浏览器
private String browser;
// user-agent
private String userAgent;
}
}

demo-log-aop/src/main/java/com/xkcoding/log/aop/controller/TestController.java → demo-log/demo-log-aop/src/main/java/com/xkcoding/log/aop/controller/TestController.java View File

@@ -13,12 +13,11 @@ import java.util.Map;

/**
* <p>
* 测试 Controller
* 测试端点
* </p>
*
* @author yangkai.shen
* @author chen qi
* @date Created in 2018-10-01 22:10
* @date Created in 2022-08-26 11:58
*/
@Slf4j
@RestController
@@ -36,7 +35,8 @@ public class TestController {
}

/**
* 测试post json方法
* 测试post json方法
*
* @param map 请求的json参数
* @return {@link Dict}
*/

+ 63
- 0
demo-log/demo-log-aop/src/main/java/com/xkcoding/log/aop/model/LogData.java View File

@@ -0,0 +1,63 @@
package com.xkcoding.log.aop.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class LogData {
/**
* 线程id
*/
private String threadId;
/**
* 线程名称
*/
private String threadName;
/**
* ip
*/
private String ip;
/**
* url
*/
private String url;
/**
* 类方法
*/
private String classMethod;
/**
* http方法 GET
* POST PUT
* DELETE PATCH
*/
private String httpMethod;
/**
* 请求参数
*/
private Object requestParams;
/**
* 返回参数
*/
private Object result;
/**
* 接口耗时
*/
private Long timeCost;
/**
* 操作系统
*/
private String os;
/**
* 浏览器
*/
private String browser;
/**
* user-agent
*/
private String userAgent;
}

demo-log-aop/src/main/resources/application.yml → demo-log/demo-log-aop/src/main/resources/application.yml View File


+ 77
- 0
demo-log/demo-log-aop/src/main/resources/logback-spring.xml View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>

<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--如果只是想要 Info 级别的日志,只是过滤 info 还是会输出 Error 日志,因为 Error 的级别高, 所以我们使用下面的策略,可以避免输出 Error 的日志-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!--过滤 Error-->
<level>ERROR</level>
<!--匹配到就禁止-->
<onMatch>DENY</onMatch>
<!--没有匹配到就允许-->
<onMismatch>ACCEPT</onMismatch>
</filter>
<!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。-->
<!--<File>logs/info.demo-log-aop.log</File>-->
<!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
<FileNamePattern>logs/demo-log/demo-log-aop/info.created_on_%d{yyyy-MM-dd}.part_%i.log</FileNamePattern>
<!--只保留最近90天的日志-->
<maxHistory>90</maxHistory>
<!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
<!--<totalSizeCap>1GB</totalSizeCap>-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- maxFileSize:这是活动文件的大小,默认值是10MB,本篇设置为1KB,只是为了演示 -->
<maxFileSize>2MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!--<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">-->
<!--<maxFileSize>1KB</maxFileSize>-->
<!--</triggeringPolicy>-->
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
</appender>

<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>Error</level>
</filter>
<!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。-->
<!--<File>logs/error.demo-log-aop.log</File>-->
<!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
<FileNamePattern>logs/demo-log/demo-log-aop/error.created_on_%d{yyyy-MM-dd}.part_%i.log</FileNamePattern>
<!--只保留最近90天的日志-->
<maxHistory>90</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- maxFileSize:这是活动文件的大小,默认值是10MB,本篇设置为1KB,只是为了演示 -->
<maxFileSize>2MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
</appender>

<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE_INFO"/>
<appender-ref ref="FILE_ERROR"/>
</root>
</configuration>

+ 13
- 0
demo-log/demo-log-aop/src/test/java/com/xkcoding/log/aop/LogAopApplicationTests.java View File

@@ -0,0 +1,13 @@
package com.xkcoding.log.aop;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class LogAopApplicationTests {

@Test
void contextLoads() {
}

}

+ 1
- 0
demo-log/pom.xml View File

@@ -20,6 +20,7 @@

<modules>
<module>demo-log-logback</module>
<module>demo-log-aop</module>
</modules>

</project>

+ 0
- 1
pom.xml View File

@@ -28,7 +28,6 @@
<module>demo-workflow</module>
<module>demo-package</module>
<module>demo-others</module>
<!-- <module>demo-log-aop</module>-->
<!-- <module>demo-template-freemarker</module>-->
<!-- <module>demo-template-thymeleaf</module>-->
<!-- <module>demo-template-beetl</module>-->


Loading…
Cancel
Save