Spring如何基于aop实现操作日志功能

1. 在pom中添加所需依赖

创建一个springboot工程,添加所需要的依赖,持久化用的是mybatis

        <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!--springboot aop依赖-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<!--mybatis-->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.1.3</version>
		</dependency>
		<!--mysql连接-->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.19</version>
			<scope>runtime</scope>
		</dependency>
		<!--lombok-->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

2. 创建日志实体类

import lombok.Data;

import java.io.Serializable;

@Data
public class AdminLog implements Serializable {

  private static final long serialVersionUID = -291495801959706565L;

  private Integer id; //日志记录id
  private Integer userId;//操作人id
  private String userName;//操作人name
  private String loginip;//登录ip
  private int type;
  private String url;
  private String operation;
  private String createtime;
  private String remark;

}

3. 自定义log注解

import java.lang.annotation.*;

/**
 * 自定义日志注解
 */
@Target(ElementType.METHOD) //注解防止位置
@Retention(RetentionPolicy.RUNTIME)//运行时可见
@Documented //生成文档
public @interface MyLog {
  String operation() default "";

  int type();
}

4. 创建aop切面处理类

import cn.***.springaopdemo.anno.MyLog;
import cn.***.springaopdemo.dao.MyLogMapper;
import cn.***.springaopdemo.pojo.Admin;
import cn.***.springaopdemo.pojo.AdminLog;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 切面处理类
 */
@Aspect
@Component
public class SysLogAspect {
  /**
   * 使用log4j2把一些信息打印在控制台上面
   */
  private static final Logger log = LogManager.getLogger(SysLogAspect.class);

  @Autowired
  private MyLogMapper myLogMapper;

  //定义切点 @Pointcut
  //在注解的位置切入代码
  @Pointcut("@annotation(cn.***.springaopdemo.anno.MyLog)")
  public void logPointCut() {

  }

  //切面 配置为前置通知
  @Before("logPointCut()")
  public void saveOperation(JoinPoint joinPoint) {
    log.info("---------------接口日志记录---------------");
    //创建一个日志对象
    AdminLog adminLog = new AdminLog();
    //获取切面织处入点的方法
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    //获取切入点所在的方法
    Method method = signature.getMethod();

    //获取操作日志的属性值
    MyLog myLog = method.getAnnotation(MyLog.class);

    if (myLog != null) {

      //操作事件
      String operation = myLog.operation();
      adminLog.setOperation(operation);

      //日志类型
      int type = myLog.type();
      adminLog.setType(type);

      log.info("operation=" + operation + ",type=" + type);
    }
    //获取url
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    String requestURL = request.getRequestURI().toString();
    adminLog.setUrl(requestURL);

    //获取客户端ip
    String ip = request.getRemoteAddr();
    adminLog.setLoginip(ip);

    //获取操作人账号、姓名(需要提前将用户信息保存到Session)
    Admin admin = (Admin) request.getSession().getAttribute("admin");
    if (admin != null) {
      Integer id = admin.getId();
      String name = admin.getName();
      adminLog.setUserId(id);
      adminLog.setUserName(name);
    }

    log.info("url=" + requestURL + ",ip=" + ip);

    //调用service保存Operation实体类到数据库
    //可以在这设置id,因为是测试,这里就使用的是数据库的自增id
    myLogMapper.insertLog(adminLog);

  }

}

5. mapper层把日志数据存储到mysql数据库中

mapper接口

import cn.***.springaopdemo.pojo.AdminLog;
import java.util.List;
public interface MyLogMapper {
  void insertLog(AdminLog adminLog);
}

mapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.***.springaopdemo.dao.MyLogMapper">

  <insert id="insertLog" parameterType="cn.***.springaopdemo.pojo.AdminLog">
    INSERT INTO admin_log (user_id,user_name,loginip,type,url,operation,createtime,remark)
    VALUES (#{userId},#{userName},#{loginip},#{type},#{url},#{operation},now(),#{remark})
  </insert>
</mapper>

6. 测试

先直接登录用户,因为是测试,直接从数据库中获取后登录,把admin存储到session中

import cn.***.springaopdemo.pojo.Admin;
import cn.***.springaopdemo.service.IAdminService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

@RestController
@RequestMapping("/admin")
public class AdminController {
  private static final Logger log = LogManager.getLogger(AdminController.class);
   //中间service层可以省略,直接通过mapper接口操作数据即可
  @Autowired
  private IAdminService adminService;

  @RequestMapping("/login")
  public Admin login(HttpServletRequest request) {
    List<Admin> adminList = adminService.findAllAdmin();
    Admin admin = adminList.get(0);
    request.getSession().setAttribute("admin",admin );
    return admin;
  }

}

在浏览器中输入localhost:8080/admin/login,可以看到登录的admin

进行插入和查询操作,插入数据直接通过后台提供

import cn.***.springaopdemo.anno.MyLog;
import cn.***.springaopdemo.pojo.Type;
import cn.***.springaopdemo.service.ITypeService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/type")
public class TypeController {
  private static final Logger log = LogManager.getLogger(TypeController.class);

  @Autowired
  private ITypeService typeService;

  @MyLog(operation = "增加书籍类型", type = 2)
  @RequestMapping("/add")
  public void insertType() {
    List<Type> typeList = new ArrayList<>();
    Type type = new Type();
    type.setName("自然科学");
    typeList.add(type);
    typeService.addTypeList(typeList);
    log.info("添加书籍类型" + type.getName());
  }

  @MyLog(operation = "查询所有书籍类型", type = 1)
  @RequestMapping("/findAll")
  public List<Type> findAllType() {
    List<Type> typeList = typeService.findAllType();
    log.info("查询所有书籍类型");
    return typeList;
  }
}

在浏览器中输入localhost:8080/type/add,后台日志打印记录

再输入查询请求localhost:8080/type/findAll,获得查询出的分类

查看数据库是否添加成功

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Springboot接口项目如何使用AOP记录日志

    一. 背景 一直想给项目构建一个统一的日志收集系统,先迈出第一步,构建一个日志收集类,用AOP实现无侵入日志收集 二. 环境 1.此随笔内容基于spring boot项目 2.数据库为mysql 5.7.9版本 3.jdk 版本为1.8 三. 说明 此版采用数据库存储,之后考虑使用elasticsearch等工具存储 四. 内容 1.构建日志采集实体类:BaseLogMessage public class BaseLogMessage { private String serverIP; pr

  • Spring Boot配置AOP打印日志的全过程

    前言 在项目开发中,日志系统是必不可少的,用AOP在Web的请求做入参和出参的参数打印,同时对异常进行日志打印,避免重复的手写日志,完整案例见文末源码. 一.Spring AOP AOP(Aspect-Oriented Programming,面向切面编程),它利用一种"横切"的技术,将那些多个类的共同行为封装到一个可重用的模块.便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性. AOP中有以下概念: Aspect(切面):声明类似于Java中的类声明,在

  • springboot配置aop切面日志打印过程解析

    这篇文章主要介绍了springboot配置aop切面日志打印过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.SpringBoot Aop说明 1. Aop AOP(Aspect-Oriented Programming,面向切面编程),它利用一种"横切"的技术,将那些多个类的共同行为封装到一个可重用的模块.便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性. 2. AOP相关概念: Aspect

  • Springboot使用@Valid 和AOP做参数校验及日志输出问题

    项目背景 最近在项目上对接前端的的时候遇到了几个问题 1.经常要问前端要请求参数 2.要根据请求参数写大量if...else,代码散步在 Controller 中,影响代码质量 3.为了解决问题1,到处记日志,导致到处改代码 解决方案 为了解决这类问题,我使用了@Valid 做参数校验,并使用AOP记录前端请求日志 1.Bean实体类增加注解 对要校验的实体类增加注解,如果实体类中有List结构,就在List上加@Valid @Valid注解 注解 备注 @Null 只能为null @NotNu

  • 详解基于SpringBoot使用AOP技术实现操作日志管理

    操作日志对于程序员或管理员而言,可以快速定位到系统中相关的操作,而对于操作日志的管理的实现不能对正常业务实现进行影响,否则即不满足单一原则,也会导致后续代码维护困难,因此我们考虑使用AOP切面技术来实现对日志管理的实现. 文章大致内容: 1.基本概念 2.基本应用 3.日志管理实战 对这几部分理解了,会对AOP的应用应该很轻松. 一.基本概念 项目 描述 Aspect(切面) 跨越多个类的关注点的模块化,切面是通知和切点的结合.通知和切点共同定义了切面的全部内容--它是什么,在何时和何处完成其功

  • SpringBoot AOP处理请求日志打印功能代码实例

    设计原则和思路: 元注解方式结合AOP,灵活记录操作日志 能够记录详细错误日志为运营以及审计提供支持 日志记录尽可能减少性能影响 操作描述参数支持动态获取,其他参数自动记录. 代码实例如下 @Slf4j @Aspect @Configuration public class RequestAopConfig { @Autowired private HttpServletRequest request; private static final ThreadLocal<Long> START_

  • 利用spring AOP记录用户操作日志的方法示例

    前言 最近项目已经开发完成,但发现需要加用户操作日志,如果返回去加也不太现实,所以使用springAOP来完成比较合适.下面来一起看看详细的介绍: 注解工具类: @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface LogAnnotation { String operateModelNm() default ""; String operateFuncNm() default

  • Spring框架基于AOP实现简单日志管理步骤解析

    SPringAOP的使用 技术概述,描述这个技术是做什么?学习该技术的原因,技术的难点在哪里. 为了实现项目管理员端的操作数据库日志,便于方便所以利用Spring框架的AOP机制进行实现,项目的难点在于如果设置切入点,如何获取参数. 技术详述,描述你是如何实现和使用该技术的,要求配合代码和流程图详细描述.可以再细分多个点,分开描述各个部分. 在applicationContext.xml中开启AOP代理 <aop:aspectj-autoproxy /> 自定义一个注解 @Target(Ele

  • Spring如何基于aop实现操作日志功能

    1. 在pom中添加所需依赖 创建一个springboot工程,添加所需要的依赖,持久化用的是mybatis <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--springboot aop依赖--> <dependency

  • 使用Spring AOP实现用户操作日志功能

    目录 我使用Spring AOP实现了用户操作日志功能 需求分析 功能实现 1. 需要一张记录日志的 Log 表 导出的 sql 如下: 2.我使用的是 Spring Boot 所以需要引入 spring aop 的 starter 3.Log 实体类 4.ILog 注解 5.切面类 LogAspect 总结 我使用Spring AOP实现了用户操作日志功能 今天答辩完了,复盘了一下系统,发现还是有一些东西值得拿出来和大家分享一下. 需求分析 系统需要对用户的操作进行记录,方便未来溯源 首先想到

  • 使用SpringBoot AOP 记录操作日志、异常日志的过程

    平时我们在做项目时经常需要对一些重要功能操作记录日志,方便以后跟踪是谁在操作此功能:我们在操作某些功能时也有可能会发生异常,但是每次发生异常要定位原因我们都要到服务器去查询日志才能找到,而且也不能对发生的异常进行统计,从而改进我们的项目,要是能做个功能专门来记录操作日志和异常日志那就好了, 当然我们肯定有方法来做这件事情,而且也不会很难,我们可以在需要的方法中增加记录日志的代码,和在每个方法中增加记录异常的代码,最终把记录的日志存到数据库中.听起来好像很容易,但是我们做起来会发现,做这项工作很繁

  • springboot实现基于aop的切面日志

    本文实例为大家分享了springboot实现基于aop的切面日志的具体代码,供大家参考,具体内容如下 通过aop的切面方式实现日志 通切面拦截所有指定包下的所有方法 @Aspect @Component @EnableAspectJAutoProxy public class LogAspect1{     Logger logger = LoggerFactory.getLogger(LogAspect.class);      /**  * 拦截切点  */     @Pointcut("e

  • Spring Security基于过滤器实现图形验证码功能

    目录 前言 一. 验证码简介 二. 基于过滤器实现图形验证码 1. 实现概述 2. 创建新模块 3. 添加依赖包 4. 创建Producer对象 5. 创建生成验证码的接口 6. 自定义异常 7. 创建拦截验证码的过滤器 8. 编写SecurityConfig 9. 编写测试页面 10. 代码结构 11. 启动项目测试 前言 在前两个章节中,一一哥 带大家学习了Spring Security内部关于认证授权的核心API,以及认证授权的执行流程和底层原理.掌握了这些之后,对于Spring Secu

  • Spring如何基于aop实现事务控制

    spring的事务控制本质上是通过aop实现的. 在springboot中使用时,可以通过注解@Transactional进行类或者方法级别的事务控制,也可以自己通过spring提供的事务管理器手动控制事务 一. @Transactional注解进行进行类或者方法级别的事务控制 不需要进行特别的设置,按照正常的配置整合spring和mybatis后,在需要进行事务控制的类上或者方法上加上 @Transactional注解,即可对其进行事务控制. 二.手动控制事务 当需要在一个方法的内部进行事务控

  • SpringBoot使用AOP记录接口操作日志的方法

    目录 一.操作日志简介 1.1.系统日志和操作日志的区别 1.2.操作日志记录实现方式 二.AOP面向切面编程 2.1.AOP简介 2.2.AOP作用 2.3.AOP相关术语 2.4.JointPoint和ProceedingJoinPoint 2.5.AOP相关注解 三.AOP切面实现接口日志记录 3.1.引入AOP依赖 3.2.创建日志信息封装类WebLog 3.3.创建切面类WebLogAspect 3.4.调用接口进行测试 四.AOP切面+自定义注解实现接口日志记录 4.1.自定义日志注

  • 在springboot中使用AOP进行全局日志记录

    目录 前言 1. spring AOP 是什么? 2.spring AOP 能做什么? 3.spring AOP 我能用 AOP 解决什么问题? 一.引入依赖,增加自定义注解 1.引入 maven 依赖 2.增加自定义注解 OperationLog 二.为自定义注解编写切面实现 三.使用自定义日志注解 前言 此前项目上需要对用户的操作进行日志记录,以便后续追踪问题,所以就学习了使用 spring AOP 来进行日志记录. 1. spring AOP 是什么? spring 的两大核心就是 IOC

随机推荐