现在我以我项目的上传用户行为记录做示例
实体类
package com.xy.admin.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
*
* </p>
*
* @author duGalaxy
* @since 2024-01-31
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class UserTrail implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* iptv账号
*/
private String iptvAccount;
/**
* 访问路径
*/
private String route;
/**
* 访问界面描述
*/
private String details;
/**
* 访问时间
*/
private Date time;
/**
* 类型
*/
private String type;
}
控制层
package com.xy.admin.controller;
import com.xy.admin.entity.UserTrail;
import com.xy.admin.service.UserTrailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.sql.Timestamp;
/**
* <p>
* 前端控制器
* </p>
*
* @author duGalaxy
* @since 2024-01-31
*/
@RestController
@RequestMapping("/trail")
@Slf4j
public class UserTrailController {
@Autowired
private UserTrailService userTrailService;
@PostMapping("addTrail")
public String addTrail(String userId,String route, String details,String type){
if("".equals(userId)|| "".equals(route)|| "".equals(details)|| "".equals(type)){
log.info("参数为空,添加失败!");
return "参数为空,添加失败!";
}else{
UserTrail records = new UserTrail();
records.setIptvAccount(userId);
records.setRoute(route);
records.setDetails(details);
records.setType(type);
records.setTime(new Timestamp(System.currentTimeMillis()));
return userTrailService.add(records) ? "添加成功!" : "添加失败!";
}
}
}
service层
package com.xy.admin.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xy.admin.entity.UserTrail;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xy.admin.mapper.UserTrailMapper;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author duGalaxy
* @since 2024-01-31
*/
public interface UserTrailService extends IService<UserTrail> {
boolean add(UserTrail records);
}
重点
package com.xy.admin.service.impl;
import com.xy.admin.entity.UserTrail;
import com.xy.admin.mapper.UserTrailMapper;
import com.xy.admin.service.UserTrailService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author duGalaxy
* @since 2024-01-31
*/
import org.springframework.scheduling.annotation.Async;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
@Service
@Slf4j
public class UserTrailServiceImpl extends ServiceImpl<UserTrailMapper, UserTrail> implements UserTrailService {
@Autowired
private UserTrailMapper userTrailMapper;
@Resource
private RedisTemplate<String, UserTrail> redisTemplate;
public static final String USER_TRAIL_QUEUE = "user_trail_queue";
@Async
public void saveUserTrailToRedis(UserTrail record) {
// 存储用户轨迹数据到 Redis
redisTemplate.opsForList().rightPush(USER_TRAIL_QUEUE, record);
}
@Async
public void saveUserTrailsToDatabase(List<UserTrail> records) {
// 批量插入用户轨迹数据到 MySQL 数据库
userTrailMapper.batchInsert(records);
}
// 定时任务,每隔一段时间执行一次
@Scheduled(fixedRate = 60000) // 60秒
public void processUserTrails() {
log.info("开始处理用户轨迹数据...");
// 从 Redis 中取出用户轨迹数据并批量插入到 MySQL 数据库
List<UserTrail> userTrails = redisTemplate.opsForList().range(USER_TRAIL_QUEUE, 0, -1);
assert userTrails != null;
if (!userTrails.isEmpty()) {
saveUserTrailsToDatabase(userTrails);
redisTemplate.opsForList().trim(USER_TRAIL_QUEUE, 1, -1);
}
}
@Override
public boolean add(UserTrail record) {
// 异步将用户轨迹数据存储到 Redis
saveUserTrailToRedis(record);
return true; // 返回成功,不等待数据库插入完成
}
}
mapper层
package com.xy.admin.mapper;
import com.xy.admin.entity.UserTrail;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author duGalaxy
* @since 2024-01-31
*/
@Mapper
public interface UserTrailMapper extends BaseMapper<UserTrail> {
void batchInsert(@Param("list")List<UserTrail> records);
}
对应xml,实现批量sql
<?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 XML文件 -->
<mapper namespace="com.xy.admin.mapper.UserTrailMapper">
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO user_trail (iptv_account, route, details, time, type)
VALUES
<foreach collection="list" item="record" separator=",">
(#{record.iptvAccount}, #{record.route}, #{record.details}, #{record.time}, #{record.type})
</foreach>
</insert>
</mapper>
该项目使用了redis,用户行为会先保存在redis,每隔60秒会触发定时任务将redis中的数据持久化到mysql。
评论 (0)