欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring Boot AOP记录用户操作日志

程序员文章站 2022-04-14 16:32:18
在Spring框架中,使用AOP配合自定义注解可以方便的实现用户操作的监控。首先搭建一个基本的Spring Boot Web环境开启Spring Boot,然后 引入必要依赖: org.springframework.boot

在spring框架中,使用aop配合自定义注解可以方便的实现用户操作的监控。首先搭建一个基本的spring boot web环境开启spring boot,然后

引入必要依赖:

 <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-jdbc</artifactid>
        </dependency>

        <!-- aop依赖 -->
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-aop</artifactid>
        </dependency>

        <!-- mysql驱动 -->
        <dependency>
            <groupid>mysql</groupid>
            <artifactid>mysql-connector-java</artifactid>
            <version>5.1.41</version>
        </dependency>

        <!-- druid数据源驱动 -->
        <dependency>
            <groupid>com.alibaba</groupid>
            <artifactid>druid-spring-boot-starter</artifactid>
            <version>1.1.10</version>
        </dependency>

        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</artifactid>
        </dependency>

自定义注解

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

@target(elementtype.method)
@retention(retentionpolicy.runtime)
public @interface log {
    string value() default "";
}

创建库表和实体

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

Spring Boot AOP记录用户操作日志

 

 

 

 实体:

public class syslog implements serializable {

    private integer id;
    private string username;
    private string operation;
    private integer time;
    private string method;
    private string params;
    private string ip;
    private date createtime;

............

dao:

public interface syslogdao {
    void savesyslog(syslog syslog);
}
@repository
public class syslogdaoimpl implements syslogdao {

    @autowired
    private jdbctemplate jdbctemplate;

    @override
    public void savesyslog(syslog syslog) {

        system.out.println(syslog);

        stringbuffer sql = new stringbuffer("insert into sys_log ");
        sql.append("(id,username,operation,time,method,params,ip,create_time) ");
        sql.append("values(null,?,?,?,?,?,?,?)");
        string sql2=sql.tostring();
        jdbctemplate.update(sql2,syslog.getusername(),syslog.getoperation(),syslog.gettime(),syslog.getmethod(),syslog.getparams(),syslog.getip(),syslog.getcreatetime());
        jdbctemplate.update(sql2);

    }
}

aspect:

@aspect
@component
public class logaspect {

    @autowired
    private syslogdao syslogdao;

    @pointcut("@annotation(com.lc.aop.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);
    }
}

controller:

@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) { }
}

工具类:

public class iputils {
    /**
     * 获取ip地址
     *
     * 使用nginx等反向代理软件, 则不能通过request.getremoteaddr()获取ip地址
     * 如果使用了多级反向代理的话,x-forwarded-for的值并不止一个,而是一串ip地址,x-forwarded-for中第一个非unknown的有效ip字符串,则为真实ip地址
     */
    public static string getipaddr(httpservletrequest request) {

        string ip = request.getheader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsignorecase(ip)) {
            ip = request.getheader("proxy-client-ip");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsignorecase(ip)) {
            ip = request.getheader("wl-proxy-client-ip");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsignorecase(ip)) {
            ip = request.getremoteaddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }
}

 

public class httpcontextutils {
    public static httpservletrequest gethttpservletrequest() {
        return ((servletrequestattributes) requestcontextholder.getrequestattributes()).getrequest();
    }
}

application.properties

spring.datasource.driver-class-name=com.mysql.jdbc.driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.username=root
spring.datasource.password=123456

 

项目结构:

Spring Boot AOP记录用户操作日志

 

 

 

访问后:

Spring Boot AOP记录用户操作日志