使用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();
}
}
使用AOP监控用户操作并插入数据库的更多相关文章
- aop 记录用户操作(一)
转载: http://www.cnblogs.com/guokai870510826/p/5981015.html 使用标签来设置需要的记录 实例:@ISystemLog() @Controller ...
- Linux下监控用户操作轨迹
在实际工作当中,都会碰到误删除.误修改配置文件等事件.如果没有堡垒机,要在linux系统上查看到底谁对配置文件做了误操作,特别是遇到删库跑路的事件,当然可以通过history来查看历史命令记录,但如果 ...
- TinyFrame尾篇:整合Spring AOP实现用户认证
创建Manager用户验证表 这一篇主要讲解使用AOP对用户操作进行验证,如果通过验证,则继续执行,反之,则不能执行.其思想和上一篇完全一致. 由于需要用到用户认证,所以我们新建一个Manager实体 ...
- 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录
在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...
- 我使用Spring AOP实现了用户操作日志功能
我使用Spring AOP实现了用户操作日志功能 今天答辩完了,复盘了一下系统,发现还是有一些东西值得拿出来和大家分享一下. 需求分析 系统需要对用户的操作进行记录,方便未来溯源 首先想到的就是在每个 ...
- MySQL数据库(6)_用户操作与权限管理、视图、存储过程、触发器、基本函数
用户操作与权限管理 MySQL用户操作 创建用户 方法一: CREATE USER语句创建 CREATE USER "用户名"@"IP地址" IDENTIFIE ...
- Spring AOP使用注解记录用户操作日志
最后一个方法:核心的日志记录方法 package com.migu.cm.aspect; import com.alibaba.fastjson.JSON; import com.migu.cm.do ...
- python scrapy 插入数据库的操作
需要安装这个 pymysql 写法还是很简单的 # -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget t ...
- Mysql 创建权限较小的用户(只对特定数据库有操作权限)
项目开发过程中,因为root的权限太大,可能对其他数据库造成修改.故创建一权限较小的用户,使其只能对特定的数据库操作,以保证数据安全. 主要语句如下: grant all on bos19.* to ...
随机推荐
- 大数据学习路线copy自淘宝
一.hadoop视频学习(入门到精通) 二.数据挖掘(入门到精通) 三.Hadoop学习路线 1.开发前期准备 首先,如果你没有Java和Linux基础,建议你先简单学一下这两门课程,此宝贝里面都为你 ...
- 基于Docker部署私有npm
NPM作为前端最cool及最烂的包管理器,它解决困扰前端工程化发展中代码模块管理的大问题.但是随着业务需求的发展,我们的代码从以前的单项目复用,延伸出了多项目复用的需求.本来项目之间代码复用管理的情景 ...
- [hdu4662]MU Puzzle(找规律)
题意:给你一个串MI,按照三种规则1:M后面的部分加倍 2:III->U 3:删去连续的两个UU.看看能否变为给定的串 解题关键:将所有的U转化为I,发现 t+k*6=2^i -> =2^ ...
- Qt Console Application
代码编译完生成的.o文件(又称对象文件,是可执行文件)和链接.o文件形成的.exe可执行文件都保存在“build-Project-Desktop_Qt_5_8_0_GCC_64bit-Debug”中. ...
- linux 环境变量恢复默认值
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin 在linux命令下如何访问一个ur ...
- 打开*.gd文件的方法
问题来了: 你可能会收到*.gd的公文,那么一般的阅读器都打不开…… 解决方法: 使用书生阅读器(三合一版)来打开 地址:http://www.du8.com/download/index.html
- c#中Marshal.Copy()方法的使用
c#中Marshal.Copy方法的使用 Marshal.copy()方法用来在托管对象(数组)和非托管对象(IntPtr)之间进行内容的复制 函数有很多重载,如下所示: Copy(array< ...
- IPMITOOL 配置BMC用户设置
IPMITOOL 配置BMC用户设置 本文档共介绍5条ipmi设置user的命令,这些命令需要使用root权限才能使用,其中- H为需要操作的BMC ip,-I lanplus为使用rmcp+协议发送 ...
- iphone5 A1429国行IOS8.4.1 越狱 完美使用电信3G
国航 8.4.1,越狱,使用电信3G,能打电话,能发短信,正常上网使.(越狱降级方式,请参照本文末端连接) 有好多人说不管怎么试都是无服务,请查看 设置-蜂窝移动网络-漫游里面,必须只有 语音漫游 这 ...
- React 从入门到进阶之路(四)
之前的文章我们介绍了 React 绑定属性( 绑定class 绑定style).引入图片 循环数组渲染数据.接下来我们将介绍 React 事件,方法, React定义方法的几种方式 获取数据 改 ...