springboot 基于Aop实现自定义日志管理
一、相关依赖(maven)
// 引入springboot Aop依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
二、代码实现
1. 添加自定义定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
1. 日志注解
2. 3. @author xu_cxiang
*/
@Target(ElementType.METHOD) // 方法注解
@Retention(RetentionPolicy.RUNTIME) // 运行时可见
public @interface OtherLog {
String logName();// 记录日志的名称
}
2. 定义日志实体
/**
*
* <p>日志实体<p>
*
* @author xu_cxiang<br>
* @version 1.0
*
*/
public class OtherLog {
/**
* 主键
*/
private int id;
/**
* 日志名称
*/
private String name;
/**
* 日志类型
*/
private String type;
/**
* 本机ip
*/
private String ip;
/**
* 用户主键
*/
private int userId;
/**
* 类名称
*/
private String className;
/**
* 方法名称
*/
private String mothod;
/**
* 创建时间
*/
private String createTime;
/**
* 是否成功
*/
private String succeed;
/**
* 请求参数
*/
private String params;
/**
* 备注
*/
private String remarks;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMothod() {
return mothod;
}
public void setMothod(String mothod) {
this.mothod = mothod;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getSucceed() {
return succeed;
}
public void setSucceed(String succeed) {
this.succeed = succeed;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
@Override
public String toString() {
return "OtherLog [id=" + id + ", name=" + name + ", type=" + type
+ ", ip=" + ip + ", userId=" + userId + ", className="
+ className + ", mothod=" + mothod + ", createTime="
+ createTime + ", succeed=" + succeed + ", params=" + params
+ ", remarks=" + remarks + "]";
}
}
3. 定义日志AOP切面类(环绕通知)
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import cn.stylefeng.guns.core.common.annotion.OtherLogAnno;
import cn.stylefeng.guns.core.util.AddressUtils;
import cn.stylefeng.guns.modular.system.model.OtherLog;
/**
*
* <p>AOP日志切面类<p>
* * @author xu_cxiang<br>
* @version 1.0
* */
@Aspect
@Component
@Order(3)
public class OtherLogAop {
/**
* 环绕通知记录日志通过注解匹配到需要增加日志功能的方法
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("@annotation(cn.stylefeng.guns.core.common.annotion.OtherLogAnno)")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
// 1.方法执行前的处理,相当于前置通知
// 获取方法签名
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
// 获取类名
String class_name = pjp.getTarget().getClass().getName();
// 获取方法
Method method = methodSignature.getMethod();
// 获取请求参数
String params = Arrays.toString(pjp.getArgs()).replace("[", "")
.replace("]", "");
// 获取方法上面的注解
OtherLogAnno otherLogAop = method.getAnnotation(OtherLogAnno.class);
// 获取操作描述的属性值
String name = otherLogAop.logName();
// 创建一个日志对象(准备记录日志)
OtherLog log = new OtherLog();
log.setName(name);
log.setType("非业务日志");// 操作说明
log.setMothod(method.getName());
log.setClassName(class_name);
log.setParams(params);
log.setUserId(1);
log.setIp(AddressUtils.getV4IP());
log.setRemarks("");
Object result = null;
try {
// 让代理方法执行
result = pjp.proceed();
// 2.相当于后置通知(方法成功执行之后走这里)
log.setSucceed("成功");// 设置操作结果
} catch (SQLException e) {
// 3.相当于异常通知部分
log.setSucceed("失败");// 设置操作结果
} finally {
// 4.相当于最终通知
log.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));// 设置操作日期
// 打印日志记录
System.out.println(log.toString());
// 在此处直接调用service插入数据库也可以。
// 也可以学习guns一样利用线程池进行日志存储。
}
return result;
}
}
AOP其他通知模式
* @Before 前置通知
* @After 后置通知
* @AfterReturning 后置返回通知(可以在该通知内获取请求返回数据)
* @AfterThrowing 后置异常通知
4. 使用注解记录日志
在controller或service实现层使用@OtherLogAnno注解
@Override
@OtherLogAnno(logName = "测试日志输出")
public String getLog() {
return "success";
}
结果如下:
OtherLog :{id=0, name=测试日志输出, type=非业务日志, ip=192.168.1.1, userId=1, className=cn.stylefeng.guns.modular.system.service.impl.TestServiceImpl, mothod=getLog, createTime=2020-01-06 16:14:05, succeed=成功, params="", remarks=""}