# SpringBoot之AOP整合,记录系统日志
Springboot2.x 版本整合AOP,通过自定义注解方式实现记录系统日志
# 添加依赖
pom中引入SpringBoot的AOP相关的依赖
<!-- Spring AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
1
2
3
4
5
2
3
4
5
# 定于日志实体类SysLog
@Table(name = "sys_log")
@Entity
@Data
@ApiModel(value = "日志实体类")
public class SysLog {
@Id
// @GeneratedValue(strategy = GenerationType.AUTO)
private String id;
/**
* 类名
* */
@Column(nullable = false)
private String className;
/**
* 方法名
* */
@Column(nullable = false)
private String methodName;
/**
* 参数
* */
@Column(nullable = false)
private String params;
/**
* 执行时间
* */
@Column(nullable = false)
private Long execTime;
/**
* 切面标记
* */
private String remark;
/**
* 创建时间
* */
@Column(nullable = false)
private String createDate;
/**
* 请求URL
* */
@Column(nullable = false)
private String url;
/**
* 请求IP
* */
@Column(nullable = false)
private String ip;
/**
* http method
* */
@Column(nullable = false)
private String httpMethod;
}
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
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
# 自定义注解@SysLogAnnotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLogAnnotation {
String value() default "";
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# @Aspect注解声明一个切面
@Aspect
@Component
public class SysLogAspect {
@Autowired
private SysLogService sysLogService;
/**
* 这里我们使用注解的形式
* 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
* 切点表达式: execution(...)
* 例如:execution(public * com.example.demo.controller.*.*(..))
*/
@Pointcut("@annotation(com.gaolei.app.anno.SysLogAnnotation)")
public void logPointCut() {}
/**
* 环绕通知 @Around , 当然也可以使用 @Before (前置通知) @After (后置通知)
* @param point
* @return
* @throws Throwable
*/
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
Object result = point.proceed();
long time = System.currentTimeMillis() - beginTime;
try {
saveLog(point, time);
} catch (Exception e) {
}
return result;
}
/**
* 保存日志
* @param joinPoint
* @param time
*/
private void saveLog(ProceedingJoinPoint joinPoint, long time) {
SysLog sysLog = new SysLog();
//获取请求url,ip,httpMethod
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String ip = request.getRemoteAddr();
String httpMethod = request.getMethod();
String url = request.getRequestURL().toString();
sysLog.setIp(ip);
sysLog.setHttpMethod(httpMethod);
sysLog.setUrl(url);
sysLog.setId(UUIDGenerator.generate());
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
sysLog.setExecTime(time);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
sysLog.setCreateDate(dateFormat.format(new Date()));
SysLogAnnotation annotation = method.getAnnotation(SysLogAnnotation.class);
if(annotation != null){
//注解上的描述
sysLog.setRemark(annotation.value());
}
//请求的 类名、方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setClassName(className);
sysLog.setMethodName(methodName);
//请求的参数
Object[] args = joinPoint.getArgs();
try{
List<String> list = new ArrayList<String>();
for (Object o : args) {
list.add(new Gson().toJson(o));
}
sysLog.setParams(list.toString());
}catch (Exception e){ }
sysLogService.saveSysLog(sysLog);
}
}
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
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
# 定义service
public interface SysLogService {
boolean saveSysLog(SysLog sysLog);
}
1
2
3
4
2
3
4
# 定义serviceImpl
@Slf4j
@Service
public class SysLogServiceImpl implements SysLogService {
@Autowired
private SysLogRepository sysLogRepository;
@Override
public boolean saveSysLog(SysLog sysLog){
sysLogRepository.save(sysLog);
// log.info(sysLog.getParams());
log.info("成功");
return true;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
##定义测试TestController控制器
@Api(tags = "测试")
@Controller
@RequestMapping(value = "/test/v1")
public class TestController {
@SysLogAnnotation("切面测试")
@GetMapping("/test")
public String test(@RequestParam("name") String name){
return name;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 测试
http://localhost:9999/test/v1/test?name=gaolei
1
- idea断点查看
- 查看数据库