aop的应用使用aop完成日志的记录

AOP、Interceptor、Filter关于日志记录的联系与区别 摘要: Spring框架中AOP、Filter和Interceptor均可用于日志记录,但适用场景不同。AOP适用于业务层(@Service),记录方法调用、执行时间等核心业务日志,通过切面编程实现环绕增强;Interceptor属于SpringMVC层,适合记录Controller的HTTP请求参数、URL等Web相关日志;Filter作为Servlet容器级拦截,处理原始请求/响应数据(如Body)。三者互补:Filter全局拦截请求,Interceptor处理Web层行为,AOP聚焦业务逻辑。组合使用 阅读详情

自定义注解,用来记录用户的操作和一些基本信息

package com.soecode.lyf.log.annatation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * Create by wws on 2019/6/3
 */
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface LogRequire {
 
    /**
     * 操作模块
     */
     String operationModel() default "";
    /**
     * 操作功能
     */
     String operationFunction()default "";
 
    /**
     * 操作说明
     */
     String operationExplain ()default "";
 
 
}

增加一个获取参数里面的用户信息注解,注意这个值一般是从session里面获取的,从controller里面传过来,这里为了简单从页面传来一个假的参数。

package com.soecode.lyf.log.annatation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * @Description
 * @Author DJZ-WWS
 * @Date 2019/6/4 8:36
 */
@Target({ ElementType.TYPE, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public  @interface LogUser {
 
}


日志的切面实现

package com.soecode.lyf.log.aspect;
 
import com.mchange.v1.util.ArrayUtils;
import com.soecode.lyf.datasource.DataSourceAspect;
import com.soecode.lyf.log.annatation.LogRequire;
import com.soecode.lyf.log.annatation.LogUser;
import com.soecode.lyf.log.pojo.LogInfo;
import com.soecode.lyf.log.service.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Enumeration;
 
 
/**
 * @Description 日志切面
 * @Author DJZ-WWS
 * @Date 2019/6/3 14:04
 */
 
@Aspect
@Component
public class SysLogAspect {
    static Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);
    @Autowired
    private LogService logService;
 
    @Pointcut("@annotation(com.soecode.lyf.log.annatation.LogRequire)")
    public void log() {
    }
 
    @After("log()")
    public void doAfter(JoinPoint joinPoint) throws UnknownHostException {
        System.out.println("=====SysLogAspect后置通知开始=====,开始记录日志信息");
        LogInfo logInfo = new LogInfo();
        //记录基本信息
        Class<?> target = joinPoint.getTarget().getClass();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Parameter[] parameters = method.getParameters();
        //记录用户信息  获取参数里面加LogUser注解的值,表示用户信息
        //获取参数上所有的注解
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        //判断注解LogUser是否存在
 
        for (Annotation[] paraeterAnnotation : parameterAnnotations) {
            //获取注解的索引
            int paramIndex = ArrayUtils.indexOf(parameterAnnotations, paraeterAnnotation);
            //获取注解标记的值
 
            for (Annotation annotation : paraeterAnnotation) {
                if (annotation instanceof LogUser) {
                    Object[] args = joinPoint.getArgs();
                    Object value = args[paramIndex];
                    logInfo.setAccountInfo(value.toString());
                }
            }
        }
        //获取注解上的值
        LogRequire logRequire = null;
        logRequire = this.getLogRequire(target, method);
        //从接口初始化
        if (logRequire == null) {
            for (Class<?> clazz : target.getInterfaces()) {
                logRequire = getLogRequire(clazz, method);
                if (logRequire != null) {
                    break;//从某个接口中一旦发现注解,不再循环
                }
            }
        }
 
        if (logRequire != null && (!StringUtils.isEmpty(logRequire.operationExplain())) && (!StringUtils.isEmpty(logRequire.operationFunction())) && (!StringUtils.isEmpty(logRequire.operationModel()))) {
            调用日志处理类去处理我们的日志
            logInfo.setOperationModel(logRequire.operationModel());
            logInfo.setOperationFunction(logRequire.operationFunction());
            logInfo.setOperationExplain(logRequire.operationExplain());
            logInfo.setIp(this.getIp());
            logInfo.setOperationTime(new Date());
            logService.saveLog(logInfo);
        }
 
 
    }
 
    /**
     * 获取方法或类的注解对象DataSource
     *
     * @param target
     * @param method
     * @return
     */
    private LogRequire getLogRequire(Class<?> target, Method method) {
        try {
            //1.优先方法注解
            Class<?>[] types = method.getParameterTypes();
            Method m = target.getMethod(method.getName(), types);
            if (m != null && m.isAnnotationPresent(LogRequire.class)) {
                return m.getAnnotation(LogRequire.class);
            }
            //2.其次类注解
            if (target.isAnnotationPresent(LogRequire.class)) {
                return target.getAnnotation(LogRequire.class);
            }
 
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(MessageFormat.format("通过注解切换数据源时发生异常[class={0},method={1}]:"
                    , target.getName(), method.getName()), e);
        }
        return null;
    }
    private String getIp() throws UnknownHostException {
        try {
            InetAddress candidateAddress = null;
            // 遍历所有的网络接口
            for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
                NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
                // 在所有的接口下再遍历IP
                for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
                    InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
                    if (!inetAddr.isLoopbackAddress()) {// 排除loopback类型地址
                        if (inetAddr.isSiteLocalAddress()) {
                            // 如果是site-local地址,就是它了
                            return inetAddr.getHostAddress();
                        } else if (candidateAddress == null) {
                            // site-local类型的地址未被发现,先记录候选地址
                            candidateAddress = inetAddr;
                        }
                    }
                }
            }
            if (candidateAddress != null) {
                return candidateAddress.getHostAddress();
            }
            // 如果没有发现 non-loopback地址.只能用最次选的方案
            InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
            if (jdkSuppliedAddress == null) {
                throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
            }
            return jdkSuppliedAddress.getHostAddress();
        } catch (Exception e) {
            UnknownHostException unknownHostException = new UnknownHostException(
                    "Failed to determine LAN address: " + e);
            unknownHostException.initCause(e);
            throw unknownHostException;
        }
    }
}


业务层的应用:

package com.soecode.lyf.bookuserservice.service.impl;
 
import com.soecode.lyf.bookuserservice.dao.BookDao;
import com.soecode.lyf.bookuserservice.pojo.Book;
import com.soecode.lyf.bookuserservice.service.BookService;
import com.soecode.lyf.datasource.DataSource;
import com.soecode.lyf.log.annatation.LogRequire;
import com.soecode.lyf.log.annatation.LogUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
 
 
@Service
public class BookServiceImpl implements BookService {
 
	private Logger logger = LoggerFactory.getLogger(this.getClass());
 
	// 注入Service依赖
	@Autowired
	private BookDao bookDao;
 
 
 
	@Override
	@DataSource("dataSource1")
	@LogRequire(operationModel = "book",operationFunction = "根据书的id查询book",operationExplain = "查询操作")
	public Book getById(long bookId,@LogUser String  userName) {
		return bookDao.queryById(bookId);
	}
 
	@Override
	@DataSource("dataSource1")
	@LogRequire(operationModel = "books",operationFunction = "查询所有的书",operationExplain = "查询所有的书")
	public List<Book> getList() {
		return bookDao.queryAll(0, 1000);
	}
 
 
 
 
}

日志基本信息bean

package com.soecode.lyf.log.service.impl;
 
import com.soecode.lyf.log.pojo.LogInfo;
import com.soecode.lyf.log.service.LogService;
import org.springframework.stereotype.Service;
 
/**
 * @Description
 * @Author DJZ-WWS
 * @Date 2019/6/3 14:09
 */
 
@Service
public class LogServiceImpl  implements LogService {
    @Override
    public void saveLog(LogInfo logInfo) {
        System.out.println("执行保存操作,保存的日志信息为"+logInfo.toString());
    }
}


记录日志的服务

package com.soecode.lyf.log.service.impl;
 
import com.soecode.lyf.log.pojo.LogInfo;
import com.soecode.lyf.log.service.LogService;
import org.springframework.stereotype.Service;
 
/**
 * @Description
 * @Author DJZ-WWS
 * @Date 2019/6/3 14:09
 */
 
@Service
public class LogServiceImpl  implements LogService {
    @Override
    public void saveLog(LogInfo logInfo) {
        System.out.println("执行保存操作,保存的日志信息为"+logInfo.toString());
    }
}

业务层注解的应用

 

日志结构图

 

这样就实现了aop对日志的操作。

结果如下:

 

   这里的没用真正的实现保存,伪保存。

   日志一般我们不会记录在数据库,数据量大的时候数据库压力大,可以采用mongodb记录日志。

   另外记录日志可以采用异步的方式实现日志的记录。

关于异步可以采用MQ或者使用线程的方式实现日志的记录。

AOP实现操作日志记录 一、设计:    操作日志记录 根据业务场景 一般是需要记录下数据修改更新的日志,查询类可以忽略。 所以需要对指定的某些方法进行记录。这块希望可以结合注解灵活操作,对于注解的方法进行日志记录操作日志表设计如下:CREATE TABLE `op_log` (  `id` bigint(20) NOT NULL COMMENT '主键',  `operator` varchar(32) NOT NUL... 阅读详情

相关推荐

深入解析EDID中Display Descriptor Block的配置技巧与实战应用

本文深入解析EDID中Display Descriptor Block的配置技巧与实战应用。通过剖析像素时钟、有效像素、消隐区与同步脉冲等核心参数,并结合1280x720@60Hz的实战配置案例,指导开发者如何正确为定制硬件或非标准显示器编写“身份证”,避免黑屏、分辨率异常等问题,确保显示设备完美点亮。

1a2s3d4f5g的博客 878

AOP在项目中的实际应用-日志

乱花渐欲迷人眼,浅草才能没马蹄。 折腾一晚上,问题总算时解决了。心里倒是没有多舒服,真相有时候还蛮伤人的。 前几天,面试时,跟两个项目经理聊起来几个技术实际应用和底层原理。一位老哥指着项目组的人说“你看看这些人,你让他做,他也能做。可你问他为什么这样做,没几个能说明白的。“。“我问你原理有什么用,没用,就是看看你对这个事情的理解。” 基于这样的情况,我决定把几个事故多发地着重关注一下。 先从全家桶...

MACHENIC的博客 9484

深度探索:非线性随机森林(Nonlinear Random Forest,NL-RF)原理及应用

非线性随机森林(NL-RF)旨在通过结合集成方法与高级技术来捕捉和建模数据中的非线性关系,从而改善传统随机森林在处理复杂非线性数据结构时的表现。

qq_51320133的博客 2066

json文件 数据导入excel----->(jxl)

json文件 数据导入excel----->(jxl)

z303756980的博客 3441

PMBus协议解析:基于I2C的电源管理实战与TMS320F28003x驱动开发

在嵌入式系统与服务器电源设计中,数字电源管理总线是实现高效、可靠电源监控与控制的关键技术。PMBus协议基于广泛应用的I2C总线物理层,通过定义标准化的命令集、数据格式与时序规范,为多路电源的电压电流监控、动态调整及故障处理提供了高效解决方案。其技术价值在于通过硬件自动处理协议解析、时钟拉伸与中断,显著降低软件复杂度,使开发者能聚焦于电源环路设计等核心逻辑。该协议广泛应用于服务器、通信基站及高性能计算板卡等场景,通过引入数据包错误检查、专用告警线等机制,确保了电源管理的可靠性。本文以TI TMS320F28

weixin_29189377的博客 374

Spring AI Alibaba Skill 实战:定义、注册与渐进式披露的企业级落地

摘要:很多团队在接入大模型时,第一步做到的是“能对话”,第二步遇到的瓶颈却是“不能可靠执行”。Skill 的本质不是给模型多几个函数,而是把企业系统中的可控能力,以可治理、可审计、可扩展的方式交给 Agent。本文围绕 Spring AI Alibaba Skill 的定义、注册与渐进式披露,结合电商客服与售后场景,系统讲清楚其底层原理、架构设计、生产级实现、高并发治理与工程实践。@Component@Tool(description = "根据订单号查询订单状态、支付状态和物流状态")扫描包含。

一起修行,不孤单。这里有编程语言、开发工具、学习方法论和踩坑笔记。用简单的话说复杂的事,陪你从小白到进阶。周更干货,欢迎一起成长! 623

通过AOP记录操作日志:提升应用可追踪性与安全性的利器

AOP(Aspect-Oriented Programming)的原理基于在程序运行时动态横切关注点,以达到对关注点的统一管理和复用。它的核心思想是将横切关注点从业务逻辑中分离出来,通过切面(Aspect)来统一管理和实现这些关注点。通过本文的介绍,我们深入探讨了AOP在记录操作日志方面的使用案例,以及实现方式和最佳实践。AOP作为一种常用的编程范式,能够帮助我们实现各种与核心业务逻辑无关但又必需的功能,如日志记录、性能监控等。希望本文能够帮助读者更好地理解和应用AOP技术,提升应用的安全性和可追踪性。

网络技术联盟站 1130

JLink 添加国产芯片手把手教程(雅特力 + 华大)

拷贝厂商算法文件夹 + 配置 JLinkDevices.xml。雅特力直接复制官方配置,华大按需添加芯片节点,操作一次,永久生效,以后调试 AT32、HC32 再也不用愁找不到型号。这套方法适配全版本 JLink,也是国产 MCU 替代项目的必备技能,看完照着做,新手也能轻松搞定。百度网盘资料分享:通过网盘分享的文件:jink驱动(包括新增芯片型号)链接: https://pan.baidu.com/s/14SLgrPfyof1lglD6VQguAw?pwd=cfuq 提取码: cfuq。

weixin_48867130的博客 710

Aop实现日志功能

Aop实现日志功能1、创建表和日志实体2、编写dao、service类3、导入maven依赖4、编写注解和切面类5、配置所需要的工具类6、系统测试 众所周知AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。可以对业务方法进行扩展,常用在缓存,日志、权限等方面。这里我用aop对日志进行一个小demo演示,帮助自己更好的理解和使用aop的功能。 本案例基于一个小的增删改查的demo,用s

qq_44392492的博客 7593

微波技术仿真:微波谐振器分析_(2).微波谐振器理论

谐振器是一种能够在特定频率范围内存储和释放电磁能量的器件。在微波频段,谐振器通常用于滤波、频率选择和能量存储等应用。一个理想的谐振器在谐振频率下能够存储无限大的能量,但在实际应用中,由于损耗的存在,谐振器的性能会受到一定限制。微波谐振器在微波通信、雷达系统、微波测量和微波电路设计等领域中发挥着重要作用。谐振器的设计需要考虑多个因素,包括谐振频率的精确控制、损耗的最小化、频率稳定性的提高和小型化设计。通过理论分析和仿真工具的使用,可以有效优化谐振器的性能,满足实际应用的需求。

2401_87715305的博客 933

国科大学习资料--高级软件工程-复习题概念解释答案

国科大学习资料–高级软件工程(罗铁坚 魏峻 刘丹)-复习题概念解释答案 1. 敏捷开发方法与Scrum方法 a.敏捷是一种强调轻量的过程方法论,它强调拥抱变化而不是与之对抗,通过有效的沟通发挥群体的智慧。敏捷方法采用迭代/增量开发的过程模型。敏捷宣言是:个体和交互高于流程和工具;工作的软件高于详尽的文档;客户合作高于合同谈判;响应变化高于遵循计划。 虽然右边的也有价值,但是认为左边的更有价值。 b.Scrum(Schwaber和Beedle)是管理两个披萨规模(4-9人)的软件开发团队的方法,它高频率的短会

无名何许人的博客 1443

spring Aop 之用户操作日志以及异常处理日志记录

使用Aop做操作日志,异常处理,并记录日志。 方法1:try{}catch(){记录日志} 方法2:通过filter,或者strtus2拦截器(目前项目是struts2) 方法3:hirbernate的拦截器记录日志 方法4:通过jvm agent 代理 方法5:自定义类加载器应该也可以 虽然说各有个的好处吧,但是我个人还是喜欢Aop,当然Aop有多种实现。目前项目上用的是Spring

xiaomin1991222的专栏 806

FPGA设计-Vivado的Off-Chip Termination设置问题

经常遇到在FPGA设计时,很多人很迷惑这些关于硬件的终端匹配怎么设置,Vivado的Off-Chip Termination设置问题,这里就详细说一下这个问题。

whm128的博客 2723

SpringBoot+AOP实现日志记录

SpringBoot+AOP实现日志记录,日志入库

张刚的博客 2301

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

java注解日志记录到数据库

1.pom添加依赖包 <!--添加aop依赖--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId></dependency>2....

weixin_30367543的博客 417

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

python切面异常处理_Spring AOP 进行统一的异常处理和日志记录

步骤1.使用@Aspect注解标注一个java类,Spring将自动识别该类作为切面Bean。@Aspectpublic class ExceptionAndLogAspect {}2.在Spring配置文件中添加這個切面Bean,并启动@AspectJ支持。3.添加增强处理import org.apache.log4j.Logger;import org.aspectj.lang.JoinPoi...

weixin_39771775的博客 297

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

SpringBoot使用AOP记录接口操作日志

前言:我们项目中可能有这种需求,每个人请求了哪些接口?做了什么事情?参数是什么?重要的接口我们需要记日志以便查找。我们不可能在每个接口中去一一处理,可以借助Spring提供的AOP能力+自定义注解轻松应对。 ...

何哥的博客 2万+

【SpringBoot】SpringBoot中使用AOP实现日志记录功能

AOP的全称是Aspect-Oriented Programming,即面向切面编程(也称面向方面编程)。它是面向对象编程(OOP)的一种补充,目前已成为一种比较成熟的编程方式。在传统的业务处理代码中,通常都会进行事务处理、日志记录等操作。虽然使用OOP可以通过组合或者继承的方式来达到代码的重用,但如果要实现某个功能(如日志记录),同样的代码仍然会分散到各个方法中。这样,如果想要关闭某个功能,或者对其进行修改,就必须要修改所有的相关方法。这不但增加了开发人员的工作量,而且提高了代码的出错率。

qq_61024956的博客 5970

Spring AOP 完成日志记录

1、技术目标     掌握Spring AOP基本用法使用Spring AOP完成日志记录功能     提示:本文所用项目为"影片管理",参看 http://hotstrong.iteye.com/blog/1160153 本文基于"影片管理"项目进行了日志记录功能扩充   注意:本文所实现的项目(MyEclipse工程)已提

zl386119974的专栏 4835

使用SpringBoot AOP记录操作日志和异常日志

使用SpringBoot AOP记录操作日志和异常日志

YIYIYI 3002

如何使用AOP完成记录日志功能傻瓜式教程

使用AOP实现日志记录的需求 傻瓜式教程

cxyzhaosi的博客 6260

Java实战:Spring Boot实现AOP记录操作日志

本文将详细介绍如何在Spring Boot应用程序中使用Aspect Oriented Programming(AOP)来实现记录操作日志的功能

oandy0的博客 3491

SpringBoot中使用AOP实现日志记录功能

日志记录在软件开发中是极其重要的,能够帮助开发人员快速定位问题、监控系统性能、提高系统安全性、跟踪业务流程等,是保障系统稳定运行和快速问题排查的重要手段

customer08的博客 1816
上一篇: 请求如何避免恶意攻击
下一篇: mongodb 使用场景
wrr-cat
博客等级 码龄9年 128粉丝 302原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值