在正式上代码之前,需要了解的aop知识点:
切面(Aspect):在Spring AOP中,切面可以使用通用类或者在普通类中以@Aspect 注解(@AspectJ风格)来实现
连接点(Joinpoint):在Spring AOP中一个连接点代表一个方法的执行
通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括"around"、"before” 和"after"等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链
切入点(Pointcut):定义出一个或一组方法,当执行这些方法时可产生通知,Spring缺省使用AspectJ切入点语法。
OK知道这么多就可以了,开始我们愉快的代码时光。
先上数据库字段设计
CREATE TABLE `sys_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`table_name` varchar(50) DEFAULT NULL,
`param` varchar(255) DEFAULT NULL,
`operate_type` int(11) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`result` char(255) DEFAULT 'success',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创完表,习惯性的用逆向工程(generatorsqlmapcustom),生成一下
没有的话链接在这里(肯定要往表中添加字段,所以这是必须的)
一)在增强类注入我们的日志service
@Autowired
SysLogService sysLogService;
配置我们的spring-mybatis.xml文件,找到切入点
配置多个切入点
<!-- 设置切面 把事务管理的切面设置在service实现类这一层 -->
<aop:config>
<!-- 指定aop切面配置 定义一个切面实例 指定使用具体哪一个增强类进行增强 -->
<aop:aspect ref="ServiceAdvice">
<!-- pintcut 具体切面的表达式 execution 运行 * 访问权限任意 包路径 *所有类 *所有方法 (..)参数任意 返回值任意 -->
<aop:pointcut expression="execution(* com.oracle.ssm.service.impl.*.add*(..))"
id="addCut" />
<aop:after-returning method="after" pointcut-ref="addCut"
arg-names="joinPoint,object" returning="object" />
<aop:pointcut
expression="execution(* com.oracle.ssm.service.impl.*.insert*(..))"
id="insertCut" />
<aop:after-returning method="after" pointcut-ref="insertCut"
arg-names="joinPoint,object" returning="object" />
<aop:pointcut
expression="execution(* com.oracle.ssm.service.impl.*.delete*(..))"
id="saveCut" />
<aop:after-returning method="after" pointcut-ref="saveCut"
arg-names="joinPoint,object" returning="object" />
</aop:aspect>
</aop:config>
after-returning:返回后的一个增强方式
arg-names:配置参数 (必须要配置,不配置的话增强类获取不到。报错)
joinpoint:织入点(接入增强)
Object:返回值
二)在after中编写
取方法名:joinpoint.getSignature().getName();
取表名:
// 取方法名
String methodName = joinpoint.getSignature().getName();
String tableName = ""; // 表名
int operate_type = 0;// 操作类型
if (methodName.contains("add")) {
tableName = methodName.substring("add".length());
operate_type = 1;
}
if (methodName.contains("insert")) {
tableName = methodName.substring("insert".length());
operate_type = 1;
}
if (methodName.contains("delete")) {
tableName = methodName.substring("delete".length(), methodName.indexOf("By"));
operate_type = 2;
}
if (methodName.contains("update")) {
tableName = methodName.substring("update".length(), methodName.indexOf("By"));
operate_type = 3;
}
取参数名称,参数类型。传过来的可能是多个,我们用数组进行处理
Object[] arrays=joinpoint.getArgs();
StringBuffer rs=new StringBuffer();
String paramClass;
for (Object object2 : arrays) {
//取到参数的类型
paramClass=object2.getClass().getName();
paramClass=paramClass.substring(paramClass.lastIndexOf(".")+1);
rs.append("[参数,类型]"+paramClass+",值:(id:"
+joinpoint.getArgs()[0]+")");
}
获取用户ID
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = attr.getRequest().getSession(true);
User user = (User) session.getAttribute("user");
获取返回值:在这里我们用到了Gsonjar包:下载链接(链接:https://pan.baidu.com/s/1EdbM1HjK8WxHxnyKoSBPMw 提取码:1nc4 )
Gson json = new Gson();
String result = json.toJson(object).toString();
!!!!!!!!!!易错点!!!!!!!!!!!!!!!!!!!
当我们所有值都获取到以后,调用方法:
sysLogService.charuSelective(sysLog);
重点画圈。这里一定要改方法名字,不要用什么Insert add 什么的。
为什么?自己查看一下aop的配置即可,不改的话会出现死循环(这里本人整整卡了4个小时)。
最后启动一下项目,执行一个添加方法。
看下我们的日志记录表:
在执行一个修改的方法(没有返回值)