最近在项目中要求把后台的一些关键操作记录下来,想了好半天能想到的也就那两三种方式,要么就是写一个拦截器,然后再web.xml里面进行配置,要么就是就是在每个需要记录操作日志的代码里面进行拦截,最后我选择了第三种,也就是基于AOP的拦截,用这种方式,只需要在需记录操作的接口方法上,添加上自定义注解就好了。其实在项目开发里面真正用到AOP感觉不是很多,我也一样很少就没有怎么用到。刚好这次碰见了,就记录下来,也算是自己学习一次。
我在做的项目是基于SSH(Spring,Spring MVC,Hibernate)框架。

  1. 首先我们先想想我们做的功能到底是什么,我们要记录操作,我们首先就应该有一张记录操作记录的表
  `@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Entity
@Table(name = "表名")
public class LogModel extends IdEntity {//用户private User user;//IPprivate String remoteAddr;//异常private String exception;//日志标题private String title;//请求地址private String requestUri;//日志类型private String type;//日志记录描述private String description;
以上是我所用到的实体类

2. 关于实体类的Service层,Dao层,Impl等等我就不再这里过多叙述,无非就是一些与数据库操作挂钩的一些代码。
3. 自定义一个切面注解

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodLog {/*** 该注解作用于方法上时需要备注信息*/String remarks() default "";}

4. 接下来就是重点了,切面类的具体实现。

@Component
@Aspect
public class SystemLogAspect {//这段代码调用了org.slf4j.LoggerFactory line:280
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);
private static final ThreadLocal<Date> beginTimeThreadLocal =new NamedThreadLocal("ThreadLocal beginTime");private static final ThreadLocal<LogModel> logThreadLocal =new NamedThreadLocal("ThreadLocal log");private static final ThreadLocal<User> currentUser = new NamedThreadLocal("ThreadLocal user");@Autowiredprivate ThreadPoolTaskExecutor threadPoolTaskExecutor;/*** Controller层切点 注解拦截*/@Pointcut("@annotation(com.shopping.logrecord.MethodLog)")public void controllerAspect() {}/*** 用于拦截Controller层记录用户的操作的开始时间** @param joinPoint 切点* @throws InterruptedException*/@Before("controllerAspect()")public void doBefore(JoinPoint joinPoint) throws InterruptedException {Date beginTime = new Date();HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();beginTimeThreadLocal.set(beginTime);//线程绑定变量(该数据只有当前请求的线程可见)if (logger.isDebugEnabled()) {//这里日志级别为debuglogger.debug("开始计时: {}  URI: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(beginTime), request.getRequestURI());}//读取session中的用户HttpSession session = request.getSession();User user = (User) session.getAttribute("user");System.out.println(user);currentUser.set(user);}/*** 用于拦截Controller层记录用户的操作** @param joinPoint 切点*/@SuppressWarnings("unchecked")@After("controllerAspect()")public void doAfter(JoinPoint joinPoint)throws Exception {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();User user = currentUser.get();if (user != null) {String title = "";String type = "info";                       //日志类型(info:入库,error:错误)String remoteAddr = SystemLogAspect.getIp();//请求的IPString requestUri = request.getRequestURI();//请求的Uritry {title = getControllerMethodDescription2(joinPoint);} catch (Exception e) {e.printStackTrace();}LogModel logModel = new LogModel();logModel.setTitle(title);logModel.setType(type);logModel.setRemoteAddr(remoteAddr);logModel.setRequestUri(requestUri);logModel.setException("无异常");logModel.setUserId(user.getId());User users = userService.getObjById(user.getId());Date date = new Date();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String format = simpleDateFormat.format(date);logModel.setAddTime(date);logModel.setUserName(users.getUserName());//通过线程池来执行日志保存threadPoolTaskExecutor.execute(new SaveLogThread(logModel, logModelService));logThreadLocal.set(logModel);}}/***  异常通知 记录操作报错日志* @param joinPoint* @param e*/@AfterThrowing(pointcut = "controllerAspect()", throwing = "e")public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {LogModel logModel = logThreadLocal.get();logModel.setType("error");logModel.setException(e.toString());new UpdateLogThread(logModel, logModelService).start();}
/*** 获取注解中对方法的描述信息 用于Controller层注解* @param joinPoint 切点* @return 方法描述*/public static String getControllerMethodDescription2(JoinPoint joinPoint) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();MethodLog controllerLog = method.getAnnotation(MethodLog.class);String discription = controllerLog.remarks();return discription;}/*** 获取请求ip*/public static String getIp()throws Exception {InetAddress ia=null;ia=ia.getLocalHost();String localip=ia.getHostAddress();return localip;}/*** 保存日志线程** @author lin.r.x**/private static class SaveLogThread implements Runnable {private LogModel logModel;private LogModelService logModelService;public SaveLogThread(LogModel logModel, LogModelService logModelService) {this.logModel = logModel;this.logModelService = logModelService;}@Overridepublic void run() {logModelService.save(logModel);}}/*** 日志更新线程** @author lin.r.x**/private static class UpdateLogThread extends Thread {private LogModel logModel;private LogModelService logModelService;public UpdateLogThread(LogModel logModel, LogModelService logModelService) {super(UpdateLogThread.class.getSimpleName());this.logModel = logModel;this.logModelService = logModelService;}@Overridepublic void run() {this.logModelService.update(logModel);}}
}

接下来我们需要做一步操作,那就是在XML中开启对AOP的支持

<!-- 启动对@AspectJ注解的支持 --><aop:aspectj-autoproxy/><!-- 扫描切点类组件 -->//放置切面实现类的包路径<context:component-scan base-package="com.shopping.logrecord.logss"/>//日志表的service的包路径<context:component-scan base-package="com.shopping.logrecord.logservicess"/><bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><property name="corePoolSize" value="5" /><property name="maxPoolSize" value="10" /></bean>

OKAY,到这我们就基本算是配置完成了。
接下来,加入我们需要执行编辑操作
在编辑接口方法上添加自定义的注解

okay,完成,**注意**remarks的值。
看一下表数据

大功告成!

利用SpringMVC的AOP来实现后台系统的操作日志记录相关推荐

  1. 使用Spring AOP自定义注解方式实现用户操作日志记录

    1,开发环境 操作系统:Windows 7 JDK:1.8.0_161 Eclipse:Mars.2 Release (4.5.2) 2,自定义注解类UserLog @Target({ElementT ...

  2. 论文系统Step1:从日志记录中提取特定信息

    论文系统Step1:从日志记录中提取特定信息 前言 论文数据需要,需要实现从服务器日志中提取出用户的特定交互行为信息.日志内容如下: 自己需要获取"请求数据包一行的信息"及&quo ...

  3. JPOM - AOP+自定义注解实现操作日志记录

    文章目录 地址 版本 源码解析-AOP+自定义注解实现操作日志记录 地址 Gitee: https://gitee.com/dromara/Jpom 官网: https://jpom.io/ 一款简而 ...

  4. qt 历史记录控件_基于Qt图形界面软件的操作日志记录方法及系统_2015106293015_说明书_专利查询_专利网_钻瓜专利网...

    技术领域 本发明涉及一种软件系统的日志记录技术,特别涉及一种基于Qt图形界面软件的操作日志记录方法及系统. 背景技术 软件操作日志是记录用户在使用软件的过程中,通过鼠标和键盘在操作界面上执行的点击和输 ...

  5. AOP实现操作日志记录

    一.设计: 操作日志记录 根据业务场景 一般是需要记录下数据修改更新的日志,查询类可以忽略. 所以需要对指定的某些方法进行记录.这块希望可以结合注解灵活操作,对于注解的方法进行日志记录 操作日志表设计 ...

  6. springboot 利用aop实现系统日志和操作日志记录

    1.目的 通过aop及注解的方式,记录异常信息和特定的操作日志到数据库. 2.引入依赖 <dependency><groupId>org.springframework.boo ...

  7. 保存系统的操作日志,通过swagger注解获取请求描述(通用版本)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 大数据系列文章目录 前言 系统之前没有全局的记录操作日志,只是个别单个功能记录了操作日志,这样 ...

  8. springMVC开启声明式事务实现操作日志记录

    第一步.在applicationContext-mvc.xml开启AOP注解扫描 <aop:aspectj-autoproxy/> 第二步.创建增强类,实现日志记录 @Component ...

  9. 校园交易平台后台系统git操作全过程

    项目初始化 Shusheng Shi@PC-of-sss MINGW64 /h/mmall $ touch README.mdShusheng Shi@PC-of-sss MINGW64 /h/mma ...

最新文章

  1. 图表复现|PRD地下水微生物群落的多样性分析文献
  2. Android--应用开发3(Android layout XML属性)
  3. php 打印测试技巧
  4. 如何使用JCA (J2EE 连接器架构)实现企业应用--转载
  5. TreeView 跟 Iframe 关联设置的方法。
  6. Python-3.7.0
  7. 楼主考南师计算机学硕,【图片】2019南师大新传学硕考研经验贴【南京师范大学研究生吧】_百度贴吧...
  8. mysql创建表失败
  9. mysql 自动 分库 备份_MySQL分库备份的方法
  10. docker打包部署nginx,django应用
  11. js页面间通信方法实现
  12. 历史 微信开发者工具_微信开发者工具代码管理
  13. CCNA路由综合实验配置详解
  14. 新手自己搭建服务器步骤
  15. python判断闰年_python判断闰年
  16. 物联网协议-CoAP协议简介
  17. (一)、跨服务器自动备份
  18. 固态硬盘的计算机需要进行磁盘碎片整理吗,SSD硬盘为何不需要磁盘碎片整理?...
  19. vue打开外部页面_vue项目中嵌套外部网页
  20. Word 中插入高亮代码 | planetB | syntax-highlight-word

热门文章

  1. 关于手机分期付款项目的总结
  2. Jsp:判断List是否为空
  3. 考研证件照要求?如何制作考研用的证件照?
  4. Procedural Landmass Generation开源库测评
  5. 我的学生...我的事业...我的人生路...
  6. Excel-HLOOKUP函数匹配查找②
  7. android6.0小米note标配版
  8. .Net6开发winform程序使用依赖注入学习通http://www.bdgxy.com/
  9. ZuulServlet和ZuulFilter的简单流程
  10. android arcore素材,万物皆可造! 谷歌发布ARCore正面狙击苹果