Spring AOP实现接口请求记录到数据库的示例代码

作者:AboutChristopher 时间:2023-08-15 19:14:05 

1.引入AOP依赖

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

2.创建日志记录表

DROP TABLE IF EXISTS `rule_operate_log`;
CREATE TABLE `rule_operate_log`  (
   id INT(11) NOT NULL AUTO_INCREMENT COMMENT '日志id',
   path VARCHAR(4000) NULL DEFAULT NULL COMMENT '接口地址',
   http_method VARCHAR(32) NULL DEFAULT NULL COMMENT '请求方法',
   status_code VARCHAR(32) NULL DEFAULT NULL COMMENT '请求返回状态码',
   create_time_char VARCHAR(32) NULL DEFAULT NULL COMMENT '日志时间',
   create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '日志时间戳',
   ip varchar(200) NULL DEFAULT NULL COMMENT '请求ip',
   params mediumtext NULL COMMENT '请求参数',
   result mediumtext NULL COMMENT '返回值',
   exception mediumtext NULL COMMENT '接口异常',
   user_id VARCHAR(32) NULL DEFAULT NULL COMMENT '操作用户',
   user_account VARCHAR(32) NULL DEFAULT NULL COMMENT '操作用户账号',
   user_name VARCHAR(200) NULL DEFAULT NULL COMMENT '操作用户名称',
   user_org_id VARCHAR(32) NULL DEFAULT NULL COMMENT '操作用户机构id',
   user_org_name VARCHAR(200) NULL DEFAULT NULL COMMENT '操作用户机构名称',
   operate_name VARCHAR(200) NULL DEFAULT NULL COMMENT '操作名称',
   operate_position VARCHAR(200) NULL DEFAULT NULL COMMENT '操作位置',
   log_type VARCHAR(32) NULL DEFAULT NULL COMMENT '日志类型 error:错误日志 operate:操作日志',
   category_id VARCHAR(32) NULL DEFAULT NULL COMMENT '分类机构id',
   cost INT(11) NULL DEFAULT NULL COMMENT '接口耗时',
   PRIMARY KEY (id)
) COMMENT = '操作日志表';

3.日志实体类

import java.util.Date;

public class RuleOperateLog {
   /**
    * id
    */
   private Integer id;
   /**
    * 接口地址
    */
   private String path;
   /**
    * 请求方法
    */
   private String httpMethod;
   /**
    * 请求返回状态码
    */
   private String statusCode;
   /**
    * 日志时间
    */
   private String createTimeChar;
   /**
    * 日志时间戳
    */
   private Date createTime;
   /**
    * 请求ip
    */
   private String ip;
   /**
    * 请求参数
    */
   private String params;
   /**
    * 返回值
    */
   private String result;
   /**
    * 接口异常
    */
   private String exception;
   /**
    * 操作用户
    */
   private String userId;
   /**
    * 操作用户账号
    */
   private String userAccount;
   /**
    * 操作用户名称
    */
   private String userName;
   /**
    * 操作用户机构
    */
   private String userOrgId;
   /**
    * 操作用户机构名称
    */
   private String userOrgName;
   /**
    * 操作名称
    */
   private String operateName;
   /**
    * 操作位置
    */
   private String operatePosition;
   /**
    * 日志类型
    */
   private String logType;
   /**
    * 分类机构id
    */
   private String categoryId;
   /**
    * 请求耗时
    */
   private Integer cost;

public Integer getId() {
       return id;
   }

public void setId(Integer id) {
       this.id = id;
   }

public String getPath() {
       return path;
   }

public void setPath(String path) {
       this.path = path;
   }

public String getHttpMethod() {
       return httpMethod;
   }

public void setHttpMethod(String httpMethod) {
       this.httpMethod = httpMethod;
   }

public String getStatusCode() {
       return statusCode;
   }

public void setStatusCode(String statusCode) {
       this.statusCode = statusCode;
   }

public String getCreateTimeChar() {
       return createTimeChar;
   }

public void setCreateTimeChar(String createTimeChar) {
       this.createTimeChar = createTimeChar;
   }

public Date getCreateTime() {
       return createTime;
   }

public void setCreateTime(Date createTime) {
       this.createTime = createTime;
   }

public String getIp() {
       return ip;
   }

public void setIp(String ip) {
       this.ip = ip;
   }

public String getParams() {
       return params;
   }

public void setParams(String params) {
       this.params = params;
   }

public String getResult() {
       return result;
   }

public void setResult(String result) {
       this.result = result;
   }

public String getException() {
       return exception;
   }

public void setException(String exception) {
       this.exception = exception;
   }

public String getUserId() {
       return userId;
   }

public void setUserId(String userId) {
       this.userId = userId;
   }

public String getUserAccount() {
       return userAccount;
   }

public void setUserAccount(String userAccount) {
       this.userAccount = userAccount;
   }

public String getUserName() {
       return userName;
   }

public void setUserName(String userName) {
       this.userName = userName;
   }

public String getUserOrgId() {
       return userOrgId;
   }

public void setUserOrgId(String userOrgId) {
       this.userOrgId = userOrgId;
   }

public String getUserOrgName() {
       return userOrgName;
   }

public void setUserOrgName(String userOrgName) {
       this.userOrgName = userOrgName;
   }

public String getOperateName() {
       return operateName;
   }

public void setOperateName(String operateName) {
       this.operateName = operateName;
   }

public String getOperatePosition() {
       return operatePosition;
   }

public void setOperatePosition(String operatePosition) {
       this.operatePosition = operatePosition;
   }

public String getLogType() {
       return logType;
   }

public void setLogType(String logType) {
       this.logType = logType;
   }

public String getCategoryId() {
       return categoryId;
   }

public void setCategoryId(String categoryId) {
       this.categoryId = categoryId;
   }

public Integer getCost() {
       return cost;
   }

public void setCost(Integer cost) {
       this.cost = cost;
   }
}

4.Dao+Mapper+service

import com.xxx.xxx.xxx.entity.RuleOperateLog;

/**
* 操作日志(RuleOperateLog)表数据库访问层
*
* @author hx
* @since 2022-08-23
*/
public interface RuleOperateLogDao {

/**
    * 新增数据
    *
    * @param operateLog
    * @return
    */
   int insert(RuleOperateLog operateLog);
}
<?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="com.xxx.xxx.xxx.dao.RuleOperateLogDao">

<resultMap type="com.xxx.xxx.xxx.entity.RuleOperateLog" id="RuleOperateLogMap">
       <result property="id" column="id" jdbcType="INTEGER"/>
       <result property="path" column="path" jdbcType="VARCHAR"/>
       <result property="httpMethod" column="http_method" jdbcType="VARCHAR"/>
       <result property="statusCode" column="status_code" jdbcType="VARCHAR"/>
       <result property="createTimeChar" column="create_time_char" jdbcType="VARCHAR"/>
       <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
       <result property="ip" column="ip" jdbcType="VARCHAR"/>
       <result property="params" column="params" jdbcType="VARCHAR"/>
       <result property="result" column="result" jdbcType="VARCHAR"/>
       <result property="exception" column="exception" jdbcType="VARCHAR"/>
       <result property="userId" column="user_id" jdbcType="VARCHAR"/>
       <result property="userAccount" column="user_account" jdbcType="VARCHAR"/>
       <result property="userName" column="user_name" jdbcType="VARCHAR"/>
       <result property="userOrgId" column="user_org_id" jdbcType="VARCHAR"/>
       <result property="userOrgName" column="user_org_name" jdbcType="VARCHAR"/>
       <result property="operateName" column="operate_name" jdbcType="VARCHAR"/>
       <result property="operatePosition" column="operate_position" jdbcType="VARCHAR"/>
       <result property="logType" column="log_type" jdbcType="VARCHAR"/>
       <result property="categoryId" column="category_id" jdbcType="VARCHAR"/>
       <result property="cost" column="cost" jdbcType="INTEGER"/>
   </resultMap>

<insert id="insert" keyProperty="id" useGeneratedKeys="true">
       insert into rule_operate_log (id, path, http_method, status_code, create_time_char, create_time,
                                     ip, params, result, exception, user_id, user_account, user_name, user_org_id,
                                     user_org_name, operate_name, operate_position, log_type, category_id, cost)
       values (#{id}, #{path}, #{httpMethod}, #{statusCode}, #{createTimeChar}, #{createTime}, #{ip}, #{params}, #{result},
               #{exception},#{userId}, #{userAccount}, #{userName}, #{userOrgId}, #{userOrgName}, #{operateName}, #{operatePosition},
               #{logType}, #{categoryId}, #{cost})
   </insert>

</mapper>
import com.xxx.xxx.xxx.entity.RuleOperateLog;

/**
* 操作日志(RuleOperateLog)表服务接口
*
* @author hx
* @since 2022-08-23
*/
public interface RuleOperateLogService {

/**
    * 保存日志
    *
    * @param ruleOperateLog
    * @return
    */
   void saveLog(RuleOperateLog ruleOperateLog);

}
import com.xxx.xxx.xxx.dao.RuleOperateLogDao;
import com.xxx.xxx.xxx.entity.RuleOperateLog;
import com.xxx.xxx.xxx.service.RuleOperateLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
* 操作日志(RuleOperateLog)表服务实现类
*
* @author hx
* @since 2022-08-23
*/
@Service("RuleOperateLogService")
public class RuleOperateLogServiceImpl implements RuleOperateLogService {

@Autowired
   private RuleOperateLogDao operateLogDao;

@Override
   public void saveLog(RuleOperateLog ruleOperateLog) {
       operateLogDao.insert(ruleOperateLog);
   }
}

5.自定义注解

import java.lang.annotation.*;

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface LogResource {
   /**
    * 服务名称
    * @return
    */
   String name();

/**
    * 操作位置描述
    * @return
    */
   String position() default "";

/**
    * 日志类型
    * @return
    */
   String logType() default "";
}

6.操作日志切面类

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.com.xxx.xxx.xxx.annotation.LogResource;
import com.com.xxx.xxx.xxx.constants.LogTypeConstants;
import com.com.xxx.xxx.xxx.entity.RuleOperateLog;
import com.com.xxx.xxx.xxx.service.RuleOperateLogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.Async;
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 javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* 操作日志切面类
*
* @author hx
* @since 2022-08-23
*/

@Aspect
@Component
public class OperateLogAspect {

@Autowired
   private RuleOperateLogService operateLogService;

//扫描使用@LogResource注解的方法
   @Pointcut("@annotation(com.com.xxx.xxx.xxx.annotation.LogResource)")
   public void logPointCut() { };

@Around("logPointCut()")
   public Object around(ProceedingJoinPoint point) throws Throwable {
       Date startTime = new Date();
       String exception = null;
       String result = null;
       try {
           Object obj = point.proceed();
           if (obj != null) {
               result = JSONObject.toJSONString(obj);
           }
           return obj;
       } catch (Exception e) {
           //请求时报错
           exception = e.toString();
           throw e;
       } finally {
           //操作和报错日志都记录
           HttpServletResponse response
                   = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
           int statusCode = response.getStatus();
           if (exception != null) {
               /** CHECKSTYLE:OFF:MagicNumber */
               statusCode = 500;
               /** CHECKSTYLE:ON:MagicNumber */
           }
           syncSaveLog(point, startTime, new Date(), exception, result, statusCode);
       }
   }

@Async
   void syncSaveLog(ProceedingJoinPoint joinPoint, Date startTime, Date endTime,
                    String exception, String result, int statusCode) {
       RuleOperateLog log = new RuleOperateLog();
       try {
           MethodSignature signature = (MethodSignature) joinPoint.getSignature();
           Method method = signature.getMethod();
           LogResource annotation = method.getAnnotation(LogResource.class);
           if (annotation != null) {
               //注解上的描述
               log.setOperateName(annotation.name());
           }
           Date nowDate = new Date();
           log.setCreateTimeChar(new SimpleDateFormat("yyyyMMddhhmmss").format(nowDate));
           log.setCreateTime(nowDate);
           //入参
           if (joinPoint.getArgs() != null) {
               try {
                   log.setParams(JSONObject.toJSONString(joinPoint.getArgs(),
                           SerializerFeature.IgnoreNonFieldGetter));
               } catch (Exception e) {
                   e.printStackTrace();
               }
           }

Long cost = endTime.getTime() - startTime.getTime();
           log.setCost(cost.intValue());
           HttpServletRequest request
                   = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
           if (request != null) {
               log.setUserName(request.getHeader(HttpHeaders.USER_AGENT));
               log.setPath(request.getRequestURI());
               log.setHttpMethod(request.getMethod());
               log.setIp(request.getRemoteAddr());
           }
           log.setStatusCode(String.valueOf(statusCode));
           log.setResult(result);
           /** CHECKSTYLE:OFF:MagicNumber */
           if (statusCode > 400 && exception != null) {
               log.setException(exception);
               log.setLogType(LogTypeConstants.ERROR);
           } else {
               log.setLogType(LogTypeConstants.OPERATE);
           }
           /** CHECKSTYLE:ON:MagicNumber */
           operateLogService.saveLog(log);
       } catch (Exception e) {
           e.printStackTrace();
       }

/*        //启动一个线程,执行报错日志防止影响主请求
       new Thread() {
           @Override
           public void run() {
               try {
                   //保存到数据库
                   operLogMapper.insertOper(operLog);
               } catch (Exception e) {
                   e.printStackTrace();
               }
           }
       }.start();*/
   }
}

7.使用

Spring AOP实现接口请求记录到数据库的示例代码

来源:https://www.cnblogs.com/huangxuannn/p/16730848.html

标签:Spring,AOP,接口请求,数据库
0
投稿

猜你喜欢

  • springboot配置项目启动后自动打开浏览器访问项目方式

    2023-10-05 07:33:09
  • IntelliJ IDEA 2022.2 正式发布新功能体验

    2021-08-14 02:47:33
  • JAVA心得分享---return语句的用法

    2023-04-14 11:52:54
  • 基于C#模拟实现回合制游戏

    2021-08-01 23:09:55
  • JavaScript中栈和队列应用详情

    2023-05-01 00:25:52
  • Java多线程 ReentrantLock互斥锁详解

    2022-07-23 21:21:06
  • Android启动画面的实现方法

    2023-12-27 23:22:11
  • Android性能优化之利用强大的LeakCanary检测内存泄漏及解决办法

    2021-07-26 11:57:46
  • Java类中this关键字与static关键字的用法解析

    2023-11-09 22:45:19
  • java实现动态代理示例分享

    2023-04-28 15:54:49
  • Java spring定时任务详解

    2022-05-22 19:51:06
  • Maven+Tomcat8 实现自动化部署的方法

    2023-01-03 06:44:20
  • C#实现的文件操作封装类完整实例【删除,移动,复制,重命名】

    2022-09-14 20:41:14
  • 使用spring注入枚举类型作为参数

    2023-11-23 13:25:57
  • RocketMQ producer发送者浅析

    2023-04-03 06:35:32
  • Android NDK开发(C语言字符串)

    2023-06-18 10:21:28
  • c#定时运行程序分享(定时程序)

    2023-12-11 20:47:31
  • C#利用缓存分块读写大文件

    2022-10-20 11:18:22
  • 使用开源项目JAVAE2 进行视频格式转换

    2023-11-08 07:18:24
  • java文字转语音播报功能的实现方法

    2022-05-08 18:44:41
  • asp之家 软件编程 m.aspxhome.com