Skip to content

Commit 20d8046

Browse files
author
Songyu
committed
增加文章AOP记录日志
1 parent e98bfbb commit 20d8046

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
layout: post
3+
title: "spring aop记录访问日志 "
4+
date: 2021-05-15 20:45:59 +0800
5+
tags: java
6+
description:
7+
---
8+
9+
spring框架最大的特点之一就是AOP(Aspect Oriented Programming)。也就是面向切面编程。
10+
11+
可以在对原本的逻辑不产生修改的情况下,对原来的函数进行增强。大大降低代码的耦合度,提高程序的可重用性。可以说是面向对象思想下的一个衍生,但是在某些情况下,要优于面向对象。比如日志、鉴权等情况下,使用AOP,可以很轻松的进行实现。本文对系统访问日志采用AOP的方式进行开发。
12+
13+
## 引入依赖
14+
不论是spring boot 还是 springMVC都需要引用下面的两个包
15+
{% highlight java %}
16+
<dependency>
17+
<groupId>org.aspectj</groupId>
18+
<artifactId>aspectjweaver</artifactId>
19+
<version>1.9.6</version>
20+
</dependency>
21+
<dependency>
22+
<groupId>org.aspectj</groupId>
23+
<artifactId>aspectjrt</artifactId>
24+
<version>1.9.6</version>
25+
</dependency>
26+
{% endhighlight %}
27+
28+
在spring boot中还需要引入
29+
{% highlight java %}
30+
<dependency>
31+
<groupId>org.springframework.boot</groupId>
32+
<artifactId>spring-boot-starter-aop</artifactId>
33+
</dependency>
34+
{% endhighlight %}
35+
36+
在springMVC中,需要引入
37+
{% highlight java %}
38+
<dependency>
39+
<groupId>org.springframework</groupId>
40+
<artifactId>spring-aop</artifactId>
41+
<version>5.2.3.RELEASE</version>
42+
</dependency>
43+
{% endhighlight %}
44+
45+
## 创建切面类
46+
47+
一个切面类需要定义一个切点(一般情况下是某个函数,也可能是某个属性等)。再根据切点进行增强处理。对于系统访问日志来说,我做了如下两个后置增强
48+
{% highlight java %}
49+
@Aspect
50+
@Component
51+
public class LogAspect {
52+
53+
private HttpServletRequest request;
54+
55+
//创建切点。所有的控制器
56+
@Pointcut("execution(* com.bc.center.controller.*.*Controller.*(..))")
57+
public void cutPoint(){
58+
}
59+
60+
/**
61+
* 前置赋值
62+
*/
63+
@Before("cutPoint()")
64+
public void beforeController(){
65+
request = getRequest();
66+
}
67+
68+
/**
69+
* 请求成功记录
70+
*/
71+
@AfterReturning("cutPoint()")
72+
public void requestSuccess(){
73+
SystemLogDTO systemLogDTO = new SystemLogDTO();
74+
systemLogDTO.setIsError(0);
75+
saveLog(systemLogDTO);
76+
}
77+
78+
/**
79+
* 请求记录失败
80+
*/
81+
@AfterThrowing(value = "cutPoint()",throwing = "e")
82+
public void requestFail(Throwable e){
83+
SystemLogDTO systemLogDTO = new SystemLogDTO();
84+
systemLogDTO.setIsError(1);
85+
//获取异常位置
86+
Map errorDetail = new HashMap(2);
87+
StackTraceElement[] stack = e.getStackTrace();
88+
for (StackTraceElement stackTraceElement : stack){
89+
String className = stackTraceElement.getClassName();
90+
int lineNumber = stackTraceElement.getLineNumber();
91+
if(className.contains("com.bc") && lineNumber > 0){
92+
//存在当前项目目录异常,记录异常类和行数
93+
errorDetail.put("className",className);
94+
errorDetail.put("lineNumber",lineNumber);
95+
}
96+
}
97+
if(errorDetail.size() > 0){
98+
errorDetail.put("message",e.getMessage());
99+
//记录成功,保存到对象中
100+
systemLogDTO.setErrorDetail(JsonUtil.toJSONString(errorDetail));
101+
}
102+
103+
saveLog(systemLogDTO);
104+
}
105+
}
106+
{% endhighlight %}
107+
108+
DTO类的属性如下:
109+
{% highlight java %}
110+
public class SystemLogDTO {
111+
112+
/**
113+
* 请求url
114+
*/
115+
private String uri;
116+
117+
/**
118+
* 请求方式
119+
*/
120+
private String requestType;
121+
122+
/**
123+
* 请求参数
124+
*/
125+
private String params;
126+
127+
/**
128+
* 是否是抛出异常时的请求
129+
*/
130+
private Integer isError;
131+
132+
/**
133+
* 存在异常时,记录应用内的
134+
*/
135+
private String errorDetail;
136+
137+
}
138+
{% endhighlight %}
139+
140+
@Aspect:声明当前类是切面类。
141+
142+
@Pointcut:设置切点。通过execution关键字进行设置
143+
> * com.bc.center.controller.*.*Controller.*(..))
144+
> 第一个 * 参数是返回值 *表示任何返回值
145+
> 第二个 com.bc.center.controller.*.*Controller.* 是匹配得切点路径
146+
> 第三个 (..) 是请求参数。 ..表示任意参数
147+
148+
@Before:在切点之前执行
149+
@After:在切点之后执行
150+
@AfterReturn:切点正常返回时执行
151+
@AfterThrowing:切点抛出异常时执行
152+
153+
这里我使用了**@AfterReturn****@AfterThrowing**,为了区分记录正常返回和异常返回的日志。
154+
155+
## 小结
156+
157+
以往采用的方案是以拦截器的方式进行记录。需要配置拦截器以及放行的url,相对要繁琐一些。使用切面的话,可以以所有的控制器为切点,只需要一个切面类,就可以实现日志的访问记录,最重要的是对原来的逻辑没有任何入侵。

0 commit comments

Comments
 (0)