<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      記錄用戶業(yè)務(wù)請(qǐng)求日志

      在用戶的一般使用的時(shí)候,對(duì)于很多操作類型的接口,為了后面便于追查問題,需要記錄用戶的請(qǐng)求日志。

      用戶的請(qǐng)求日志目前主流的存儲(chǔ)方式有:

      1. 日志文件
      2. 數(shù)據(jù)庫
      3. MongoDB
      4. ElasticSearch

      在商城的項(xiàng)目中暫時(shí)存放在MySQL中了。

      增加注解

      增加專門的注解標(biāo)識(shí)哪些是需要記錄用戶日志的。

      注解就叫BizLog注解:

      @Target(ElementType.METHOD)
      @Retention(RetentionPolicy.RUNTIME)
      public @interface BizLog {
      
          String value() default "";
      }
      

      其中的value參數(shù),用來接收用戶自定義的日志描述。

      后面只要有接口打上了這個(gè)注解,就會(huì)自動(dòng)將用戶的業(yè)務(wù)請(qǐng)求日志記錄到數(shù)據(jù)庫中。

      增加業(yè)務(wù)日志表

      為了方便后續(xù)追溯用戶的請(qǐng)求行為,將用戶的業(yè)務(wù)請(qǐng)求日志記錄到數(shù)據(jù)庫的某一張表中。

      這樣以后就可以通過這張表查詢數(shù)據(jù)了。

      CREATE TABLE `biz_log` (
        `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
        `method_name` varchar(30) NOT NULL COMMENT '方法名稱',
        `description` varchar(30) NOT NULL COMMENT '描述',
        `request_ip` varchar(15) NOT NULL COMMENT '請(qǐng)求ip',
        `browser` varchar(200)  NULL COMMENT '瀏覽器',
        `url` varchar(100) NOT NULL COMMENT '請(qǐng)求地址',
        `param` varchar(300)  NULL COMMENT '請(qǐng)求參數(shù)',
        `time` int NOT NULL COMMENT '耗時(shí),毫秒級(jí)',
        `exception` varchar(300)  NULL COMMENT '異常',
        `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '狀態(tài) 1:成功 0:失敗',
        `create_user_id` bigint NOT NULL COMMENT '創(chuàng)建人ID',
        `create_user_name` varchar(30) NOT NULL COMMENT '創(chuàng)建人名稱',
        `create_time` datetime(3) DEFAULT NULL COMMENT '創(chuàng)建日期',
        `update_user_id` bigint DEFAULT NULL COMMENT '修改人ID',
        `update_user_name` varchar(30)  DEFAULT NULL COMMENT '修改人名稱',
        `update_time` datetime(3) DEFAULT NULL COMMENT '修改時(shí)間',
        `is_del` tinyint(1) DEFAULT '0' COMMENT '是否刪除 1:已刪除 0:未刪除',
        PRIMARY KEY (`id`) USING BTREE
      ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='業(yè)務(wù)日志表';
      

      增加業(yè)務(wù)日志攔截器

      package com.kailong.interceptor;
      
      import cn.hutool.http.useragent.UserAgent;
      import cn.hutool.http.useragent.UserAgentUtil;
      import com.kailong.annotation.BizLog;
      import com.kailong.entity.log.BizLogEntity;
      import com.kailong.service.log.BizLogService;
      import com.kailong.util.IpUtil;
      import org.aspectj.lang.JoinPoint;
      import org.aspectj.lang.ProceedingJoinPoint;
      import org.aspectj.lang.annotation.AfterThrowing;
      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.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 BizLogAspect {
      
          @Autowired
          private BizLogService bizLogService;
      
          @Pointcut("@annotation(com.kailong.annotation.BizLog)")
          public void pointcut() {
          }
      
          @Around("pointcut()")
          public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
              long startTime = System.currentTimeMillis();
              HttpServletRequest httpServletRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                      .getRequest();
              Object result = joinPoint.proceed();
              long time = System.currentTimeMillis() - startTime;
      
              BizLogEntity bizLogEntity = createBizLogEntity(joinPoint, httpServletRequest);
              bizLogEntity.setTime((int) time);
              bizLogEntity.setStatus(1);
              bizLogService.save(bizLogEntity);
              return result;
          }
      
          private String getParam(JoinPoint joinPoint) {
              StringBuilder params = new StringBuilder("{");
              Object[] argValues = joinPoint.getArgs();
              String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
              if (argValues != null) {
                  for (int i = 0; i < argValues.length; i++) {
                      params.append(" ").append(argNames[i]).append(": ").append(argValues[i]);
                  }
              }
              return params.append("}").toString();
          }
      
          private BizLogEntity createBizLogEntity(JoinPoint joinPoint, HttpServletRequest httpServletRequest) {
              MethodSignature signature = (MethodSignature) joinPoint.getSignature();
              Method method = signature.getMethod();
              BizLog bizLog = method.getAnnotation(BizLog.class);
              String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName();
      
              BizLogEntity bizLogEntity = new BizLogEntity();
              bizLogEntity.setDescription(bizLog.value());
              bizLogEntity.setMethodName(methodName);
              bizLogEntity.setStatus(1);
              bizLogEntity.setRequestIp(IpUtil.getIpAddr(httpServletRequest));
              bizLogEntity.setUrl(httpServletRequest.getRequestURI());
              bizLogEntity.setBrowser(getBrowserName(httpServletRequest));
              bizLogEntity.setParam(getParam(joinPoint));
              return bizLogEntity;
          }
      
          @AfterThrowing(pointcut = "pointcut()", throwing = "e")
          public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
              HttpServletRequest httpServletRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                      .getRequest();
              BizLogEntity bizLogEntity = createBizLogEntity(joinPoint, httpServletRequest);
              bizLogEntity.setStatus(0);
              bizLogEntity.setException(e.getMessage());
              bizLogService.save(bizLogEntity);
          }
      
      
          private String getBrowserName(HttpServletRequest httpServletRequest) {
              String userAgentString = httpServletRequest.getHeader("User-Agent");
              UserAgent ua = UserAgentUtil.parse(userAgentString);
              return ua.getBrowser().toString();
          }
      }
      

      這個(gè)攔截器會(huì)記錄用戶業(yè)務(wù)請(qǐng)求的ip、地址、參數(shù)、瀏覽器和接口耗時(shí)都數(shù)據(jù)。

      如果用戶業(yè)務(wù)請(qǐng)求失敗了,也會(huì)記錄一條失敗的數(shù)據(jù)。

      BizLog相關(guān)類

      (基礎(chǔ)設(shè)置,實(shí)際項(xiàng)目需修改)

      BizLogEntity

      package com.kailong.entity.log;
      
      /**
       * created by kailong on 2025/9/23
       */
      
      import com.baomidou.mybatisplus.annotation.IdType;
      import com.baomidou.mybatisplus.annotation.TableId;
      import com.baomidou.mybatisplus.annotation.TableName;
      import com.kailong.entity.BaseEntity;
      import io.swagger.v3.oas.annotations.media.Schema;
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      import java.io.Serializable;
      import java.util.Date;
      
      /**
       * 業(yè)務(wù)日志實(shí)體類
       * 對(duì)應(yīng)表:biz_log
       */
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      @TableName("biz_log") // 指定MyBatis-Plus對(duì)應(yīng)的表名
      @Schema(description = "業(yè)務(wù)日志實(shí)體類,用于記錄系統(tǒng)業(yè)務(wù)操作日志") // Swagger3類級(jí)別描述
      public class BizLogEntity extends BaseEntity implements Serializable {//可以不繼承BaseEntity
      
          private static final long serialVersionUID = 1L;
      
          /**
           * 日志ID(主鍵,自增)
           */
          @TableId(value = "id", type = IdType.AUTO) // MyBatis-Plus主鍵注解,指定自增策略
          @Schema(description = "日志ID", example = "1") // Swagger3字段描述+示例值
          private Long id;
      
          /**
           * 方法名稱(記錄調(diào)用的業(yè)務(wù)方法名)
           */
          @Schema(description = "方法名稱", example = "getUserInfo")
          private String methodName;
      
          /**
           * 操作描述(記錄業(yè)務(wù)操作的簡(jiǎn)要說明)
           */
          @Schema(description = "操作描述", example = "查詢用戶信息")
          private String description;
      
          /**
           * 請(qǐng)求IP(記錄發(fā)起請(qǐng)求的客戶端IP地址)
           */
          @Schema(description = "請(qǐng)求IP", example = "192.168.1.100")
          private String requestIp;
      
          /**
           * 瀏覽器類型(記錄發(fā)起請(qǐng)求的瀏覽器信息,如Chrome、Firefox)
           */
          @Schema(description = "瀏覽器類型", example = "Chrome 120.0.0.0")
          private String browser;
      
          /**
           * 請(qǐng)求地址(記錄請(qǐng)求的URL路徑,如/api/user/info)
           */
          @Schema(description = "請(qǐng)求地址", example = "/api/user/info")
          private String url;
      
          /**
           * 請(qǐng)求參數(shù)(記錄請(qǐng)求的參數(shù)信息,如{"userId":1})
           */
          @Schema(description = "請(qǐng)求參數(shù)", example = "{\"userId\":1}")
          private String param;
      
          /**
           * 耗時(shí)(記錄業(yè)務(wù)方法執(zhí)行的耗時(shí),單位:毫秒)
           */
          @Schema(description = "耗時(shí)(毫秒)", example = "50")
          private Integer time;
      
          /**
           * 異常信息(記錄業(yè)務(wù)方法執(zhí)行過程中拋出的異常信息,無異常則為空)
           */
          @Schema(description = "異常信息", example = "java.lang.NullPointerException: 用戶不存在")
          private String exception;
      
          /**
           * 狀態(tài)(1:成功 0:失敗,記錄業(yè)務(wù)操作的執(zhí)行結(jié)果)
           */
          @Schema(description = "狀態(tài)(1:成功 0:失敗)", example = "1")
          private int status;
      
          /**
           * 創(chuàng)建人ID(記錄創(chuàng)建該日志的用戶ID)
           */
          @Schema(description = "創(chuàng)建人ID", example = "1001")
          private Long createUserId;
      
          /**
           * 創(chuàng)建人名稱(記錄創(chuàng)建該日志的用戶名)
           */
          @Schema(description = "創(chuàng)建人名稱", example = "admin")
          private String createUserName;
      
          /**
           * 創(chuàng)建時(shí)間(記錄日志的創(chuàng)建時(shí)間,默認(rèn)為當(dāng)前時(shí)間)
           */
          @Schema(description = "創(chuàng)建時(shí)間", example = "2025-09-23 17:13:18")
          private Date createTime;
      
          /**
           * 修改人ID(記錄最后修改該日志的用戶ID,無修改則為空)
           */
          @Schema(description = "修改人ID", example = "1002")
          private Long updateUserId;
      
          /**
           * 修改人名稱(記錄最后修改該日志的用戶名,無修改則為空)
           */
          @Schema(description = "修改人名稱", example = "operator")
          private String updateUserName;
      
          /**
           * 修改時(shí)間(記錄最后修改該日志的時(shí)間,無修改則為空)
           */
          @Schema(description = "修改時(shí)間", example = "2025-09-23 17:15:30")
          private Date updateTime;
      
          /**
           * 是否刪除(1:已刪除 0:未刪除,邏輯刪除標(biāo)記)
           */
          @Schema(description = "是否刪除(1:已刪除 0:未刪除)", example = "0")
          private Integer isDel;
      }
      

      BizLogMapper(用的MyBatisplus)

      @Mapper
      public interface BizLogMapper extends BaseMapper<BizLogEntity> {
      }
      

      BizLogService

      public interface BizLogService {
          public void save(BizLogEntity bizLogEntity);
      }
      

      BizLogServiceImpl

      @Service
      public class BizLogServiceImpl implements BizLogService {
          @Autowired
          private BizLogMapper bizLogMapper;
          @Override
          public void save(BizLogEntity bizLogEntity) {
              FillUserUtil.fillCreateUserInfo(bizLogEntity);
              bizLogMapper.insert(bizLogEntity);
          }
      }
      

      測(cè)試效果

      posted @ 2025-09-24 10:24  愚生淺末  閱讀(25)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 屏东县| 隆安县| 日韩AV高清在线看片| 欧美大肥婆大肥bbbbb| 内射老阿姨1区2区3区4区| 亚洲国产精品自产拍久久| 国内精品久久久久影院不卡| 国产成人精品亚洲资源| 2020国产欧洲精品网站| 999福利激情视频| 亚洲精品香蕉一区二区| 国产中文一区卡二区不卡| 亚洲免费一区二区av| 国产制服丝袜无码视频| 天柱县| 青青草国产自产一区二区| 亚洲精品中文综合第一页| 欧美综合婷婷欧美综合五月 | 国产极品粉嫩学生一线天| 人妻激情一区二区三区四区| 欧美视频网站www色| 怀远县| 香蕉久久夜色精品国产成人| 精品人妻少妇嫩草av专区| 国产第一区二区三区精品| 亚洲精品日韩在线观看| 亚洲人成人伊人成综合网无码| 少妇人妻偷人精品视蜜桃| 从化市| 免费看黄片一区二区三区 | 曲阳县| 自拍偷拍视频一区二区三区| 亚洲色www成人永久网址| 91网站在线看| 亚洲男人的天堂久久香蕉| 亚洲中文字幕精品一区二区三区| 亚洲国产高清精品线久久| 浓毛老太交欧美老妇热爱乱| 亚洲AV日韩精品久久久久| 性姿势真人免费视频放| 无码熟妇人妻av影音先锋|