010-53388338

快驴生鲜系统用户操作日志开发详解:从需求到部署优化全流程

分类:IT频道 时间:2026-02-08 23:40 浏览:24
概述
    一、需求分析    1.日志记录目的:  -审计追踪:记录用户所有关键操作,便于问题排查和合规性检查  -安全监控:识别异常操作行为,预防潜在安全威胁  -数据分析:了解用户行为模式,优化系统功能    2.需记录的操作类型:  -登录/登出操作  -权限变更操作  -关键数据修改(商品信息
内容
  
   一、需求分析
  
  1. 日志记录目的:
   - 审计追踪:记录用户所有关键操作,便于问题排查和合规性检查
   - 安全监控:识别异常操作行为,预防潜在安全威胁
   - 数据分析:了解用户行为模式,优化系统功能
  
  2. 需记录的操作类型:
   - 登录/登出操作
   - 权限变更操作
   - 关键数据修改(商品信息、订单状态、价格调整等)
   - 批量操作(导入/导出、批量删除等)
   - 系统配置变更
  
  3. 日志内容要求:
   - 操作时间
   - 操作用户
   - 操作类型
   - 操作对象(如商品ID、订单号等)
   - 操作前数据状态(可选)
   - 操作后数据状态
   - 操作结果(成功/失败)
   - 客户端IP地址
  
   二、技术方案设计
  
   1. 日志存储方案
  
  方案一:数据库存储
  - 优点:便于查询、结构化存储
  - 缺点:高并发写入可能影响性能
  - 实现:创建`user_operation_log`表
  
  ```sql
  CREATE TABLE user_operation_log (
   id BIGINT PRIMARY KEY AUTO_INCREMENT,
   user_id BIGINT NOT NULL COMMENT 用户ID,
   username VARCHAR(50) NOT NULL COMMENT 用户名,
   operation_type VARCHAR(50) NOT NULL COMMENT 操作类型,
   operation_object VARCHAR(100) COMMENT 操作对象ID,
   old_value TEXT COMMENT 操作前值,
   new_value TEXT COMMENT 操作后值,
   result VARCHAR(20) NOT NULL COMMENT 操作结果(SUCCESS/FAIL),
   ip_address VARCHAR(50) COMMENT 客户端IP,
   user_agent VARCHAR(255) COMMENT 用户代理,
   create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 操作时间,
   INDEX idx_user_id (user_id),
   INDEX idx_operation_time (create_time),
   INDEX idx_operation_type (operation_type)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=用户操作日志表;
  ```
  
  方案二:文件存储+ELK
  - 优点:高性能写入,适合大规模日志
  - 缺点:需要额外维护ELK栈
  - 实现:使用Logback/Log4j2写入文件,通过Filebeat收集到Elasticsearch
  
   2. 日志记录方式
  
  方案一:AOP切面实现
  ```java
  @Aspect
  @Component
  public class OperationLogAspect {
  
   @Autowired
   private UserOperationLogService logService;
  
   @Pointcut("@annotation(com.kuailu.annotation.OperationLog)")
   public void logPointCut() {}
  
   @AfterReturning(pointcut = "logPointCut()", returning = "result")
   public void afterReturning(JoinPoint joinPoint, Object result) {
   // 获取方法注解信息
   MethodSignature signature = (MethodSignature) joinPoint.getSignature();
   Method method = signature.getMethod();
   OperationLog operationLog = method.getAnnotation(OperationLog.class);
  
   // 获取请求参数
   Object[] args = joinPoint.getArgs();
  
   // 构建日志对象
   UserOperationLog log = new UserOperationLog();
   // 设置日志属性...
  
   logService.save(log);
   }
  }
  ```
  
  方案二:手动调用服务层
  在每个需要记录日志的方法中显式调用日志服务
  
   3. 自定义注解设计
  
  ```java
  @Target(ElementType.METHOD)
  @Retention(RetentionPolicy.RUNTIME)
  public @interface OperationLog {
   /
   * 操作类型
   */
   String operationType();
  
   /
   * 操作对象类型
   */
   String objectType() default "";
  
   /
   * 是否记录请求参数
   */
   boolean logParams() default true;
  
   /
   * 是否记录响应结果
   */
   boolean logResult() default false;
  
   /
   * 操作描述
   */
   String description() default "";
  }
  ```
  
   三、具体实现
  
   1. 日志服务实现
  
  ```java
  @Service
  public class UserOperationLogServiceImpl implements UserOperationLogService {
  
   @Autowired
   private UserOperationLogMapper logMapper;
  
   @Autowired
   private HttpServletRequest request;
  
   @Override
   @Transactional(propagation = Propagation.NOT_SUPPORTED)
   public void save(UserOperationLogDTO logDTO) {
   // 获取当前用户信息
   UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  
   // 构建日志实体
   UserOperationLog log = new UserOperationLog();
   log.setUserId(userDetails.getUserId());
   log.setUsername(userDetails.getUsername());
   log.setOperationType(logDTO.getOperationType());
   log.setOperationObject(logDTO.getOperationObject());
   log.setOldValue(logDTO.getOldValue());
   log.setNewValue(logDTO.getNewValue());
   log.setResult(logDTO.getResult());
   log.setIpAddress(getIpAddress());
   log.setUserAgent(request.getHeader("User-Agent"));
  
   // 保存日志
   logMapper.insert(log);
   }
  
   private String getIpAddress() {
   // IP获取逻辑...
   }
  }
  ```
  
   2. 控制器示例
  
  ```java
  @RestController
  @RequestMapping("/api/products")
  public class ProductController {
  
   @Autowired
   private ProductService productService;
  
   @OperationLog(
   operationType = "UPDATE_PRODUCT",
   objectType = "PRODUCT",
   description = "更新商品信息"
   )
   @PutMapping("/{id}")
   public Result updateProduct(@PathVariable Long id, @RequestBody ProductDTO productDTO) {
   // 获取修改前数据
   Product oldProduct = productService.getById(id);
  
   // 执行更新
   productService.update(id, productDTO);
  
   // 获取修改后数据
   Product newProduct = productService.getById(id);
  
   // 构建日志参数(实际可通过AOP自动获取)
   Map logParams = new HashMap<>();
   logParams.put("oldProduct", oldProduct);
   logParams.put("newProduct", newProduct);
  
   return Result.success();
   }
  }
  ```
  
   四、高级功能实现
  
   1. 异步日志记录
  
  ```java
  @Configuration
  public class AsyncLogConfig {
  
   @Bean("logExecutor")
   public Executor logExecutor() {
   ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
   executor.setCorePoolSize(5);
   executor.setMaxPoolSize(10);
   executor.setQueueCapacity(100);
   executor.setThreadNamePrefix("log-executor-");
   executor.initialize();
   return executor;
   }
  }
  
  // 在日志服务中添加@Async注解
  @Service
  public class UserOperationLogServiceImpl implements UserOperationLogService {
  
   @Async("logExecutor")
   @Override
   public void save(UserOperationLogDTO logDTO) {
   // 日志保存逻辑
   }
  }
  ```
  
   2. 日志脱敏处理
  
  ```java
  public class LogDesensitizer {
  
   public static String desensitize(String content, String fieldType) {
   if (StringUtils.isEmpty(content)) {
   return content;
   }
  
   switch (fieldType) {
   case "phone":
   return content.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1$2");
   case "id_card":
   return content.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1$2");
   case "address":
   return content.length() > 6 ? content.substring(0, 3) + "*" + content.substring(content.length()-3) : content;
   default:
   return content;
   }
   }
  }
  ```
  
   3. 日志查询接口
  
  ```java
  @RestController
  @RequestMapping("/api/logs")
  public class LogController {
  
   @Autowired
   private UserOperationLogService logService;
  
   @GetMapping
   public Result queryLogs(
   @RequestParam(required = false) String username,
   @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) {
  
   PageInfo pageInfo = logService.queryLogs(
   username, operationType, startTime, endTime, pageNum, pageSize);
  
   return Result.success(pageInfo);
   }
  }
  ```
  
   五、部署与监控
  
  1. 日志清理策略:
   - 设置定时任务定期清理过期日志(如保留90天)
   - 考虑将历史日志归档到廉价存储
  
  2. 监控告警:
   - 监控日志写入失败情况
   - 对异常操作频率设置告警阈值
  
  3. 性能优化:
   - 批量插入日志
   - 对高频操作考虑采样记录
  
   六、测试用例
  
  1. 正常操作日志记录:
   - 测试各种操作类型是否能正确记录
   - 验证日志内容完整性
  
  2. 异常情况处理:
   - 测试日志服务不可用时系统行为
   - 测试高并发场景下的日志记录
  
  3. 脱敏测试:
   - 验证敏感信息是否被正确脱敏
  
  4. 查询功能测试:
   - 测试各种查询条件的组合效果
   - 验证分页功能
  
   七、后续优化方向
  
  1. 引入日志分析平台(如ELK)实现可视化分析
  2. 添加操作日志导出功能
  3. 实现操作日志的自动关联(如根据订单号关联所有相关操作)
  4. 添加操作日志的审计签名功能
  
  以上是快驴生鲜系统用户操作日志开发的基本记录,实际实现时可根据具体业务需求和技术栈进行调整。
评论
  • 下一篇

  • Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 8192 bytes) in /www/wwwroot/www.sjwxsc.com/config/function.php on line 274