我是靠谱客的博主 沉静奇迹,这篇文章主要介绍SpringBoot/Cloud AOP 统一日志输出,现在分享给大家,希望可以做个参考。

在这里插入图片描述
在这里插入图片描述

文章目录

            • 1. 导入依赖
            • 2. aop拦截器
            • 3. logback配置
            • 4. 测试类
            • 5. 关键点
            • 6. 效果图

1. 导入依赖
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
<!-- AOP --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!-- 数据序列化--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency>
2. aop拦截器
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package com.course.server.config; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.support.spring.PropertyPreFilters; import com.course.server.util.UuidUtil; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Around; 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.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Field; @Aspect @Component public class LogAspect { private final static Logger LOG = LoggerFactory.getLogger(LogAspect.class); /** 定义一个切点 */ @Pointcut("execution(public * com.course.*.controller..*Controller.*(..))") public void controllerPointcut() {} @Before("controllerPointcut()") public void doBefore(JoinPoint joinPoint) throws Throwable { // 日志编号 MDC.put("UUID", UuidUtil.getShortUuid()); // 开始打印请求日志 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); Signature signature = joinPoint.getSignature(); String name = signature.getName(); // 打印业务操作 String nameCn = ""; if (name.contains("list") || name.contains("query")) { nameCn = "查询"; } else if (name.contains("save")) { nameCn = "保存"; } else if (name.contains("delete")) { nameCn = "删除"; } else { nameCn = "操作"; } // 使用反射,获取业务名称 Class clazz = signature.getDeclaringType(); Field field; String businessName = ""; try { field = clazz.getField("BUSINESS_NAME"); if (!StringUtils.isEmpty(field)) { businessName = (String) field.get(clazz); } } catch (NoSuchFieldException e) { LOG.error("未获取到业务名称"); } catch (SecurityException e) { LOG.error("获取业务名称失败", e); } // 打印请求信息 LOG.info("------------- 【{}】{}开始 -------------", businessName, nameCn); LOG.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod()); LOG.info("类名方法: {}.{}", signature.getDeclaringTypeName(), name); LOG.info("远程地址: {}", request.getRemoteAddr()); // 打印请求参数 Object[] args = joinPoint.getArgs(); Object[] arguments = new Object[args.length]; for (int i = 0; i < args.length; i++) { if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) { continue; } arguments[i] = args[i]; } // 排除字段,敏感字段或太长的字段不显示 String[] excludeProperties = {"shard"}; PropertyPreFilters filters = new PropertyPreFilters(); PropertyPreFilters.MySimplePropertyPreFilter excludefilter = filters.addFilter(); excludefilter.addExcludes(excludeProperties); LOG.info("请求参数: {}", JSONObject.toJSONString(arguments, excludefilter)); // 为空的会不打印,但是像图片等长字段也会打印 } @Around("controllerPointcut()") public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { long startTime = System.currentTimeMillis(); Object result = proceedingJoinPoint.proceed(); // 排除字段,敏感字段或太长的字段不显示 String[] excludeProperties = {"password", "shard"}; PropertyPreFilters filters = new PropertyPreFilters(); PropertyPreFilters.MySimplePropertyPreFilter excludefilter = filters.addFilter(); excludefilter.addExcludes(excludeProperties); LOG.info("返回结果: {}", JSONObject.toJSONString(result, excludefilter)); LOG.info("------------- 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime); return result; } }
3. logback配置

在这里插入图片描述
logback.xml

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- 修改一下路径--> <property name="PATH" value="/log/imooc/course/business"></property> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <!-- <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %blue(%-50logger{50}:%-4line) %green(%-8X{UUID}) %msg%n</Pattern>--> <Pattern>%d{ss.SSS} %highlight(%-5level) %blue(%-30logger{30}:%-4line) %green(%-8X{UUID}) %msg%n</Pattern> </encoder> </appender> <appender name="TRACE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${PATH}/trace.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${PATH}/trace.%d{yyyy-MM-dd}.%i.log</FileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <layout> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-50logger{50}:%-4line %green(%-8X{UUID}) %msg%n</pattern> </layout> </appender> <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${PATH}/error.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${PATH}/error.%d{yyyy-MM-dd}.%i.log</FileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <layout> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-50logger{50}:%-4line %green(%-8X{UUID}) %msg%n</pattern> </layout> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <root level="ERROR"> <appender-ref ref="ERROR_FILE" /> </root> <root level="TRACE"> <appender-ref ref="TRACE_FILE" /> </root> <root level="INFO"> <appender-ref ref="STDOUT" /> </root> </configuration>
4. 测试类
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.course.business.controller.admin; import com.course.server.dto.ChapterDto; import com.course.server.dto.PageDto; import com.course.server.dto.ResponseDto; import com.course.server.service.ChapterService; import com.course.server.util.ValidatorUtil; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @RestController @RequestMapping("/admin/chapter") public class ChapterController { // 业务标识 public static final String BUSINESS_NAME = "大章"; @Resource private ChapterService chapterService; //http://127.0.0.1:9002/business/admin/chapter/list @PostMapping("/list") public ResponseDto list(@RequestBody PageDto pageDto) { ResponseDto responseDto = new ResponseDto(); chapterService.list(pageDto); responseDto.setContent(pageDto); return responseDto; } @PostMapping("/save") public ResponseDto save(@RequestBody ChapterDto chapterDto) { // 保存校验 ValidatorUtil.require(chapterDto.getName(), "名称"); ValidatorUtil.require(chapterDto.getCourseId(), "课程ID"); ValidatorUtil.length(chapterDto.getCourseId(), "课程ID", 1, 8); ResponseDto responseDto = new ResponseDto(); chapterService.save(chapterDto); responseDto.setContent(chapterDto); return responseDto; } @DeleteMapping("/delete/{id}") public ResponseDto delete(@PathVariable String id) { ResponseDto responseDto = new ResponseDto(); chapterService.delete(id); return responseDto; } }
5. 关键点

LogAspect中日志key “UUID”要和logback.xml中的获取的key UUID要一致,UUID生成规则自定义
在这里插入图片描述
在这里插入图片描述

6. 效果图

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

最后

以上就是沉静奇迹最近收集整理的关于SpringBoot/Cloud AOP 统一日志输出的全部内容,更多相关SpringBoot/Cloud内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部