Browse Source

6.24 客户金币余额,异步部分

huangqizheng/feature-20250626103451-权限页面
huangqizhen 1 week ago
parent
commit
3dcdb9f7b5
  1. 175
      src/main/java/com/example/demo/Util/RedisUtil.java
  2. 15
      src/main/java/com/example/demo/controller/GoldDetailController.java
  3. 33
      src/main/java/com/example/demo/domain/entity/Export.java
  4. 3
      src/main/java/com/example/demo/domain/entity/User.java
  5. 2
      src/main/java/com/example/demo/domain/vo/GoldDetail.java
  6. 2
      src/main/java/com/example/demo/domain/vo/Page.java
  7. 4
      src/main/java/com/example/demo/mapper/GoldDetailMapper.java
  8. 4
      src/main/java/com/example/demo/service/GoldDetailService.java
  9. 13
      src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java
  10. 36
      src/main/resources/mapper/GoldDetailMapper.xml

175
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<String, Object> 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<Object>() {
@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<String> 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<ZSetOperations.TypedTuple<Object>> messages = redisTemplate.opsForZSet()
.rangeByScoreWithScores(delayQueueKey, 0, now);
if (messages != null && !messages.isEmpty()) {
for (ZSetOperations.TypedTuple<Object> 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;
}
}

15
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()));
}
}

33
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: 202506-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;
}

3
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; //排序顺序
}

2
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; //排序顺序

2
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;
}

4
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<GoldDetail> getGoldDetail(GoldDetail goldDetail);
Total getTotal(GoldDetail goldDetail);
List<User> getGold(User user);
Total GoldTotal(User user);
}

4
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<GoldDetail> getGoldDetail(Integer pageNum, Integer pageSize, GoldDetail goldDetail);
Total getTotal(GoldDetail goldDetail);
PageInfo<User> getGold(Integer pageNum, Integer pageSize, User user);
Total GoldTotal(User user);
}

13
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<User> getGold(Integer pageNum, Integer pageSize, User user) {
PageHelper.startPage(pageNum, pageSize);
List<User> list= goldDetailMapper.getGold(user);
return new PageInfo<>(list);
}
@Override
public Total GoldTotal(User user) {
return goldDetailMapper.GoldTotal(user);
}
}

36
src/main/resources/mapper/GoldDetailMapper.xml

@ -54,5 +54,41 @@
and ugr.`audit_time` BETWEEN #{startTime} AND #{endTime}
</if>
</where>
</select>
<select id="getGold" resultType="com.example.demo.domain.entity.User">
select * from user
<where>
<if test="jwcode != null and jwcode.length > 0">
and jwcode = #{jwcode}
</if>
<if test="market != null and market.length > 0">
and market = #{market}
</if>
</where>
<choose>
<when test="sortField != null and sortField.length > 0 or sortOrder != null and sortOrder.length > 0">
ORDER BY ${sortField} ${sortOrder}
</when>
<otherwise>
ORDER BY create_time DESC
</otherwise>
</choose>
</select>
<select id="GoldTotal" resultType="com.example.demo.domain.vo.Total">
select
sum(current_permanent_gold) as permanentGold,
sum(current_free_june + current_free_december) as freeGold,
sum(current_task_gold) as taskGold,
sum(current_permanent_gold) + sum(current_free_june + current_free_december) + sum(current_task_gold) as Goldtotal
from `user`
<where>
<if test="jwcode != null and jwcode.length > 0">
and jwcode = #{jwcode}
</if>
<if test="market != null and market.length > 0">
and market = #{market}
</if>
</where>
</select>
</mapper>
Loading…
Cancel
Save