1.目的

通过aop及注解的方式,记录异常信息和特定的操作日志到数据库。

2.引入依赖

   <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>

3.自定义注解

4.aspect定义切入点和切入处理

@Aspect
@Component
@EnableAsync
public class SystemLogAspect extends EsgBaseController {private static Log log = LogFactory.getLog(SystemLogAspect.class);@AutowiredSysLogService sysLogService;@AutowiredLogQueue logQueue;@Pointcut("@annotation(com.mixislink.common.OperationAnnotation)")public void logPointCut() {}//@AfterRunning: 返回通知 rsult为返回内容@Before(value="logPointCut()")public void before(JoinPoint joinPoint){log.info("调用了前置通知");HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();handle(joinPoint,null,request);}//@AfterThrowing: 异常通知@AfterThrowing(pointcut="logPointCut()",throwing="e")public void afterReturningMethod(JoinPoint joinPoint, Exception e) {log.info("调用了异常通知");HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();handle(joinPoint,e,request);}//    @Async("asyncServiceExecutor")@Asyncpublic void handle(final JoinPoint joinPoint,final Exception e,final HttpServletRequest request){SysLog sysLog = new SysLog();MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();OperationAnnotation op = method.getAnnotation(OperationAnnotation.class);if (op != null){sysLog.setRemark(op.remark());sysLog.setSystype(op.sysType());sysLog.setOpType(op.opType());}//请求的 类名、方法名String className = joinPoint.getTarget().getClass().getName();String methodName = signature.getName();String ip = this.getIpAddress(request);String url = request.getRequestURI();String param = getParams(joinPoint);sysLog.setRequestUrl(url + "&"+ param);sysLog.setMethod(className + "." + methodName + "()");sysLog.setIpAddress(ip);try {if (e != null){sysLog.setRemark(e.getMessage());sysLog.setLogType(1);logQueue.add(sysLog);}else {if (!op.onlyErr()){sysLog.setLogType(0);logQueue.add(sysLog);}}} catch (Exception ex) {log.error("handle systemLog 出现异常",ex);}}public String getIpAddress(HttpServletRequest request){String ipAddress = request.getHeader("x-forwarded-for");if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){//根据网卡取本机配置的IPInetAddress inet=null;try {inet = InetAddress.getLocalHost();} catch (UnknownHostException e) {e.printStackTrace();}ipAddress= inet.getHostAddress();}}//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15if(ipAddress.indexOf(",")>0){ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));}}return ipAddress;}public String getParams(JoinPoint joinPoint){ParameterRequestWrapper requestWrapper = (ParameterRequestWrapper) joinPoint.getArgs()[0];Map map = requestWrapper.getParameterMap();return map != null ? JSON.toJSONString(map): null;}

这里讲一下Before会在方法执行前调用,AfterThrowing会抛异常时调用,最最最重要的是你的方法里如果用try catch捕获了异常,则不会走AfterThrowing,除非在catch里手动用throw重新抛出异常,这个问题之前困扰我很久。

然后我再注解里多加了一个onlyErr字段,为true时,只在方法出异常时记录,为false时,不仅会记录异常,还会记录自定义的操作日志,这样在只想记录异常,不想记录操作日志的地方加上这个字段就可以了。

5.启动queue处理,定时将日志批量插入到数据库。

@Slf4j
@Component
public class LogTask {@AutowiredLogQueue logQueue;@AutowiredSysLogService sysLogService;private volatile List<SysLog> operLogs = Collections.synchronizedList(new ArrayList<>());@Scheduled(fixedDelay = 500)public void logFixDelay(){//获取日志信息while (true){SysLog operLog = logQueue.poll();if(null==operLog){break;}operLogs.add(operLog);}if(operLogs.size()>0){try{log.info("######################批量添加系统日志"+operLogs.size());sysLogService.insertAll(operLogs);}catch (Exception e){log.error("批量添加系统日志异常:",e);operLogs.clear();}operLogs.clear();}}
}

6.工具类

@Component
public class LogQueue {//LinkedList实现了Queue接口,可以用LinkedList做一个队列,这里使用阻塞队列BlockingQueueprivate  volatile Queue<SysLog> dataQueue = new LinkedBlockingQueue<>();//添加日志信息public void add(SysLog logininfor) {dataQueue.add(logininfor);}//获取日志信息,用于插入到数据库中。public SysLog poll() { return dataQueue.poll(); }
}

7.到这里基本完成了,用法如下:

    @RequiresPermissions("sys:sysLog:list")@OperationAnnotation(remark = "分页查询SysLog信息",sysType = 1,opType = 4)@RequestMapping(value = "/selectAll",method = RequestMethod.GET)public HttpEntity selectAll(HttpServletRequest request)  throws Exception {EngineParameter ep = initParameter(request);try {return sysLogService.selectAll(ep);} catch (Exception e) {log.error("SysLog",e);throw e;}}

在要记录日志的地方加上@OperationAnnotation注解,就可以啦!!!

效果如下

springboot 利用aop实现系统日志和操作日志记录相关推荐

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

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

  2. SpringBoot利用Aop打印入参出参日志

    SpringBoot利用Aop打印入参出参日志 前言 以前写代码不会用Aop的时候,记录入参出参的日志打印都是在Controller中完成的,每个Controller的方法开始之前先打印个日志,然后方 ...

  3. SpringBoot通过AOP实现系统日志记录(一)-Controller层日志监控

    Service层日志监控:SpringBoot通过AOP实现系统日志记录(二)-Service层日志监控 Mapper层日志监控:SpringBoot通过AOP实现系统日志记录(三)-Mapper层日 ...

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

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

  5. AOP实现操作日志记录

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

  6. SpringBoot使用Slf4j+Log4j2完成项目的日志记录

    SpringBoot使用Slf4j+Log4j完成项目的日志记录 前言 本示例采用SpringBoot项目使用SpringAOP记录日志,Slf4j作为日志门面,Log4j2作为日志实现实,实现开发中 ...

  7. 如何实现操作操作日志记录

    如何实现操作操作日志记录 为什么要记录操作日志? 项目中的业务需求,需要针对用户的一些业务操作做操作记录, 也就是标题中的操场日志记录,最近做的项目也有这个需求, 我也是第一次写,相信有很多开发者也有 ...

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

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

  9. 共享服务器文件归档,如何实现共享文件访问记录方法、共享文件管理和共享文件操作日志记录.docx...

    文档 文档 PAGE / NUMPAGES 文档 如何实现共享文件访问记录方法.共享文件管理和共享文件操作日志记录 企业单位,办公都有应用到共享文件,经常会在文件共享服务器上存储单位一些重要的共享文件 ...

最新文章

  1. 基于Cobbler实现多版本系统批量部署
  2. linux raid auto 软raid parted,linux下的raid5配置方法.doc
  3. c++判断文件是否被修改(获取文件的MD5值)
  4. 技术人凭什么那么骄傲?谢然:给自己开发工具
  5. noip模拟赛 写代码
  6. 程序员必看!Android面试10大知识点总结宝典助你通关!年薪50W
  7. 编程小白模拟简易比特币系统,手把手带你写一波!(附代码)
  8. 【重点】程序员面试金典——17.13树转链表
  9. 客流分析江湖争端再起,新旧势力谁更胜一筹?
  10. 关于PWA落地问题的思考
  11. 天翼云服务器怎么重装系统,天翼云操作系统介绍
  12. Minecraft mod制作简易教程(三)——创建一个物品
  13. 计算机专业英语教学工作总结,2020大学英语教师上学期教学工作总结
  14. c++读取倍福PLC中轴状态
  15. 输入一个有大写和小写的字符串,把其中的大写转化为小写,小写转化为大写。
  16. Windows下动态内存分配方式http://whx.tzgt.gov.cn/newOperate/html/7/71/711/3938.html
  17. springdata数据源的配置
  18. 别被“僵尸”吃掉大脑!学会用Kubernetes (K8s)思考
  19. 短视频程序源码高仿马蜂窝旅游头像泡泡动画
  20. LVGL 8.2 meter控件实现模拟时钟

热门文章

  1. 奋斗吧,程序员——第十六章 笑渐不闻声渐悄,多情却被无情恼
  2. win10家庭版如何修改用户名对应的用户文件夹下的用户文件名字(中文该成英文字符)
  3. JDK8之ConcurrentHashMap源码解读
  4. excel 数据不全
  5. webstorm设置Ctrl+滚轮缩放字体大小
  6. 社交+小游戏方案来袭,全方位提升社交APP的活跃留存
  7. html:link-icon标签引入网站小图标favicon.ico
  8. flume高并发优化——(9)配置文件交由zookeeper管理
  9. 分析谁是2020欧洲杯的最佳球员
  10. 头盔-看完就不会买错的VR头盔攻略:VR头盔到底选哪个?