使用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 ...
随机推荐
- [tyvj1860]后缀数组
题目链接:http://www.tyvj.cn/p/1860 解题关键:模板题.贴一个代码详解 http://www.cnblogs.com/staginner/archive/2012/02/02/ ...
- 30、 bowtie和bowtie2使用条件区别及用法
转载:http://blog.csdn.net/soyabean555999/article/details/62235577 一.转录组还是基因组? map常用的工具有bowtie/bowtie2, ...
- 9、scala函数式编程-集合操作
一.集合操作1 1.Scala的集合体系结构 // Scala中的集合体系主要包括:Iterable.Seq.Set.Map.其中Iterable是所有集合trait的根trai.这个结构与Java的 ...
- C# 生成chm帮助文件
引用博友的博客地址,里面有详细资料,谢谢博主分享 http://blog.csdn.net/snakorse/article/details/44963015
- SDUT2140图结构练习——判断给定图是否存在合法拓扑序列
拓扑序列的判断方法为不存在有向环,代码实现的话有两种,一种是直接去判断是否存在环,较为难理解一些,另一种的话去判断结点入度,如果存在的入度为0的点大于一个,则该有向图肯定不存在一个确定的拓扑序列 #i ...
- 《鸟哥的Linux私房菜》读书笔记2
1. 压缩后缀与压缩程序: *.Z compress 程序压缩的档案; *.bz2 bzip2 程序压缩的档案; *.gz gzip 程序压缩的档案; *.tar tar 程序打包的数据,并没有压缩过 ...
- 【maven setting.xml】
<!--声明语句--> <?xml version="1.0" encoding="UTF-8"?> <settings xmln ...
- C# 中介者模式
中介者模式 中介者模式,定义了一个中介对象来封装一系列对象之间的交互关系.中介者使各个对象之间不需要显式地相互引用,从而使耦合性降低,而且可以独立地改变它们之间的交互行为. 结构: 中介者模式设计两个 ...
- Python中的try和except语句
Python中是通过缩进来解析代码块的,要特别注意tab和空格符,两者不可以混用,通常情况下用四个空格来代替tab键 下面通过一个简单的例子来说明 提示用户输入工作的时间和每小时的时薪,如果超过40个 ...
- hdu2586(lca模板 / tarjan离线 + RMQ在线)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意: 给出一棵 n 个节点的带边权的树, 有 m 个形如 x y 的询问, 要求输出所有 x, ...