diff --git a/src/main/java/com/example/demo/Util/RedisUtil.java b/src/main/java/com/example/demo/Util/RedisUtil.java new file mode 100644 index 0000000..1bc95af --- /dev/null +++ b/src/main/java/com/example/demo/Util/RedisUtil.java @@ -0,0 +1,175 @@ +package com.example.demo.Util; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ZSetOperations; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + + +import java.util.Set; +import java.util.concurrent.*; + +@Component +public class RedisUtil { + + @Resource + private RedisTemplate redisTemplate; + + // 线程池用于处理延迟消息 + private ExecutorService delayMessageExecutor; + + // 延迟消息处理线程数 + private static final int DELAY_THREAD_POOL_SIZE = 4; + + // 延迟队列轮询间隔(毫秒) + private static final long DELAY_QUEUE_POLL_INTERVAL = 1000L; + + @PostConstruct + public void init() { + // 初始化线程池 + delayMessageExecutor = Executors.newFixedThreadPool(DELAY_THREAD_POOL_SIZE); + } + + /** + * 发送消息到队列 + * @param queueName 队列名称 + * @param message 消息内容 + */ + public void sendMessage(String queueName, Object message) { + redisTemplate.opsForList().rightPush(queueName, message); + } + + /** + * 阻塞获取消息(优化版,增加重试机制) + * @param queueName 队列名称 + * @param timeout 超时时间(秒) + * @return 消息内容 + */ + public Object blockingGetMessage(String queueName, long timeout) { + // 分段获取,避免长时间阻塞 + long endTime = System.currentTimeMillis() + timeout * 1000; + while (System.currentTimeMillis() < endTime) { + Object message = redisTemplate.opsForList().leftPop(queueName, 1, TimeUnit.SECONDS); + if (message != null) { + return message; + } + } + return null; + } + + /** + * 非阻塞获取消息 + * @param queueName 队列名称 + * @return 消息内容 + */ + public Object getMessage(String queueName) { + return redisTemplate.opsForList().leftPop(queueName); + } + + /** + * 获取队列长度 + * @param queueName 队列名称 + * @return 队列长度 + */ + public Long getQueueSize(String queueName) { + return redisTemplate.opsForList().size(queueName); + } + + /** + * 发送延迟消息(优化版) + * @param queueName 队列名称 + * @param message 消息内容 + * @param delay 延迟时间(秒) + */ + public void sendDelayMessage(String queueName, Object message, long delay) { + String delayQueueKey = getDelayQueueKey(queueName); + String messageId = generateMessageId(); + + redisTemplate.execute(new RedisCallback() { + @Override + public Object doInRedis(RedisConnection connection) { + connection.openPipeline(); + // 直接存储消息内容到ZSet的value中 + connection.zAdd( + delayQueueKey.getBytes(), + System.currentTimeMillis() + delay * 1000, + serializeMessage(messageId, message) + ); + connection.closePipeline(); + return null; + } + }); + } + + /** + * 启动延迟消息处理任务 + */ + @Scheduled(fixedRate = DELAY_QUEUE_POLL_INTERVAL) + public void processDelayMessages() { + Set delayQueues = redisTemplate.keys("delay:*"); + if (delayQueues != null) { + for (String delayQueue : delayQueues) { + delayMessageExecutor.execute(() -> { + String queueName = delayQueue.substring(6); // 去掉"delay:"前缀 + processSingleDelayQueue(queueName); + }); + } + } + } + + /** + * 处理单个延迟队列 + */ + private void processSingleDelayQueue(String queueName) { + String delayQueueKey = getDelayQueueKey(queueName); + long now = System.currentTimeMillis(); + + // 获取所有已到期的消息 + Set> messages = redisTemplate.opsForZSet() + .rangeByScoreWithScores(delayQueueKey, 0, now); + + if (messages != null && !messages.isEmpty()) { + for (ZSetOperations.TypedTuple tuple : messages) { + Object messageWithId = tuple.getValue(); + if (messageWithId != null) { + // 反序列化消息 + Object message = deserializeMessage(messageWithId.toString()); + // 发送到实际队列 + sendMessage(queueName, message); + // 从延迟队列中移除 + redisTemplate.opsForZSet().remove(delayQueueKey, messageWithId); + } + } + } + } + + // 生成消息ID + private String generateMessageId() { + return java.util.UUID.randomUUID().toString(); + } + + // 获取延迟队列key + private String getDelayQueueKey(String queueName) { + return "delay:" + queueName; + } + + // 序列化消息(可根据实际需求实现) + private byte[] serializeMessage(String messageId, Object message) { + // 这里简单实现,实际项目中可以使用JSON序列化等 + return (messageId + ":" + message.toString()).getBytes(); + } + + // 反序列化消息(可根据实际需求实现) + private Object deserializeMessage(String serialized) { + // 简单实现,根据实际序列化方式调整 + int separatorIndex = serialized.indexOf(':'); + if (separatorIndex > 0) { + return serialized.substring(separatorIndex + 1); + } + return serialized; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/controller/GoldDetailController.java b/src/main/java/com/example/demo/controller/GoldDetailController.java index f01bc53..6f7efce 100644 --- a/src/main/java/com/example/demo/controller/GoldDetailController.java +++ b/src/main/java/com/example/demo/controller/GoldDetailController.java @@ -1,5 +1,6 @@ package com.example.demo.controller; +import com.example.demo.domain.entity.User; import com.example.demo.domain.vo.GoldDetail; import com.example.demo.domain.vo.Page; import com.example.demo.domain.vo.Result; @@ -42,4 +43,18 @@ public class GoldDetailController { public Result getTotal(@RequestBody GoldDetail goldDetail) { return Result.success(goldDetailService.getTotal(goldDetail)); } + @PostMapping("/goldTotal") + public Result GoldTotal(@RequestBody User user) { + return Result.success(goldDetailService.GoldTotal(user)); + } + @PostMapping("/getGold") + public Result getGold(@RequestBody Page page) { + if(ObjectUtils.isEmpty(page.getPageNum())){ + return Result.error("页码数为空!"); + } + if(ObjectUtils.isEmpty(page.getPageSize())){ + return Result.error("页大小为空!"); + } + return Result.success(goldDetailService.getGold(page.getPageNum(), page.getPageSize(), page.getUser())); + } } diff --git a/src/main/java/com/example/demo/domain/entity/Export.java b/src/main/java/com/example/demo/domain/entity/Export.java new file mode 100644 index 0000000..ebc1832 --- /dev/null +++ b/src/main/java/com/example/demo/domain/entity/Export.java @@ -0,0 +1,33 @@ +package com.example.demo.domain.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @program: GOLD + * @ClassName Export + * @description: + * @author: huangqizhen + * @create: 2025−06-24 16:17 + * @Version 1.0 + **/ +@Data +@NoArgsConstructor +public class Export { + private String token; + private Integer account; + private String url; + private String fileName; + private Byte type; + private Byte state; + private Integer dataNum; + private String reason; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") + private Date createTime; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") + private Date updateTime; +} diff --git a/src/main/java/com/example/demo/domain/entity/User.java b/src/main/java/com/example/demo/domain/entity/User.java index 625421e..3014336 100644 --- a/src/main/java/com/example/demo/domain/entity/User.java +++ b/src/main/java/com/example/demo/domain/entity/User.java @@ -27,6 +27,7 @@ public class User implements Serializable { private Integer currentFreeDecember; // 当前十二月免费金币 private Integer currentTaskGold; // 当前任务金币 private Integer rechargeNum; // 充值次数 + private Integer sumConsume; // 消费总额 private Integer consumeNum; // 消费次数 @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai") @@ -37,4 +38,6 @@ public class User implements Serializable { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") private Date updateTime; // 更新时间 + private String sortField; //排序字段 + private String sortOrder; //排序顺序 } \ No newline at end of file diff --git a/src/main/java/com/example/demo/domain/vo/GoldDetail.java b/src/main/java/com/example/demo/domain/vo/GoldDetail.java index d1ee6ca..bf676f7 100644 --- a/src/main/java/com/example/demo/domain/vo/GoldDetail.java +++ b/src/main/java/com/example/demo/domain/vo/GoldDetail.java @@ -33,10 +33,8 @@ public class GoldDetail { private Integer taskGold; // 任务金币 private String adminName; //提交人 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") - @DateTimeFormat(pattern = "yyyy-MM-dd") private Date startTime; // 开始时间 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") - @DateTimeFormat(pattern = "yyyy-MM-dd") private Date endTime; // 结束时间 private String sortField; //排序字段 private String sortOrder; //排序顺序 diff --git a/src/main/java/com/example/demo/domain/vo/Page.java b/src/main/java/com/example/demo/domain/vo/Page.java index 36d7d9d..8ba9fe7 100644 --- a/src/main/java/com/example/demo/domain/vo/Page.java +++ b/src/main/java/com/example/demo/domain/vo/Page.java @@ -1,5 +1,6 @@ package com.example.demo.domain.vo; +import com.example.demo.domain.entity.User; import lombok.Data; import lombok.NoArgsConstructor; @@ -19,5 +20,6 @@ public class Page { private Integer pageNum; private Integer pageSize; private GoldDetail goldDetail; + private User user; } diff --git a/src/main/java/com/example/demo/mapper/GoldDetailMapper.java b/src/main/java/com/example/demo/mapper/GoldDetailMapper.java index faebecb..a6343f2 100644 --- a/src/main/java/com/example/demo/mapper/GoldDetailMapper.java +++ b/src/main/java/com/example/demo/mapper/GoldDetailMapper.java @@ -1,5 +1,6 @@ package com.example.demo.mapper; +import com.example.demo.domain.entity.User; import com.example.demo.domain.vo.GoldDetail; import com.example.demo.domain.vo.Total; import org.apache.ibatis.annotations.Mapper; @@ -18,4 +19,7 @@ import java.util.List; public interface GoldDetailMapper { List getGoldDetail(GoldDetail goldDetail); Total getTotal(GoldDetail goldDetail); + + List getGold(User user); + Total GoldTotal(User user); } diff --git a/src/main/java/com/example/demo/service/GoldDetailService.java b/src/main/java/com/example/demo/service/GoldDetailService.java index 7095f16..2592acc 100644 --- a/src/main/java/com/example/demo/service/GoldDetailService.java +++ b/src/main/java/com/example/demo/service/GoldDetailService.java @@ -1,5 +1,6 @@ package com.example.demo.service; +import com.example.demo.domain.entity.User; import com.example.demo.domain.vo.GoldDetail; import com.example.demo.domain.vo.Total; import com.github.pagehelper.PageInfo; @@ -15,4 +16,7 @@ import com.github.pagehelper.PageInfo; public interface GoldDetailService { PageInfo getGoldDetail(Integer pageNum, Integer pageSize, GoldDetail goldDetail); Total getTotal(GoldDetail goldDetail); + + PageInfo getGold(Integer pageNum, Integer pageSize, User user); + Total GoldTotal(User user); } diff --git a/src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java b/src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java index 96cbd1c..d00420f 100644 --- a/src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java +++ b/src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java @@ -1,5 +1,6 @@ package com.example.demo.serviceImpl; +import com.example.demo.domain.entity.User; import com.example.demo.domain.vo.GoldDetail; import com.example.demo.domain.vo.Total; import com.example.demo.mapper.GoldDetailMapper; @@ -36,4 +37,16 @@ public class GoldDetailServiceImpl implements GoldDetailService { return goldDetailMapper.getTotal(goldDetail); } + + @Override + public PageInfo getGold(Integer pageNum, Integer pageSize, User user) { + PageHelper.startPage(pageNum, pageSize); + List list= goldDetailMapper.getGold(user); + return new PageInfo<>(list); + } + + @Override + public Total GoldTotal(User user) { + return goldDetailMapper.GoldTotal(user); + } } diff --git a/src/main/resources/mapper/GoldDetailMapper.xml b/src/main/resources/mapper/GoldDetailMapper.xml index c0c6acf..02cfb51 100644 --- a/src/main/resources/mapper/GoldDetailMapper.xml +++ b/src/main/resources/mapper/GoldDetailMapper.xml @@ -54,5 +54,41 @@ and ugr.`audit_time` BETWEEN #{startTime} AND #{endTime} + + + +