010-53388338

快驴生鲜系统:用户操作日志记录方案设计与实现

分类:IT频道 时间:2025-12-19 06:45 浏览:29
概述
    一、需求分析    1.日志记录范围:  -用户登录/登出操作  -商品浏览、搜索、筛选操作  -购物车操作(添加、修改数量、删除)  -订单创建、支付、取消操作  -售后申请、退款操作  -用户信息修改操作    2.日志内容要求:  -操作时间戳(精确到毫秒)  -用户ID/用户名  -
内容
  
   一、需求分析
  
  1. 日志记录范围:
   - 用户登录/登出操作
   - 商品浏览、搜索、筛选操作
   - 购物车操作(添加、修改数量、删除)
   - 订单创建、支付、取消操作
   - 售后申请、退款操作
   - 用户信息修改操作
  
  2. 日志内容要求:
   - 操作时间戳(精确到毫秒)
   - 用户ID/用户名
   - 操作类型
   - 操作对象(如商品ID、订单号等)
   - 操作结果(成功/失败)
   - 操作详情(如修改前的值、修改后的值)
   - 客户端信息(IP地址、设备类型、浏览器类型等)
  
   二、技术方案设计
  
   1. 日志存储方案
  - 数据库存储:使用MySQL表存储结构化日志
  - 文件存储:同时写入日志文件供离线分析
  - ELK集成:考虑未来扩展,预留Elasticsearch接口
  
   2. 日志表设计
  ```sql
  CREATE TABLE user_operation_log (
   id BIGINT PRIMARY KEY AUTO_INCREMENT,
   user_id BIGINT NOT NULL,
   username VARCHAR(50),
   operation_type VARCHAR(50) NOT NULL,
   operation_object VARCHAR(100),
   operation_result VARCHAR(20) NOT NULL,
   operation_detail TEXT,
   client_ip VARCHAR(50),
   user_agent VARCHAR(255),
   create_time DATETIME(3) NOT NULL,
   INDEX idx_user_id (user_id),
   INDEX idx_operation_time (create_time),
   INDEX idx_operation_type (operation_type)
  );
  ```
  
   3. 实现方式
  - AOP切面实现:使用Spring AOP拦截关键方法
  - 注解方式:自定义@OperationLog注解标记需要记录的方法
  - 异步写入:使用消息队列(如RabbitMQ)异步处理日志写入
  
   三、具体实现代码
  
   1. 自定义注解
  ```java
  @Target(ElementType.METHOD)
  @Retention(RetentionPolicy.RUNTIME)
  public @interface OperationLog {
   String operationType() default "";
   String operationObject() default "";
   String detail() default "";
  }
  ```
  
   2. AOP切面实现
  ```java
  @Aspect
  @Component
  public class OperationLogAspect {
  
   @Autowired
   private OperationLogService logService;
  
   @Autowired
   private HttpServletRequest request;
  
   @Around("@annotation(operationLog)")
   public Object around(ProceedingJoinPoint joinPoint, OperationLog operationLog) throws Throwable {
   // 获取用户信息
   Long userId = getCurrentUserId();
   String username = getCurrentUsername();
  
   // 获取客户端信息
   String ip = getClientIp();
   String userAgent = request.getHeader("User-Agent");
  
   // 记录开始时间
   long startTime = System.currentTimeMillis();
  
   // 执行原方法
   Object result = joinPoint.proceed();
  
   // 计算耗时
   long costTime = System.currentTimeMillis() - startTime;
  
   // 构建日志对象
   OperationLogDTO logDTO = new OperationLogDTO();
   logDTO.setUserId(userId);
   logDTO.setUsername(username);
   logDTO.setOperationType(operationLog.operationType());
   logDTO.setOperationObject(operationLog.operationObject());
   logDTO.setOperationResult(result == null ? "失败" : "成功");
   logDTO.setOperationDetail(operationLog.detail());
   logDTO.setClientIp(ip);
   logDTO.setUserAgent(userAgent);
   logDTO.setCostTime(costTime);
  
   // 异步保存日志
   logService.saveAsync(logDTO);
  
   return result;
   }
  
   // 其他辅助方法...
  }
  ```
  
   3. 日志服务实现
  ```java
  @Service
  public class OperationLogServiceImpl implements OperationLogService {
  
   @Autowired
   private OperationLogMapper logMapper;
  
   @Autowired
   private RabbitTemplate rabbitTemplate;
  
   @Override
   public void save(OperationLogDTO logDTO) {
   // 直接写入数据库
   OperationLogEntity entity = convertToEntity(logDTO);
   logMapper.insert(entity);
   }
  
   @Override
   @Async
   public void saveAsync(OperationLogDTO logDTO) {
   // 发送到消息队列异步处理
   rabbitTemplate.convertAndSend("log.exchange", "log.save", logDTO);
   }
  
   // 消息消费者
   @RabbitListener(queues = "log.save.queue")
   public void consumeLogMessage(OperationLogDTO logDTO) {
   OperationLogEntity entity = convertToEntity(logDTO);
   logMapper.insert(entity);
   }
  }
  ```
  
   四、日志查询功能实现
  
  1. 查询接口:
  ```java
  @RestController
  @RequestMapping("/api/logs")
  public class LogController {
  
   @Autowired
   private LogQueryService logQueryService;
  
   @GetMapping
   public Result> queryLogs(
   @RequestParam(required = false) Long userId,
   @RequestParam(required = false) String operationType,
   @RequestParam(required = false) Date startTime,
   @RequestParam(required = false) Date endTime,
   @RequestParam(defaultValue = "1") Integer pageNum,
   @RequestParam(defaultValue = "10") Integer pageSize) {
  
   Page page = logQueryService.queryLogs(
   userId, operationType, startTime, endTime, pageNum, pageSize);
   return Result.success(page);
   }
  }
  ```
  
  2. 查询服务:
  ```java
  @Service
  public class LogQueryServiceImpl implements LogQueryService {
  
   @Autowired
   private OperationLogMapper logMapper;
  
   @Override
   public Page queryLogs(Long userId, String operationType,
   Date startTime, Date endTime,
   Integer pageNum, Integer pageSize) {
  
   PageHelper.startPage(pageNum, pageSize);
   List entities = logMapper.selectByCondition(
   userId, operationType, startTime, endTime);
  
   List vos = entities.stream()
   .map(this::convertToVO)
   .collect(Collectors.toList());
  
   return new Page<>(vos);
   }
  }
  ```
  
   五、测试与验证
  
  1. 单元测试:
   - 测试日志记录是否正常写入
   - 测试异常情况下的日志记录
   - 测试异步日志处理是否正确
  
  2. 集成测试:
   - 模拟用户操作,验证日志是否完整记录
   - 测试高并发情况下的日志处理能力
  
  3. 性能测试:
   - 测试日志写入对系统性能的影响
   - 测试日志查询的响应时间
  
   六、部署与监控
  
  1. 日志轮转配置:
   - 配置日志文件大小限制和保留天数
   - 设置日志文件压缩和归档策略
  
  2. 监控告警:
   - 监控日志写入延迟
   - 设置日志写入失败告警
   - 监控日志查询接口响应时间
  
   七、优化方向
  
  1. 日志分级:根据操作重要性设置不同日志级别
  2. 采样记录:对高频操作进行采样记录,减少存储压力
  3. 日志分析:开发日志分析功能,生成用户行为报告
  4. 数据脱敏:对敏感信息进行脱敏处理
  
   八、开发注意事项
  
  1. 确保日志记录不影响主业务流程性能
  2. 考虑日志存储的空间占用,设置合理的保留策略
  3. 保护用户隐私,避免记录敏感信息
  4. 考虑分布式系统下的日志收集问题
  5. 提供日志清理和归档功能
  
  通过以上方案,快驴生鲜系统能够完整记录用户操作日志,为系统运维、安全审计和用户行为分析提供有力支持。
评论
  • 上一篇