Spring AOP 系统日志记录
AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,AOP实际是GoF设计模式的延续
关于Spring AOP的一些术语
- 切面(Aspect):在Spring AOP中,切面可以使用通用类或者在普通类中以@Aspect 注解(@AspectJ风格)来实现
- 连接点(Joinpoint):在Spring AOP中一个连接点代表一个方法的执行
- 通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括"around"、"before”和"after"等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链
- 切入点(Pointcut):定义出一个或一组方法,当执行这些方法时可产生通知,Spring缺省使用AspectJ切入点语法。
通知类型
- 前置通知(@Before):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)
- 返回后通知(@AfterReturning):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回
- 抛出异常后通知(@AfterThrowing):方法抛出异常退出时执行的通知
- 后通知(@After):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)
- 环绕通知(@Around):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型,环绕通知可以在方法调用前后完成自定义的行为,它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行
@AspectJ风格的AOP配置
Spring AOP配置有两种风格:
- XML风格 = 采用声明形式实现Spring AOP
- AspectJ风格 = 采用注解形式实现Spring AOP
创建日志记录表(MySQL)
CREATE TABLE `t_log` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `userid` bigint(20) unsigned NOT NULL, `createdate` datetime NOT NULL COMMENT '创建日期', `content` varchar(8000) NOT NULL DEFAULT '' COMMENT '日志内容', `operation` varchar(250) NOT NULL DEFAULT '' COMMENT '用户所做的操作', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
日志记录POJO类:
package com.hz.yiliao.orm; import java.io.Serializable; import java.util.Date; /** * 系统日志 * @author Administrator * */ public class Log implements Serializable{ private static final long serialVersionUID = -7372303516713218870L; private Long id;// private Long userId;// private Date createDate;//创建日期 private String content;//日志内容 private String operation;//用户所做的操作 //get set方法省略,自己生成 }
日志记录Mapper接口与XML配置文件:
package com.hz.yiliao.dao; import java.util.List; import java.util.Map; import com.hz.yiliao.orm.Log; /** * 系统日志接口 * @author Administrator * */ public interface LogMapper { /** * 新增 * @param log */ public void insert(Log log); }
LogMapper.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hz.yiliao.dao.LogMapper"> <resultMap type="com.hz.yiliao.orm.Log" id="LogMapper"> <id property="id" column="id"/> <result property="userId" column="userid" /> <result property="createDate" column="createdate" /> <result property="content" column="content" /> <result property="operation" column="operation" /> </resultMap> <sql id="LogSQL"> userid,createdate,content,operation </sql> <insert id="insert" parameterType="com.hz.yiliao.orm.Log" useGeneratedKeys="true" keyProperty="id" keyColumn="id"> insert into t_log(<include refid="LogSQL"/>) value(#{userId},NOW(),#{content},#{operation}) </insert> </mapper>
日志记录Service层:
package com.hz.yiliao.bo; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.hz.yiliao.dao.LogMapper; import com.hz.yiliao.orm.AdminUser; import com.hz.yiliao.orm.Log; /** * 系统日志逻辑层 * @author Administrator * */ @Service public class LogBO { @Autowired private LogMapper logMapper; /** * 新增 * @param log */ @Transactional("transactionManager") public void insertLog(Log log){ logMapper.insert(log); } }
在MyBatis配置文件mybatis-config.xml中配置POJO,根据自己的要求配置,如果不知道怎么配置,看一下spring+mybatis整合
创建utils包,在utils包下创建切面类LogAspect:
package com.hz.yiliao.utils; import java.lang.reflect.Method; 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.springframework.beans.factory.annotation.Autowired; import com.hz.yiliao.bo.LogBO; import com.hz.yiliao.orm.Log; /** * 系统日志AOP * @author Administrator * */ @Aspect public class LogAspect { @Autowired private LogBO logBO; /** * 添加业务逻辑方法切入点 */ @Pointcut("execution(* com.hz.yiliao.bo.*.insert(..))") public void insertCell(){} /** * 修改业务逻辑方法切入点 */ @Pointcut("execution(* com.hz.yiliao.bo.*.update(..))") public void updateCell(){} /** * 删除业务逻辑方法切入点 */ @Pointcut("execution(* com.hz.yiliao.bo.*.delete(..))") public void deleteCell(){} /** * 添加操作日志(后置通知) * @param joinPoint * @param rtv */ @SuppressWarnings("unused") @AfterReturning(value="insertCell()",argNames="rtv", returning="rtv") public void insertLog(JoinPoint joinPoint, Object rtv) throws Throwable{ Long userId = 1L; if(userId == null){//没有管理员登录 return ; } //判断参数 if(joinPoint.getArgs() == null){//没有参数 return ; } //获取方法名 String methodName = joinPoint.getSignature().getName(); //获取操作内容 String opContent = optionContent(joinPoint.getArgs(),methodName); Log log = new Log(); log.setUserId(userId); log.setContent(opContent); log.setOperation("添加"); logBO.insertLog(log); } /** * 管理员修改操作日志(后置通知) * @param joinPoint * @param rtv * @throws Throwable */ @SuppressWarnings("unused") @AfterReturning(value="updateCell()", argNames="rtv", returning="rtv") public void updateLog(JoinPoint joinPoint, Object rtv) throws Throwable{ Long userId = 1L; if(userId == null){//没有登录 return; } //判断参数 if(joinPoint.getArgs() == null){//没有参数 return; } //获取方法名 String methodName = joinPoint.getSignature().getName(); //获取操作内容 String opContent = optionContent(joinPoint.getArgs(), methodName); //创建日志对象 Log log = new Log(); log.setUserId(userId); log.setContent(opContent); log.setOperation("修改");//操作 logBO.insertLog(log); } /** * 删除操作 * @param joinPoint * @param rtv */ @SuppressWarnings("unused") @AfterReturning(value="deleteCell()",argNames="rtv", returning="rtv") public void deleteLog(JoinPoint joinPoint, Object rtv) throws Throwable{ Long userId = 1L; if(userId == null){//没有登录 return; } //判断参数 if(joinPoint.getArgs() == null){//没有参数 return; } //获取方法名 String methodName = joinPoint.getSignature().getName(); StringBuffer rs = new StringBuffer(); rs.append(methodName); String className = null; for(Object info : joinPoint.getArgs()){ //获取对象类型 className = info.getClass().getName(); className = className.substring(className.lastIndexOf(".") + 1); rs.append("[参数1,类型:" + className + ",值:(id:" + joinPoint.getArgs()[0]+")"); } //创建日志对象 Log log = new Log(); log.setUserId(userId); log.setContent(rs.toString()); log.setOperation("删除");//操作 logBO.insertLog(log); } /** * 使用Java反射来获取被拦截方法(insert、update)的参数值, * 将参数值拼接为操作内容 * @param args * @param mName * @return */ public String optionContent(Object[] args, String mName){ if(args == null){ return null; } StringBuffer rs = new StringBuffer(); rs.append(mName); String className = null; int index = 1; //遍历参数对象 for(Object info : args){ //获取对象类型 className = info.getClass().getName(); className = className.substring(className.lastIndexOf(".") + 1); rs.append("[参数"+index+",类型:" + className + ",值:"); //获取对象的所有方法 Method[] methods = info.getClass().getDeclaredMethods(); // 遍历方法,判断get方法 for(Method method : methods){ String methodName = method.getName(); // 判断是不是get方法 if(methodName.indexOf("get") == -1){//不是get方法 continue;//不处理 } Object rsValue = null; try{ // 调用get方法,获取返回值 rsValue = method.invoke(info); }catch (Exception e) { continue; } //将值加入内容中 rs.append("(" + methodName+ ":" + rsValue + ")"); } rs.append("]"); index ++; } return rs.toString(); } }
在applicationContext.xml中加入新的配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-tx-3.0.xsd"> <!-- 加入Aspectj配置 --> <aop:aspectj-autoproxy /> <bean id="logAspect" class="com.hz.yiliao.utils.LogAspect" /> <context:component-scan base-package="com.hz.yiliao.bo,com.hz.yiliao.orm" /> <bean id="yiliaoDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/yiliao?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull" /> <property name="username" value="root" /> <property name="password" value="root" /> <property name="defaultAutoCommit" value="false" /> <property name="timeBetweenEvictionRunsMillis" value="3600000" /> <property name="minEvictableIdleTimeMillis" value="3600000" /> </bean> <bean id="yiliaoSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="yiliaoDataSource" /> <property name="typeAliasesPackage" value="com.hz.yiliao.orm" /> </bean> <bean id="mailSender" class="com.hz.yiliao.utils.MailSender"> <property name="javaMailSender" ref="javaMailSender" /> </bean> <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.163.com" /> <property name="username" value="yiliao_2014@163.com" /> <property name="password" value="yiliao2014" /> <property name="defaultEncoding" value="UTF-8" /> </bean> <import resource="mybatis-config.xml" /> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref local="yiliaoDataSource" /> </property> </bean> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**" /> <bean class="com.hz.yiliao.filt.YiliaoSysInterceptor" /> </mvc:interceptor> </mvc:interceptors> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> </beans>
配置成功后分别进行登录、添加、修改、删除等操作,日志记录表的内容如下:
相关推荐
4、想看spring aop 注解实现记录系统日志并入库等 二、能学到什么 1、收获可用源码 2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑实现 (需要知道原理的请看spring aop源码,此处不做赘述) 3、...
内容概要: 充分利用SpringBoot AOP设计的精妙日志记录方案,实现高效的日志处理策略。此外,我们还支持通过配置文件(yml)精准控制日志开关,并定制AOP切点表达式(Pointcut)。 适用人群: 针对资深Java开发者、...
Spring mvc mybatis plus 实现AOP 切面日志系统,带有数据库。可以自行拓展
Spring mvc Aop+annotation实现系统日志记录功能实现的jar包asm-3.3.jar ,aspectjrt.jar , aspectjweaver.jar , cglib-nodep-2.1_3.jar , spring-aop.jar
主要是用于记录系统操作日志的方法和配置,采用spring aop的方式
spring.net aop 性能影响 在非单例模式下,了测试加入aop 后,对系统影响,测试时只加入aop,不实际记录日志。 测试介绍: http://blog.csdn.net/yangjian15/archive/2009/11/09/4790164.aspx
Spring AOP! 弹簧速度自由标记
功能日志:基于java aop思想设计,通过Spring advisorAutoProxy(自动代理)实现controller过滤代理拦截,并提供拦截filter过滤,支持spring EL表达式。 数据日志:设计中提供数据日志注入接口,管理数据日志注入,...
它的主要意图就要将日志记录,性能统计,安全控制等等代码从商业逻辑代码中清楚的划分出来,我们可以把这些行为一个一个单独看作系统所要解决的问题,就是所谓的面向问题的编程(不知将AOP译作面向问题的编程是否欠妥...
系统日志 记录用户访问监控异常信息 系统缓存管理 将redis的操作可视化,提供对redis的基本操作 Sql监控 采用 druid 监控数据库访问性能 技术栈 基础框架:Spring Boot 2.1.0.RELEASE 持久层框架:Spring boot Jpa ...
项目作品名称: 基于Struts2+Hibernate+Spring框架的超市信息管理系统 使用JQuery datatable插件浏览从数据库查询的信息记录...用Spring AOP技术,实现对添加或修改数据库记录操作的日志功能,日志记录保存在数据库。
AOP的强大之处在于它允许我们在不修改原有业务逻辑代码的情况下,将横切关注点(如日志记录、安全检查等)与业务逻辑分离。这样,我们可以更好地实现代码的复用和模块化,提高了应用程序的可维护性和可扩展性。 ...
aop日志记录。 4、调度 ====== Spring task, 可以查询已经注册的任务。立即执行一次任务。 5、缓存和Session =========== 注解redis缓存数据,Spring-session和redis实现分布式session同步(建议按功能模块...
其中包含apache的log4j记录日志信息,spring管理组件,springmvc分层,springaop配置数据库事务控制,hibernate二级缓存配置,实现了查询,用户登录注册,请求验证是否登录等基础功能Demo,基于后台测试,使用前台...
aop后置通知实现整个系统重要操作日志的记录。 项目技术栈: 前端 前端后台管理系统由vue与elementUI搭建,路由使用vue-router,前端在线考试系统由nuxt搭建,ajax请求均使用axios。 vsCode工具开发 后台 mysql...
HappyCat:这是一个比较完整的项目(尽管功能很简单)...其中,权限管理细化到每个URL,日志记录使用Spring AOP。也是自己随便搞搞,管理员页面使用了Super-ui开源框架,首页面支持响应式,手机浏览器打开可以实现自适应
您将了解如何使用AOP来处理横切关注点,例如日志记录、事务管理和安全性,而不必污染核心业务逻辑。 AOP的实际应用: 我们将提供实际的示例和案例,展示如何使用AOP来改善代码的可维护性和可扩展性。您将了解如何在...
旅游后台管理系统 1、项目环境 IDEA 2018.2 Mysql 5.5.27 jdk1.8 tomcat7 2、如何启动 1、在启动位置,配置maven,模块为ssm_web,使用tomcat7:run启动 2、网址: 用户:admin 密码:123
1,开发一个web应用程序使用Spring框架 2,使用Java、JSP和Javscript文件来实现用户需求 3,创建一个日志记录工具来记录系统日志(什么是好的),并使用AOP调用日志效用而线程退出你的方法
这有助于增加模块化,并且可以用于事务管理、日志记录等。 事务管理:Spring提供了一致的事务管理接口,可以在JTA(Java Transaction API)或非托管环境中使用,简化了事务管理代码。 模型-视图-控制器(MVC):...