引入依赖

<!--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();
}
}

												

使用AOP监控用户操作并插入数据库的更多相关文章

  1. aop 记录用户操作(一)

    转载: http://www.cnblogs.com/guokai870510826/p/5981015.html 使用标签来设置需要的记录 实例:@ISystemLog() @Controller ...

  2. Linux下监控用户操作轨迹

    在实际工作当中,都会碰到误删除.误修改配置文件等事件.如果没有堡垒机,要在linux系统上查看到底谁对配置文件做了误操作,特别是遇到删库跑路的事件,当然可以通过history来查看历史命令记录,但如果 ...

  3. TinyFrame尾篇:整合Spring AOP实现用户认证

    创建Manager用户验证表 这一篇主要讲解使用AOP对用户操作进行验证,如果通过验证,则继续执行,反之,则不能执行.其思想和上一篇完全一致. 由于需要用到用户认证,所以我们新建一个Manager实体 ...

  4. 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

    在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...

  5. 我使用Spring AOP实现了用户操作日志功能

    我使用Spring AOP实现了用户操作日志功能 今天答辩完了,复盘了一下系统,发现还是有一些东西值得拿出来和大家分享一下. 需求分析 系统需要对用户的操作进行记录,方便未来溯源 首先想到的就是在每个 ...

  6. MySQL数据库(6)_用户操作与权限管理、视图、存储过程、触发器、基本函数

    用户操作与权限管理 MySQL用户操作 创建用户 方法一: CREATE USER语句创建 CREATE USER "用户名"@"IP地址" IDENTIFIE ...

  7. Spring AOP使用注解记录用户操作日志

    最后一个方法:核心的日志记录方法 package com.migu.cm.aspect; import com.alibaba.fastjson.JSON; import com.migu.cm.do ...

  8. python scrapy 插入数据库的操作

    需要安装这个 pymysql 写法还是很简单的 # -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget t ...

  9. Mysql 创建权限较小的用户(只对特定数据库有操作权限)

    项目开发过程中,因为root的权限太大,可能对其他数据库造成修改.故创建一权限较小的用户,使其只能对特定的数据库操作,以保证数据安全. 主要语句如下: grant all on bos19.* to ...

随机推荐

  1. .net 缓存之文件缓存依赖

    CaCheHelp 类中代码如下: #region 根据键从缓存中读取保持的数据 /// <summary> /// 根据键从缓存中读取保持的数据 /// </summary> ...

  2. 面试题: !=!=未看12 略多 sql语句练习 非常 有用

    JAVA面试总结 2015年03月25日 16:53:40 阅读数:4306 刚才看到的,先转载过来,没准以后用到…… 面试总结 2013年8月6日: 问题2:Hibernate的核心接口有哪些?   ...

  3. java多态和强制类型转换

    子类可以赋值给超类,称之为向上转型,这个是自动的. 超类不可以赋值给子类,这个是向下转型,需要我们手动实现. 赋值给超类的子类引用在运行期间将表现出不同的特性,这就是多态. 小类型    可转换为   ...

  4. Object.prototype.toString.call(arg)详解

    经常能碰到Object.prototype.toString.call对参数类型进行判断,一开始只知道怎么使用,却不了解具体实现的原理,最近恶补了一下相关知识,写个笔记加强理解,有什么不对的请指教. ...

  5. grep的常用命令语法

    grep的常用命令语法 1. 双引号引用和单引号引用在g r e p命令中输入字符串参数时,最好将其用双引号括起来.例如:"m y s t r i n g".这样做有两个原因,一是 ...

  6. 利用css实现鼠标经过元素,下划线由中间向两边展开

    代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  7. (linux)修改MySQL密码方法

    1,在/etc/my.cnf末尾  加入skip-grant-tables,保存,跳过身份验证. 2,重启MySql,使刚才修改的配置生效. 3,终端输入mysql,然后再输入use mysql; 4 ...

  8. 为什么要使用func.call(this)

    1.为什么要使用func.call(this) 在正常模式下,js 函数里那些你没有声明就使用的变量,其实是访问的全局对象的属性.但是在严格模式下,不允许这种语法,所有变量都必须要显示声明,所以如果你 ...

  9. Nginx + Tomcat7 + redis session一致性问题

    Nginx 作负载均衡时,由于是每次都需要把请求分发到不同的机器,同一个用户在一台机器上创建了 session,下一次的请求很有可能会转发到另外一台机器,会造成 session 丢失.我们可以使用 R ...

  10. [Xcode 实际操作]四、常用控件-(1)UIButton控件的使用

    目录:[Swift]Xcode实际操作 本文将演示按钮控件的使用,按钮是用户界面中最常见的交互控件 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import U ...