java aop日志保存_Spring Boot AOP记录用户操作日志

在Spring框架中,使用AOP配合自定义注解可以方便的实现用户操作的监控。首先搭建一个基本的Spring Boot Web环境开启Spring Boot,然后引入必要依赖:

org.springframework.boot

spring-boot-starter-jdbc

org.springframework.boot

spring-boot-starter-aop

com.oracle

ojdbc6

6.0

com.alibaba

druid-spring-boot-starter

1.1.6

自定义注解

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

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface Log {

String value() default "";

}

创建库表和实体

在数据库中创建一张sys_log表,用于保存用户的操作日志,数据库采用oracle 11g:

CREATE TABLE "SCOTT"."SYS_LOG" (

"ID" NUMBER(20) NOT NULL ,

"USERNAME" VARCHAR2(50 BYTE) NULL ,

"OPERATION" VARCHAR2(50 BYTE) NULL ,

"TIME" NUMBER(11) NULL ,

"METHOD" VARCHAR2(200 BYTE) NULL ,

"PARAMS" VARCHAR2(500 BYTE) NULL ,

"IP" VARCHAR2(64 BYTE) NULL ,

"CREATE_TIME" DATE NULL

);

COMMENT ON COLUMN "SCOTT"."SYS_LOG"."USERNAME" IS '用户名';

COMMENT ON COLUMN "SCOTT"."SYS_LOG"."OPERATION" IS '用户操作';

COMMENT ON COLUMN "SCOTT"."SYS_LOG"."TIME" IS '响应时间';

COMMENT ON COLUMN "SCOTT"."SYS_LOG"."METHOD" IS '请求方法';

COMMENT ON COLUMN "SCOTT"."SYS_LOG"."PARAMS" IS '请求参数';

COMMENT ON COLUMN "SCOTT"."SYS_LOG"."IP" IS 'IP地址';

COMMENT ON COLUMN "SCOTT"."SYS_LOG"."CREATE_TIME" IS '创建时间';

CREATE SEQUENCE seq_sys_log START WITH 1 INCREMENT BY 1;

库表对应的实体:

public class SysLog implements Serializable{

private static final long serialVersionUID = -6309732882044872298L;

private Integer id;

private String username;

private String operation;

private Integer time;

private String method;

private String params;

private String ip;

private Date createTime;

// get,set略

}

保存日志的方法

为了方便,这里直接使用Spring JdbcTemplate来操作数据库。定义一个SysLogDao接口,包含一个保存操作日志的抽象方法:

public interface SysLogDao {

void saveSysLog(SysLog syslog);

}

其实现方法:

@Repository

public class SysLogDaoImp implements SysLogDao {

@Autowired

private JdbcTemplate jdbcTemplate;

@Override

public void saveSysLog(SysLog syslog) {

StringBuffer sql = new StringBuffer("insert into sys_log ");

sql.append("(id,username,operation,time,method,params,ip,create_time) ");

sql.append("values(seq_sys_log.nextval,:username,:operation,:time,:method,");

sql.append(":params,:ip,:createTime)");

NamedParameterJdbcTemplate npjt = new NamedParameterJdbcTemplate(this.jdbcTemplate.getDataSource());

npjt.update(sql.toString(), new BeanPropertySqlParameterSource(syslog));

}

}

切面和切点

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

@Aspect

@Component

public class LogAspect {

@Autowired

private SysLogDao sysLogDao;

@Pointcut("@annotation(com.springboot.annotation.Log)")

public void pointcut() { }

@Around("pointcut()")

public Object around(ProceedingJoinPoint point) {

Object result = null;

long beginTime = System.currentTimeMillis();

try {

// 执行方法

result = point.proceed();

} catch (Throwable e) {

e.printStackTrace();

}

// 执行时长(毫秒)

long time = System.currentTimeMillis() - beginTime;

// 保存日志

saveLog(point, time);

return result;

}

private void saveLog(ProceedingJoinPoint joinPoint, long time) {

MethodSignature signature = (MethodSignature) joinPoint.getSignature();

Method method = signature.getMethod();

SysLog sysLog = new SysLog();

Log logAnnotation = method.getAnnotation(Log.class);

if (logAnnotation != null) {

// 注解上的描述

sysLog.setOperation(logAnnotation.value());

}

// 请求的方法名

String className = joinPoint.getTarget().getClass().getName();

String methodName = signature.getName();

sysLog.setMethod(className + "." + methodName + "()");

// 请求的方法参数值

Object[] args = joinPoint.getArgs();

// 请求的方法参数名称

LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();

String[] paramNames = u.getParameterNames(method);

if (args != null && paramNames != null) {

String params = "";

for (int i = 0; i < args.length; i++) {

params += " " + paramNames[i] + ": " + args[i];

}

sysLog.setParams(params);

}

// 获取request

HttpServletRequest request = HttpContextUtils.getHttpServletRequest();

// 设置IP地址

sysLog.setIp(IPUtils.getIpAddr(request));

// 模拟一个用户名

sysLog.setUsername("mrbird");

sysLog.setTime((int) time);

sysLog.setCreateTime(new Date());

// 保存系统日志

sysLogDao.saveSysLog(sysLog);

}

}

测试

TestController:

@RestController

public class TestController {

@Log("执行方法一")

@GetMapping("/one")

public void methodOne(String name) { }

@Log("执行方法二")

@GetMapping("/two")

public void methodTwo() throws InterruptedException {

Thread.sleep(2000);

}

@Log("执行方法三")

@GetMapping("/three")

public void methodThree(String name, String age) { }

}

最终项目目录如下图所示:

588fe40955952a496f9b4a1d2a0bd114.png

启动项目,分别访问:

http://localhost:8080/web/one?name=KangKang

http://localhost:8080/web/three?name=Mike&age=25

查询数据库:

SQL> select * from sys_log order by id;

ID USERNAME OPERATION TIME METHOD PARAMS IP CREATE_TIME

---------- ---------- ---------- ---------- ------------------------------ ------------------------------ ---------- --------------

11 mrbird 执行方法一 6 com.springboot.controller.Test name: KangKang 127.0.0.1 08-12月-17

Controller.methodOne()

12 mrbird 执行方法二 2000 com.springboot.controller.Test 127.0.0.1 08-12月-17

Controller.methodTwo()

13 mrbird 执行方法三 0 com.springboot.controller.Test name: Mike age: 25 127.0.0.1 08-12月-17

Controller.methodThree()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值