在Spring Boot中,利用AOP(Aspect-Oriented Programming)实现操作日志记录。

在Spring Boot中,利用AOP(Aspect-Oriented Programming)结合自定义注解,可以优雅地实现操作日志记录。这种方式不仅解耦了业务逻辑与日志记录功能,还能让代码更简洁、可维护性更高。

以下是实现步骤:

1. 项目依赖

在Spring Boot项目中,确保以下依赖已存在(默认spring-boot-starter-aopspring-boot-starter引入):

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

2. 自定义注解

首先创建一个注解,用于标记需要记录操作日志的方法。

package com.example.aspect;

import java.lang.annotation.*;

@Documented
@Target(ElementType.METHOD) // 作用于方法
@Retention(RetentionPolicy.RUNTIME) // 运行时保留
public @interface LogOperation {

    String value() default ""; // 描述信息
}

3. 创建 AOP 切面

通过 AOP 切面拦截带有 @LogOperation 注解的方法,并实现日志记录。

package com.example.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

@Aspect
@Component
public class LogAspect {

    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    // 定义切点:匹配带有 @LogOperation 注解的方法
    @Pointcut("@annotation(com.example.aspect.LogOperation)")
    public void logPointcut() {
    }

    // 环绕通知:在方法执行前后做增强
    @Around("logPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();

        // 获取方法信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        LogOperation logOperation = method.getAnnotation(LogOperation.class);

        // 获取方法参数
        Object[] args = joinPoint.getArgs();

        // 日志内容
        String operationDesc = logOperation.value();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();

        logger.info("开始执行操作: {}", operationDesc);
        logger.info("类名: {}, 方法: {}", className, methodName);
        logger.info("方法参数: {}", Arrays.toString(args));

        Object result;
        try {
            result = joinPoint.proceed(); // 执行目标方法
            logger.info("操作成功: {}", operationDesc);
        } catch (Exception e) {
            logger.error("操作失败: {}, 异常信息: {}", operationDesc, e.getMessage(), e);
            throw e;
        } finally {
            long endTime = System.currentTimeMillis();
            logger.info("操作耗时: {}ms", (endTime - startTime));
        }

        return result;
    }
}

4. 示例:应用注解

在控制器或服务方法中使用 @LogOperation 注解。

控制器示例

package com.example.controller;

import com.example.aspect.LogOperation;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class ExampleController {

    @GetMapping("/example")
    @LogOperation("查询示例数据")
    public String getExample(@RequestParam String name) {
        return "Hello, " + name;
    }

    @PostMapping("/example")
    @LogOperation("保存示例数据")
    public String saveExample(@RequestBody String data) {
        // 模拟保存逻辑
        return "Data saved: " + data;
    }
}

服务层示例

package com.example.service;

import com.example.aspect.LogOperation;
import org.springframework.stereotype.Service;

@Service
public class ExampleService {

    @LogOperation("执行复杂业务逻辑")
    public String complexOperation(String input) {
        // 模拟复杂逻辑
        return "Processed: " + input;
    }
}

5. 日志输出示例

访问 /api/example?name=John 时,日志将输出如下内容:

INFO  - 开始执行操作: 查询示例数据
INFO  - 类名: com.example.controller.ExampleController, 方法: getExample
INFO  - 方法参数: [John]
INFO  - 操作成功: 查询示例数据
INFO  - 操作耗时: 12ms

6. 进阶功能

(1) 保存日志到数据库

可以在 AOP 中直接将日志信息持久化到数据库,例如通过 LogRepository 保存日志:

@Autowired
private LogRepository logRepository;

logRepository.save(new LogEntity(operationDesc, className, methodName, args, timestamp));

(2) 动态获取用户信息

结合 Spring Security 或 Token 解析,获取当前用户信息:

String username = SecurityContextHolder.getContext().getAuthentication().getName();
logger.info("操作用户: {}", username);

(3) 日志级别控制

根据不同操作,选择合适的日志级别(INFO、DEBUG、ERROR 等)。

(4) 异步记录

使用 @Async 注解将日志记录操作改为异步,提高接口响应速度。

7. 完整性测试

对带有 @LogOperation 注解的方法进行测试,验证日志功能是否正常记录,并检查以下场景:

  • 方法执行成功。
  • 方法抛出异常。
  • 方法参数为空。

通过以上实现,利用 AOP 和自定义注解,不仅能优雅地记录操作日志,还能保持业务逻辑的简洁性,为后续功能扩展打下基础。

发布者:myrgd,转载请注明出处:https://www.object-c.cn/4434

Like (0)
Previous 2024年11月23日 下午1:53
Next 2024年11月23日 下午2:03

相关推荐

  • 博客网站的链接添加nofollow的好处

    在博客中为链接添加 nofollow 属性可以在以下几个方面带来好处: 1. 防止权重流失作用:为外部链接添加 nofollow 标签可以阻止搜索引擎将页面权重(PageRank)传递给目标页面,从而保留网站自身的 SEO 权重。适用场景:指向不可靠或低质量内容的链接。赞助商链接或付费推广链接。 2. 避免搜索引擎惩罚作用:搜索引擎(如 Google)要求对…

    2024年11月28日
    00
  • 在开发 Angular 项目时,使用 RangeSlider 控件时的常见问题

    在开发 Angular 项目时,使用 RangeSlider 控件时,可能会遇到一些常见的问题。以下是一些问题及其解决方案:1. 滑块值不更新问题描述:当用户拖动滑块时,滑块的值不会实时更新,或者显示的值不正确。解决方案:确保绑定的模型是双向绑定,使用 ngModel 或者监听 input 事件来确保滑块值能实时更新。例如: 确保你已经导入了 FormsMo…

    2024年11月27日
    00
  • uni-app 一个使用 Vue.js 开发所有前端应用的框架跨端开发的优势

    uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、Web(响应式)、以及各种小程序(微信 / 支付宝 / 百度 / 头条 / QQ / 钉钉)等多个平台,其跨端开发具有以下优势: 开发效率高 跨平台兼容性好 性能优化 生态丰富 学习成本低

    2024年12月22日
    00
  • 微信小程序中,通过Node.js连接本地 MySQL 实现数据的增删改查

    在微信小程序中,通过Node.js连接本地 MySQL 实现数据的增删改查的过程,可以分为以下几个步骤: 1. 准备工作 必要工具: 2. 搭建 Node.js 后端服务 安装依赖 在 Node.js 项目中,使用 npm init 初始化项目,并安装以下依赖: express: 用于搭建 Web 服务。 mysql: 用于连接和操作 MySQL 数据库。 …

    2024年12月9日
    00
  • Flutter 在 PC 端多窗口支持方面的进展备受关注的功能,已在 Ubuntu/Canonical 展示

    Flutter 在 PC 端多窗口支持方面的进展是一个备受关注的功能,它的目标是进一步提升 Flutter 的跨平台能力。最近,Flutter 团队与 Canonical 合作,在 Ubuntu 平台上展示了多窗口功能的新成果。这一进展对开发者和终端用户来说都有重要意义,以下是相关细节分析: 展示细节多窗口功能亮相Flutter 的多窗口支持在 Ubuntu…

    2024年12月2日
    00
  • Python 的 json模块序列化数据从文件里读取出来或存入文件

    Python 的 json 模块用于处理 JSON 格式的数据,可以将 JSON 数据与 Python 数据结构之间相互转换。以下是具体用法,包括从文件读取 JSON 数据以及将数据写入文件: 1. 将 JSON 数据从文件中读取到 Python 数据结构 代码示例: 解析过程: 2. 将 Python 数据结构写入到文件中(序列化为 JSON) 代码示例:…

    2024年11月26日
    00
  • 在 Jupyter Notebook 中使用 Markdown 的相关技巧

    在 Jupyter Notebook 中使用 Markdown 是一种常见的方式来撰写文档和注释,增强数据分析和报告的可读性。Markdown 在 Jupyter Notebook 中不仅支持标准的文本格式化功能,还提供了许多扩展功能,比如数学公式、表格、代码块等。以下是一些常用的 Markdown 技巧,可以帮助你提升 Jupyter Notebook 中…

    2024年11月27日
    00
  • 如何用pbootcmsAPI接口开发微信小程序UNIAPP

    使用 PbootCMS 的 API 接口结合 UniApp 开发微信小程序,可以实现高效的内容管理和展示。以下是一个完整的开发流程,包括 API 接口设置、小程序功能设计和开发细节。 1. 准备工作1.1 配置 PbootCMS API 接口PbootCMS 提供 API 功能,需在后台开启并配置:登录 PbootCMS 后台管理。前往 系统管理 -> AP…

    2024年11月28日
    00
  • 在 Nuxt.js 应用中,webpack 的 compile 事件钩子构建过程

    在 Nuxt.js 应用中,webpack 的 compile 事件钩子通常用于在构建过程中处理或监听 Webpack 编译的状态。webpack 是 Nuxt.js 中的核心构建工具之一,而 Nuxt.js 本身是基于 Webpack 配置的,允许你通过扩展 Webpack 配置来进行自定义。要使用 webpack 的 compile 事件钩子,首先你需要…

    2024年11月29日
    00
  • 在 Vue3 和 uniapp 的 H5 环境中使用 QRCode.toDataURL() 生成二维码时无法显示的问题

    1. 图片格式或生成的 DataURL 处理问题QRCode.toDataURL() 方法通常会生成一个 Base64 编码的 PNG 图片。某些 Android 浏览器或 WebView 可能对 Base64 编码的图片支持不好,或者由于资源限制无法正常解析。解决方法:尝试通过生成二维码的图片 URL 直接展示而非使用 Base64 编码。可以通过将二维码…

    2024年11月27日
    00
  • 在 Ant Design ProTable 中,如何设置不分页,依然显示分页信息,前端分页不触发

    在 Ant Design ProTable 中,默认情况下,分页是与数据请求(request)相关联的。也就是说,每当分页切换时,request 会被触发,重新请求新的数据。如果你希望在禁用分页的同时,依然显示分页控件,并且不触发 request 请求,可以通过以下方法进行配置。解决方案要在 Ant Design ProTable 中禁用分页的同时保留分页信…

    2024年11月29日
    00
  • 微信小程序使用 map 组件实现拖动地图并获取当前地图中心的经纬度

    在微信小程序中,使用 map 组件可以轻松实现拖动地图并获取当前地图中心的经纬度。以下是实现步骤和代码示例: 实现思路 代码实现 1. 页面 WXML 添加 map 组件并设置属性。 2. 页面 WXSS 定义地图样式和中心点标记样式。 3. 页面 JS 初始化地图中心点的经纬度,并监听地图拖动。 4. 中心点图标 将一个中心标记图标放置在地图中间。可以在小…

    2024年11月25日
    00
  • 把一个矩形div变成一个直角三角形

    要将一个矩形 div 变成一个直角三角形,可以通过 CSS 的一些属性进行实现。具体的方法是利用 border 属性来隐藏矩形的部分,留下一个直角三角形的形状。以下是实现的步骤:CSS 方法: 解释:width 和 height 设置为 0:通过将 div 的宽度和高度设置为 0,实际上把矩形的主体部分隐藏了。border-left 和 border-bot…

    2024年11月27日
    00
  • 微信小程序获取图片网页链接转换为 base64 ,wx.arrayBufferToBase64(binary) 提示已弃用的处理方法

    微信小程序中 wx.arrayBufferToBase64 提示已弃用的问题,可以通过其他方式实现将图片网页链接转换为 Base64 文件。以下是几种替代方法和完整的实现方案。 1. 问题分析wx.arrayBufferToBase64 在较新版本的小程序中可能会提示已弃用,建议开发者使用 JavaScript 原生方式处理。如果目标是将网络图片转换为 Ba…

    2024年11月28日
    00
  • 在 WPF 中使用 Vlc.DotNet 和 LibVLCSharp.WPF 两种库来进行 VLC 的二次开发

    在 WPF 中使用 Vlc.DotNet 和 LibVLCSharp.WPF 两种库来进行 VLC 的二次开发,可以实现丰富的视频播放功能,比如播放本地视频、流媒体、控制播放、获取视频信息等功能。以下是对两者的介绍及开发步骤。 一、Vlc.DotNet 和 LibVLCSharp 的对比 特性 Vlc.DotNet LibVLCSharp.WPF 开发活跃度…

    2024年12月3日
    00

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

在线咨询: QQ交谈

邮件:723923060@qq.com

关注微信