一、背景

​ 在公司写业务的时候,都会有保存日志的操作,方便出错的时候进行排查;一般不仅仅在数据库中保存日志,

也会在后端控制台打印一些需要的信息。在这里,一般使用 AOP 织入的方式将日志保存在数据库中,使用一些日

志包将某些 Controller 层的信息打印在控制台。

二、准备

Entiy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Entity
@Table(name = "log")
@EntityListeners(AuditingEntityListener.class)
public class Log implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY )
@Column(name = "id")
private Long id;

@Column(name = "title", columnDefinition = "VARCHAR(100) COMMENT '标题'")
private String title;

@Column(name = "author", columnDefinition = "VARCHAR(255) COMMENT '作者'")
private String author;

@Column(name = "content", columnDefinition = "TEXT COMMENT '内容'")
private String content;

// get 和 set 省略

注: 这里是使用 Spring Data JPA 自动生成的数据库对应实体,导入相关依赖后,可以先运行一遍,看数据库

是否生成对应实体;然后自行在数据库中插入几条数据。

Repository:

1
2
3
public interface LogRepository extends JpaRepository<Log, Long> {

}

注: 这里只要继承 JpaRepository ,这个 repository 也继承了别的 repository(里面有一些常见的方法可以

调用)

Service:

1
2
3
4
5
6
7
8
9
10
11
@Service
public class LogService {

@Autowired
LogRepository logRepository;

public List<Log> getAllLog() {
List<Log> logs = logRepository.findAll();
return logs;
}
}

注: 这里就不写接口,再去实现了

Controller:

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class LogController {

@Autowired
LogService logService;

@GetMapping("/list")
public List<Log> getAll() {
List<Log> logs = logService.getAllLog();
return logs;
}
}

再使用 Postman 等工具进行一次测试就行

三、使用注解的方式进行 AOP

首先定义一个方法级别的 @Log 注解,用于标注需要监控的方法:

1
2
3
4
5
6
7
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {

String value() default "";

}

定义一个LogAspect类,使用 @Aspect 标注让其成为一个切面,切点为使用 @Log 注解标注的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Aspect
@Component
public class LogAspec {

private final static Logger logger = LoggerFactory.getLogger(LogAspec.class);

@Pointcut("@annotation(org.wangba.springboot013aop.antoation.Log)")
public void pointcut() { }

@Before("pointcut()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
logger.info("Start Time: {}", System.currentTimeMillis());
}


@After("pointcut()")
public void doAfter() throws Throwable {
logger.info("End Time: {}", System.currentTimeMillis());
}
}

再在 Controller 层的方法上加上 @Log 注解:

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
public class LogController {

@Autowired
LogService logService;

@Log("获得所有文章")
@GetMapping("/list")
public List<Article> getAll() {
List<Article> articles = logService.getAllLog();
return articles;
}
}

此时再在 Postman 中测试一次,你就可以看到控制台会打印如下结果:

image-20200903214650730

在公司业务中,我们一般都是在 @Before 进行一些请求信息等, @After 在控制台打印一些信息,并将结

果直接存到数据库中的日志表中。

评论