使用AOP監控用戶操作並插入數據庫


引入依賴

<!--spring切面aop依賴-->

<dependency>

  <groupId>org.springframework.boot</groupId>

  <artifactId>spring-boot-starter-aop</artifactId>

</dependency>

 

在application.properties添加配置

spring.aop.auto=true

 

 

 

1.創建自定義注解類

當然該注解類可以使用spring自帶注解類:@Before,@After,@AfterRuturning ,@AfterThrowing ,@Around 。

只是這5種方式的作用不同:

 

(1)Before ---在所攔截方法執行前執行;

 

(2)After ---在所攔截方法執行后執行;

 

(3)AfterRuturning  ---在所攔截方法返回值后,執行;

 

(4)AfterThrowing ---當所攔截方法拋出異常時,執行;

 

(5)Around ---最為復雜的切入方式,剛方式可以包括上述4個方式。

 

import java.lang.annotation.*;

/**
 * 自定義注解類
 * @author MrRoot
 * @date 2019-01-16
 */
@Target(ElementType.METHOD) //注解放置的目標位置,METHOD是可注解在方法級別上
@Retention(RetentionPolicy.RUNTIME) //注解在哪個階段執行
@Documented //生成文檔
public @interface MyLog {
    String value() default "";
}

 

2.生成日志實體類

博主使用的是mybatisplus根據表信息生成的實體類,當然也可以使用普通實體類。

import com.baomidou.mybatisplus.enums.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.enums.FieldFill;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableName;
import java.io.Serializable;

/**
 * <p>
 * 日志表
 * </p>
 *
 * @author MrRoot
 * @since 2019-01-16
 */
@TableName("research_log")
public class Log extends Model<Log> {

    private static final long serialVersionUID = 1L;

    /**
     * 主鍵
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 用戶id
     */
    @TableField("user_id")
    private Long userId;
    /**
     * 操作時用戶的ip地址
     */
    private String ip;
    /**
     * 操作詳情
     */
    private String operation;
    /**
     * 創建時間
     */
    @TableField(value = "gmt_create", fill = FieldFill.INSERT)
    private Date gmtCreate;
    /**
     * 更新時間
     */
    @TableField(value = "gmt_modified", fill = FieldFill.INSERT_UPDATE)
    private Date gmtModified;


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getOperation() {
        return operation;
    }

    public void setOperation(String operation) {
        this.operation = operation;
    }

    public Date getGmtCreate() {
        return gmtCreate;
    }

    public void setGmtCreate(Date gmtCreate) {
        this.gmtCreate = gmtCreate;
    }

    public Date getGmtModified() {
        return gmtModified;
    }

    public void setGmtModified(Date gmtModified) {
        this.gmtModified = gmtModified;
    }

    @Override
    protected Serializable pkVal() {
        return this.id;
    }

    @Override
    public String toString() {
        return "Log{" +
        ", id=" + id +
        ", userId=" + userId +
        ", ip=" + ip +
        ", operation=" + operation +
        ", gmtCreate=" + gmtCreate +
        ", gmtModified=" + gmtModified +
        "}";
    }
}

 

3.系統日志:處理切面類

其中最后的insert方法為mybatisplus封裝好的插入方法,如果使用普通實體類則需要自己寫插入數據庫的方法。

IPUtils方法見附錄

 
        
import com.alibaba.fastjson.JSON;

import com.panshi.cecdc.research.entity.Log;
import com.panshi.cecdc.research.service.LogService;
import com.panshi.cecdc.research.util.IPUtils;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * 系統日志:切面處理類
 * @author MrRoot
 * @date 2019-01-16
 */
@Aspect
@Component
public class SysLogAspect {

    @Autowired
    private LogService logService;

    /**
     * 定義切點 @Pointcut
     * 在注解的位置切入代碼
     */
    @Pointcut("@annotation(com.panshi.cecdc.research.common.MyLog)")
    public void logPointCut() {
    }

    /**
     * 切面 配置通知
     * @param joinPoint
     */
    @AfterReturning("logPointCut()")//這里可以選擇日志插入的方式
    public void saveSysLog(JoinPoint joinPoint) {
        //保存日志
        Log log = new Log();

        //從切面織入點處通過反射機制獲取織入點處的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //獲取切入點所在的方法
        Method method = signature.getMethod();

        //獲取操作
        MyLog myLog = method.getAnnotation(MyLog.class);
        if (myLog != null) {
            String value = myLog.value();
            //保存獲取的操作
            log.setOperation(value);
        }

        //獲取請求的類名
        //String className = joinPoint.getTarget().getClass().getName();
        //獲取請求的方法名
        //String methodName = method.getName();
        //sysLog.setMethod(className + "." + methodName);

        //請求的參數
        //Object[] args = joinPoint.getArgs();
        //將參數所在的數組轉換成json
        //String params = JSON.toJSONString(args);
        //log.setParams(params);

        log.setGmtCreate(new Date());
        //獲取用戶名
        log.setUserId((Long)SecurityUtils.getSubject().getSession().getAttribute("userId"));
        //獲取用戶ip地址
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        log.setIp(IPUtils.getIp(request));
        //調用service保存SysLog實體類到數據庫
        logService.insert(log);
    }

}

 

4.在需要監控的controller方法上加上注解

@MyLog(value = "用戶詳情")//操作類型
@GetMapping("/detail")
public Result detail(@RequestParam("id") Long id){

    return Result.createBySuccess(sysUserService.detail(id));
}

 

5.結果示例

附錄:

IPUtils:

 
        
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * ip工具類
 * @author MrRoot
 * @date 2019-01-16
 */
public class IPUtils {

    private static final String UNKNOWN = "unKnown";

    public static String getIp(HttpServletRequest request) {

        String ip = request.getHeader("X-Forwarded-For");
        if(StringUtils.isNotEmpty(ip) && !UNKNOWN.equalsIgnoreCase(ip)){
        //多次反向代理后會有多個ip值,第一個ip才是真實ip
            int index = ip.indexOf(",");
            if(index != -1){
                return ip.substring(0,index);
            }else{
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if(StringUtils.isNotEmpty(ip) && !UNKNOWN.equalsIgnoreCase(ip)){
            return ip;
        }
        return request.getRemoteAddr();
    }
}

 

 

 

 

 

 

 

 

 

 

 
        
 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM