AOP案例

news2024/11/18 13:41:11

黑马程序员JavaWeb开发教程

文章目录

  • 一、案例
    • 1.1 案例
    • 1.2 步骤
      • 1.2.1 准备
      • 1.2.2 编码

一、案例

1.1 案例

  • 将之前案例中增、删、改相关节后的操作日志记录到数据库表中。
  1. 操作日志:日志信息包含:操作人、操作时间、执行方法的全类名、执行方法名、方法运行时参数、返回值、方法执行时长
  2. 思路分析
    • 需要对所有业务中的增、删、改方法添加同一功能,使用AOP技术最为方便,@Around 环绕通知
    • 由于增、删、改方法名没有规律,可以自定义@Log 注解完成目标方法匹配

1.2 步骤

1.2.1 准备

  1. 在案例工程中引入AOP的起步依赖
<!--        AOP起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
  1. 在数据库中新建日志数据表,并引入对应的实体类
  • 创建数据表语句
-- 操作日志表
create table operate_log(
    id int unsigned primary key auto_increment comment 'ID',
    operate_user int unsigned comment '操作人ID',
    operate_time datetime comment '操作时间',
    class_name varchar(100) comment '操作的类名',
    method_name varchar(100) comment '操作的方法名',
    method_params varchar(1000) comment '方法参数',
    return_value varchar(2000) comment '返回值',
    cost_time bigint comment '方法执行耗时, 单位:ms'
) comment '操作日志表';
  • 实体类代码
package com.itheima.mytlias.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigInteger;
import java.time.LocalDateTime;

//操作日志表
@Data//getter、setter等
@NoArgsConstructor//无参构造函数
@AllArgsConstructor//全参构造函数
public class OperateLog {
    private Integer id;//id
    private Integer operateUser;//操作人id
    private LocalDateTime operateTime;//操作时间
    private String className;//操作的类名
    private String methodName;//操作的方法名
    private String methodParas;//方法参数
    private String returnValue;//返回值
    private BigInteger costTime;//方法执行时间,单位ms
}

  • 另外还需要mapper接口,以向日志记录表中插入数据
package com.itheima.mytlias.mapper;

import com.itheima.mytlias.pojo.OperateLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface OperateLogMapper {

    @Insert("insert into operate_log(operate_user,operate_time,class_name,method_name,method_params,return_value,cost_time) values(#{operateUser},#{operateTime},#{className},#{methodName},#{methodParams},#{returnValue},#{costTime})")
    public void insert(OperateLog operateLog);
}

获取当前登录用户:获取request对象,从轻去偷中获取到jwt令牌,解析令牌获取出当前用户的id

1.2.2 编码

  1. 自定义注解@Log
    • 在com.itheima.mytilas 包下新建包 anno,创建注解 @Log
    • 在这里插入图片描述
package com.itheima.mytlias.anno;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
}

  1. 定义切面类,完成记录操作日志的逻辑
package com.itheima.mytlias.aop;

import com.alibaba.fastjson.JSONObject;
import com.itheima.mytlias.mapper.OperateLogMapper;
import com.itheima.mytlias.pojo.OperateLog;
import com.itheima.mytlias.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;

@Slf4j//日志
@Component//交给IOC容器管理
@Aspect//切面类
public class LogAspect {
    //为了拿到当前这次请求的请求头对象,我们直接注入一个HttpServletRequest 对象
    @Autowired
    HttpServletRequest request;
    //调用mapper接口中的insert方法记录日志,因此注入一个OperateLogMapper对象
    @Autowired
    OperateLogMapper operateLogMapper;


    @Around("@annotation(com.itheima.mytlias.anno.Log)")
    public Object recordLog(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        //操作人id(通过获取请求头张的jwt令牌来解析令牌)
        String jwt = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(jwt);//使用JWT工具类解析jwt令牌
        Integer operateUser = (Integer) claims.get("id");//操作用户的id
        log.info("用户id,{}", operateUser);
        //操作时间
        LocalDateTime operateTime = LocalDateTime.now();
        //操作的类名
        String className = proceedingJoinPoint.getTarget().getClass().getName();
        // 操作的方法名
        String methodName = proceedingJoinPoint.getSignature().getName();
        // 操作的方法参数
        Object[] args = proceedingJoinPoint.getArgs();
        String methodParms = Arrays.toString(args);
        //调用方法之前的时间(用于计算方法运行耗时)
        long begin = System.currentTimeMillis();

        //调用原始目标方法
        Object result = proceedingJoinPoint.proceed();

        //调用方法之后的时间(用于计算方法运行耗时)
        long end = System.currentTimeMillis();

        // 返回值
        String returnValue = JSONObject.toJSONString(result);
        // 操作耗时
        long costTime = (end - begin);

        //记录操作日志
        OperateLog operateLog = new OperateLog(null, operateUser, operateTime, className, methodName, methodParms, returnValue, costTime);

        operateLogMapper.insert(operateLog);
        //在控制打印输出日志
        log.info("AOP记录操作日志:{}", operateLog);
        //返回值
        return result;


    }
}

  1. 在所有增删改的方法上加上注解@Log

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1792186.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

苍穹外卖笔记-02-借助小乌龟创建gitee仓库,apifox代替YApi,Swagger

TOC 1 借助小乌龟创建gitee苍穹外卖仓库 这里建议看视频bilibili比特鹏哥视频 使用软件 git TortoiseGit https://git-scm.com/downloads https://tortoisegit.org/ 使用代码托管平台gitee&#xff0c;git的使用和gitee的账号创建需要查询其他资料 在一个从未克隆仓库的…

yolov8-obb 旋转目标检测 瑞芯微RKNN芯片部署、地平线Horizon芯片部署、TensorRT部署

特别说明&#xff1a;参考官方开源的yolov8代码、瑞芯微官方文档、地平线的官方文档&#xff0c;如有侵权告知删&#xff0c;谢谢。 模型和完整仿真测试代码&#xff0c;放在github上参考链接 模型和代码。 折腾旋转目标检测的小伙伴们看过来&#xff0c;yolov8旋转目标检测部署…

ShowDoc item_id 未授权SQL注入漏洞复现

0x01 产品简介 ShowDoc 是一个开源的在线文档协作平台,它支持Markdown、图片等多种格式,方便团队成员共同编辑和分享文档。企业常见使用场景是使用其进行接口文档、内部知识库管理。 0x02 漏洞概述 2024年6月,ShowDoc官方发布新版本修复了一个SQL注入漏洞。鉴于该漏洞无前…

速通数据挖掘课程

速通 数据挖掘课程 大的分类 标签预测&#xff08;分类&#xff09; 和 数值预测&#xff08;预测呀&#xff09; 监督 非监督 是否 需要预先训练模型 然后预测 聚类&#xff1a;拿一个比一个&#xff0c;看看相似否&#xff0c;然后归一类 数据四种类型 数据属性有四种&…

C++实现,简单的命令行交互框架

目录 背景背景 在实际开发中,经常需要有对端测试程序,配合自己的程序,验证功能、逻辑等。面对繁杂、多变的需求,如果对端程序设计得不够灵活,则无法提升工作效率,如果能够与对端程序交互,通过命令行输入命令的方式完成测试验证,将大大提升工作效率,下面的示例程序是一…

weak的底层原理

weak 引用在 iOS 中通过维护一个全局的弱引用表来实现。当弱引用的对象被释放时&#xff0c;所有指向它的弱引用会被自动置为 nil&#xff0c;从而防止悬挂指针。 弱引用表&#xff08;Weak Table&#xff09;的键和值 理解弱引用表的键和值对于理解 weak 引用的底层机制非常重…

酱菜产业:传承美味,点亮生活

酱菜&#xff0c;这道深受人们喜爱的传统美食&#xff0c;以其独特的风味和营养价值&#xff0c;点亮了我们的日常生活。酱菜产业作为美食文化的重要组成部分&#xff0c;正以其独特的魅力&#xff0c;吸引着越来越多的消费者。 酱菜产业的赵总说&#xff1a;酱菜的制作过程&am…

Nginx网站服务【☆☆☆】

市面上常用Linux的web服务器&#xff1a;apache、Nginx。 apache与nginx的区别&#xff1f; 最核心的区别在于NGINX采用异步非阻塞机制&#xff0c;多个连接可以对应一个进程&#xff1b;apache采用的是同步阻塞多进程/线程模型&#xff0c;一个连接对应一个进程。apache美国…

【C语言】一节课拿捏---动态内存分配

谢谢观看&#xff01;希望以下内容帮助到了你&#xff0c;对你起到作用的话&#xff0c;可以一键三连加关注&#xff01;你们的支持是我更新地动力。 因作者水平有限&#xff0c;有错误还请指出&#xff0c;多多包涵&#xff0c;谢谢&#xff01; 目录 一、 为什么要有动态内存…

关于IDEA创建Maven一直爆红无法下载的问题

你能看到这我就知道你肯定已经试过了网上的很多方法了&#xff0c;我之前也是&#xff0c;试过了很多一直无法正常下载&#xff0c;我也是找人给 线下看了看解决了&#xff0c;我总结一下从头到尾排除问题&#xff0c;试到最后要是还解决不了你直接私信我&#xff0c;我给你看看…

vue3+uniapp

1.页面滚动 2.图片懒加载 3.安全区域 4.返回顶部&#xff0c;刷新页面 5.grid布局 place-self: center; 6.模糊效果 7.缩放 8.微信小程序联系客服 9.拨打电话 10.穿透 11.盒子宽度 12.一般文字以及盒子阴影 13.选中文字 14.顶部安全距离 15.onLoad周期函数在setup语法糖执行后…

微信小程序-案例:本地生活-首页(不使用网络数据请求)

一、 1.页面效果&#xff1a; 二、 1.新建项目并添加页面 在app.json文件中&#xff1a; "pages": ["pages/home/home","pages/message/message","pages/contact/contact"] 2.配置导航栏效果 在app.json文件中&#xff1a; &quo…

DVWA-XSS(DOM)

Low 后端没有代码&#xff0c;点击select按钮动作是前端的JS代码进行处理的 function addEventListeners() {var source_button document.getElementById ("source_button");if (source_button) {source_button.addEventListener("click", function() {v…

Doris Connector 结合 Flink CDC 实现 MySQL 分库分表

1. 概述 在实际业务系统中为了解决单表数据量大带来的各种问题&#xff0c;我们通常采用分库分表的方式对库表进行拆分&#xff0c;以达到提高系统的吞吐量。 但是这样给后面数据分析带来了麻烦&#xff0c;这个时候我们通常试将业务数据库的分库分表同步到数据仓库时&#x…

【杂谈】AIGC之ChatGPT-与智能对话机器人的奇妙对话之旅

与智能对话机器人的奇妙对话之旅 引言 在数字时代的浪潮中&#xff0c;ChatGPT如同一位智慧的旅伴&#xff0c;它不仅能够与我们畅谈古今&#xff0c;还能解答我们的疑惑&#xff0c;成为我们探索知识海洋的得力助手。今天&#xff0c;就让我们走进ChatGPT的世界&#xff0c;…

Capture One Pro 23:专业 Raw 图像处理的卓越之选

在当今的数字摄影时代&#xff0c;拥有一款强大的图像处理软件至关重要。而 Capture One Pro 23 for Mac/Win 无疑是其中的佼佼者&#xff0c;为摄影师和图像爱好者带来了前所未有的体验。 Capture One Pro 23 以其出色的 Raw 图像处理能力而闻名。它能够精准地解析和处理各种…

题号:BC19 题目:反向输出一个四位数

题号&#xff1a;BC19 题目&#xff1a;反向输出一个四位数 废话不多说&#xff0c;上题目&#xff1a; 解题思路&#xff1a; 我们发现可以用%和/两个操作符就可以解决。 代码如下: int main() {int a 0;scanf("%d ",& a);while (a){printf("%d "…

基于googlenet深度学习网络的睁眼闭眼识别算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .................................................................. % 对测试集进行分类预…

如何通过 6 种简单方法将照片从华为转移到 PC?

华为作为全球领先的智能手机供应商之一&#xff0c;最近推出了其自主研发的操作系统——HarmonyOS 2.0&#xff0c;旨在为智能手机、平板电脑和智能手表等设备提供更流畅的用户体验。随着Mate 40/P40等系列手机计划升级到HarmonyOS 2.0&#xff0c;用户可能需要将手机中的文件备…

Aws EC2,kubeadm方式安装kubernetes(k8s)

版本 docker版本&#xff1a;20.10.25 k8s版本&#xff08;kubeadm&#xff0c;kubelet和kubectl&#xff09;&#xff1a;1.20.10-0 初始化 # 禁用 SELinux sudo setenforce 0 sudo sed -i s/^SELINUXenforcing$/SELINUXpermissive/ /etc/selinux/config# 关闭防火墙 sudo …