From 5eb479d572c0fe6aabbfe8c3f75a2457d1cd80af Mon Sep 17 00:00:00 2001 From: wangguorui <2069821375@qq.com> Date: Thu, 29 Jan 2026 10:48:47 +0800 Subject: [PATCH] =?UTF-8?q?1=E6=9C=8829=E6=97=A5=EF=BC=8C=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E6=8E=A8=E9=80=81=E9=87=91=E5=B8=81=E6=94=B6=E6=AC=BE?= =?UTF-8?q?=E9=80=80=E6=AC=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/demo/RabbitMQ/CoinRechargeAspect.java | 96 +++++++++++++++++++++ .../demo/RabbitMQ/CoinRechargeConsumer.java | 31 +++++++ .../example/demo/RabbitMQ/CoinRefundAspect.java | 97 ++++++++++++++++++++++ .../example/demo/RabbitMQ/CoinRefundConsumer.java | 31 +++++++ .../com/example/demo/config/RabbitMQConfig.java | 39 +++++++++ .../com/example/demo/domain/vo/coin/Messages.java | 2 +- .../demo/serviceImpl/coin/RechargeServiceImpl.java | 23 ++++- .../demo/serviceImpl/coin/RefundServiceImpl.java | 24 +++++- 8 files changed, 340 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/example/demo/RabbitMQ/CoinRechargeAspect.java create mode 100644 src/main/java/com/example/demo/RabbitMQ/CoinRechargeConsumer.java create mode 100644 src/main/java/com/example/demo/RabbitMQ/CoinRefundAspect.java create mode 100644 src/main/java/com/example/demo/RabbitMQ/CoinRefundConsumer.java diff --git a/src/main/java/com/example/demo/RabbitMQ/CoinRechargeAspect.java b/src/main/java/com/example/demo/RabbitMQ/CoinRechargeAspect.java new file mode 100644 index 0000000..897aaf3 --- /dev/null +++ b/src/main/java/com/example/demo/RabbitMQ/CoinRechargeAspect.java @@ -0,0 +1,96 @@ +package com.example.demo.RabbitMQ; + +import com.example.demo.Util.SecurityUtils; +import com.example.demo.config.RabbitMQConfig; +import com.example.demo.config.interfac.Message; +import com.example.demo.domain.vo.coin.Messages; +import com.example.demo.mapper.coin.OperationLogMapper; +import com.example.demo.mapper.coin.UserMapper; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @program: GOLD + * @ClassName CoinRechargeAspect + * @description: 金币充值流程切面 + * @author: + * @create: + * @Version 1.0 + **/ +@Aspect +@Component +@Slf4j +public class CoinRechargeAspect { + @Autowired + private RabbitTemplate rabbitTemplate; + @Autowired + private UserMapper userMapper; + @Autowired + private OperationLogMapper operationLogMapper; + + @Around("@annotation(com.example.demo.config.interfac.Message)") + public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { + long startTime = System.currentTimeMillis(); + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + String methodName = signature.getName(); + String className = signature.getDeclaringTypeName(); + Object[] args = joinPoint.getArgs(); + + Message logAnnotation = signature.getMethod().getAnnotation(Message.class); + String action = logAnnotation.value(); + + // ✅ 使用 Spring Security 获取真实用户 + String username = SecurityUtils.getCurrentUsername(); + Integer userId = SecurityUtils.getCurrentUserId(); + String name = userMapper.selectUserByJwcode(Integer.valueOf(username)).getName(); + + // 添加空值检查 + if (userId == null) { + log.warn("无法获取当前用户ID,使用默认值 -1"); + userId = -1; // 或者使用其他默认值 + } + + ObjectMapper mapper = new ObjectMapper(); + String argsJson = "[]"; + try { + argsJson = mapper.writeValueAsString(args); + } catch (Exception e) { + argsJson = "serialize failed"; + } + + Object result; + try { + result = joinPoint.proceed(); + } catch (Exception e) { + log.error("方法执行异常: {}", e.getMessage()); + throw e; + } + + long duration = System.currentTimeMillis() - startTime; + + // ✅ 构造金币充值消息 DTO + Messages messageDTO = new Messages(); + messageDTO.setJwcode(Integer.valueOf(username)); + messageDTO.setName(name); + messageDTO.setTitle(action); + messageDTO.setDesc(username + "有一条金币充值消息需要处理"); + + // ✅ 发送消息到 RabbitMQ(不等待) + try { + rabbitTemplate.convertAndSend(RabbitMQConfig.COIN_RECHARGE_EXCHANGE, "coin.recharge.save", messageDTO); + log.info("📩 金币充值消息已发送到 RabbitMQ: {}", action); + } catch (Exception e) { + log.error("发送金币充值消息到 RabbitMQ 失败", e); + } + + log.info("✅ AOP 拦截完成: {} 执行 [{}] 耗时 {}ms", username, action, duration); + return result; + } +} diff --git a/src/main/java/com/example/demo/RabbitMQ/CoinRechargeConsumer.java b/src/main/java/com/example/demo/RabbitMQ/CoinRechargeConsumer.java new file mode 100644 index 0000000..eeac0a7 --- /dev/null +++ b/src/main/java/com/example/demo/RabbitMQ/CoinRechargeConsumer.java @@ -0,0 +1,31 @@ +package com.example.demo.RabbitMQ; + +import com.example.demo.config.RabbitMQConfig; +import com.example.demo.domain.vo.coin.Messages; +import com.example.demo.mapper.coin.OperationLogMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 金币充值流程消息消费者 + * 监听金币充值流程中各个状态变更的消息队列 + */ +@Component +@Slf4j +public class CoinRechargeConsumer { + @Autowired + private OperationLogMapper operationLogMapper; + + @RabbitListener(queues = RabbitMQConfig.COIN_RECHARGE_QUEUE) + public void consumeLog(Messages messages) { + try { + operationLogMapper.insertMessage(messages); + + } catch (Exception e) { + log.error("持久化金币充值日志失败", e); + // 可以重试或记录到文件 + } + } +} diff --git a/src/main/java/com/example/demo/RabbitMQ/CoinRefundAspect.java b/src/main/java/com/example/demo/RabbitMQ/CoinRefundAspect.java new file mode 100644 index 0000000..7fdcd14 --- /dev/null +++ b/src/main/java/com/example/demo/RabbitMQ/CoinRefundAspect.java @@ -0,0 +1,97 @@ +package com.example.demo.RabbitMQ; + +import com.example.demo.Util.SecurityUtils; +import com.example.demo.config.RabbitMQConfig; +import com.example.demo.config.interfac.Message; +import com.example.demo.domain.DTO.MessageDTO; +import com.example.demo.domain.vo.coin.Messages; +import com.example.demo.mapper.coin.OperationLogMapper; +import com.example.demo.mapper.coin.UserMapper; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @program: GOLD + * @ClassName CoinRefundAspect + * @description: 金币退款流程切面 + * @author: wangguorui + * @create: + * @Version 1.0 + **/ +@Aspect +@Component +@Slf4j +public class CoinRefundAspect { + @Autowired + private RabbitTemplate rabbitTemplate; + @Autowired + private UserMapper userMapper; + @Autowired + private OperationLogMapper operationLogMapper; + + @Around("@annotation(com.example.demo.config.interfac.Message)") + public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { + long startTime = System.currentTimeMillis(); + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + String methodName = signature.getName(); + String className = signature.getDeclaringTypeName(); + Object[] args = joinPoint.getArgs(); + + Message logAnnotation = signature.getMethod().getAnnotation(Message.class); + String action = logAnnotation.value(); + + // ✅ 使用 Spring Security 获取真实用户 + String username = SecurityUtils.getCurrentUsername(); + Integer userId = SecurityUtils.getCurrentUserId(); + String name = userMapper.selectUserByJwcode(Integer.valueOf(username)).getName(); + + // 添加空值检查 + if (userId == null) { + log.warn("无法获取当前用户ID,使用默认值 -1"); + userId = -1; // 或者使用其他默认值 + } + + ObjectMapper mapper = new ObjectMapper(); + String argsJson = "[]"; + try { + argsJson = mapper.writeValueAsString(args); + } catch (Exception e) { + argsJson = "serialize failed"; + } + + Object result; + try { + result = joinPoint.proceed(); + } catch (Exception e) { + log.error("方法执行异常: {}", e.getMessage()); + throw e; + } + + long duration = System.currentTimeMillis() - startTime; + + // ✅ 构造金币退款消息 DTO + Messages messageDTO = new Messages(); + messageDTO.setJwcode(Integer.valueOf(username)); + messageDTO.setName(name); + messageDTO.setTitle(action); + messageDTO.setDesc(username + "有一条金币退款消息需要处理"); + + // ✅ 发送消息到 RabbitMQ(不等待) + try { + rabbitTemplate.convertAndSend(RabbitMQConfig.COIN_REFUND_EXCHANGE, "coin.refund.save", messageDTO); + log.info("📩 金币退款消息已发送到 RabbitMQ: {}", action); + } catch (Exception e) { + log.error("发送金币退款消息到 RabbitMQ 失败", e); + } + + log.info("✅ AOP 拦截完成: {} 执行 [{}] 耗时 {}ms", username, action, duration); + return result; + } +} diff --git a/src/main/java/com/example/demo/RabbitMQ/CoinRefundConsumer.java b/src/main/java/com/example/demo/RabbitMQ/CoinRefundConsumer.java new file mode 100644 index 0000000..2ea520c --- /dev/null +++ b/src/main/java/com/example/demo/RabbitMQ/CoinRefundConsumer.java @@ -0,0 +1,31 @@ +package com.example.demo.RabbitMQ; + +import com.example.demo.config.RabbitMQConfig; +import com.example.demo.domain.vo.coin.Messages; +import com.example.demo.mapper.coin.OperationLogMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 金币退款流程消息消费者 + * 监听金币退款流程中各个状态变更的消息队列 + */ +@Component +@Slf4j +public class CoinRefundConsumer { + @Autowired + private OperationLogMapper operationLogMapper; + + @RabbitListener(queues = RabbitMQConfig.COIN_REFUND_QUEUE) + public void consumeLog(Messages messages) { + try { + operationLogMapper.insertMessage(messages); + + } catch (Exception e) { + log.error("持久化金币退款日志失败", e); + // 可以重试或记录到文件 + } + } +} diff --git a/src/main/java/com/example/demo/config/RabbitMQConfig.java b/src/main/java/com/example/demo/config/RabbitMQConfig.java index ffa9c72..71d58c2 100644 --- a/src/main/java/com/example/demo/config/RabbitMQConfig.java +++ b/src/main/java/com/example/demo/config/RabbitMQConfig.java @@ -21,6 +21,10 @@ public class RabbitMQConfig { public static final String CASH_COLLECTION_EXCHANGE = "cash_collection_exchange"; public static final String CASH_REFUND_QUEUE = "cash_collection_exchange"; public static final String CASH_REFUND_EXCHANGE = "cash_refund_exchange"; + public static final String COIN_REFUND_QUEUE = "coin_refund_queue"; + public static final String COIN_REFUND_EXCHANGE = "coin_refund_exchange"; + public static final String COIN_RECHARGE_QUEUE = "coin_recharge_queue"; + public static final String COIN_RECHARGE_EXCHANGE = "coin_recharge_exchange"; @Bean public Queue logQueue() { return new Queue(LOG_QUEUE, true); @@ -74,6 +78,41 @@ public class RabbitMQConfig { .with("cash.refund.*"); } + // 金币退款队列和绑定(按照操作日志的标准) + @Bean + public Queue coinRefundQueue() { + return new Queue(COIN_REFUND_QUEUE, true); + } + + @Bean + public TopicExchange coinRefundExchange() { + return new TopicExchange(COIN_REFUND_EXCHANGE); + } + + @Bean + public Binding coinRefundBinding() { + return BindingBuilder.bind(coinRefundQueue()) + .to(coinRefundExchange()) + .with("coin.refund.*"); + } + + // 金币充值队列和绑定(按照操作日志的标准) + @Bean + public Queue coinRechargeQueue() { + return new Queue(COIN_RECHARGE_QUEUE, true); + } + + @Bean + public TopicExchange coinRechargeExchange() { + return new TopicExchange(COIN_RECHARGE_EXCHANGE); + } + + @Bean + public Binding coinRechargeBinding() { + return BindingBuilder.bind(coinRechargeQueue()) + .to(coinRechargeExchange()) + .with("coin.recharge.*"); + } @Bean public MessageConverter messageConverter() { diff --git a/src/main/java/com/example/demo/domain/vo/coin/Messages.java b/src/main/java/com/example/demo/domain/vo/coin/Messages.java index ae4942e..b53ccda 100644 --- a/src/main/java/com/example/demo/domain/vo/coin/Messages.java +++ b/src/main/java/com/example/demo/domain/vo/coin/Messages.java @@ -33,6 +33,6 @@ public class Messages { private Integer market; private Integer flag; private String marketName; - + private Integer menuId; } diff --git a/src/main/java/com/example/demo/serviceImpl/coin/RechargeServiceImpl.java b/src/main/java/com/example/demo/serviceImpl/coin/RechargeServiceImpl.java index 8b88792..9e43a57 100644 --- a/src/main/java/com/example/demo/serviceImpl/coin/RechargeServiceImpl.java +++ b/src/main/java/com/example/demo/serviceImpl/coin/RechargeServiceImpl.java @@ -1,6 +1,7 @@ package com.example.demo.serviceImpl.coin; import com.example.demo.Util.SimpleIdGenerator; +import com.example.demo.config.RabbitMQConfig; import com.example.demo.domain.entity.UserGoldRecord; import com.example.demo.domain.vo.bean.BeanUserCard; import com.example.demo.mapper.bean.BeanUserMapper; @@ -11,6 +12,7 @@ import com.example.demo.service.coin.MarketService; import com.example.demo.service.coin.RechargeService; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; +import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.example.demo.domain.vo.coin.*; @@ -48,7 +50,8 @@ public class RechargeServiceImpl implements RechargeService { @Autowired private BeanUserMapper beanUserMapper; - + @Autowired + private RabbitTemplate rabbitTemplate; //查询所有充值 @Override @@ -148,6 +151,24 @@ public class RechargeServiceImpl implements RechargeService { userGoldRecord.setLinkId(SimpleIdGenerator.generateId()); userGoldRecord.setPrice(rechargeUser.getPermanentGold()); rechargeMapper.add(userGoldRecord); + + // 发送金币充值创建消息 + Messages message = new Messages(); + message.setJwcode(rechargeUser.getJwcode()); + message.setName(goldUser.getName()); + message.setStatus(10); + message.setDesc(rechargeUser.getJwcode() + "的金币充值收款申请待审核,前往处理"); + message.setTitle("金币管理--金币审核--充值审核"); + message.setType(0); + message.setTypeId(userGoldRecord.getId()); + message.setMarket(Integer.valueOf(goldUser.getMarket())); + String marketName = marketMapper.getMarketNameById(String.valueOf(message.getMarket())); + message.setMarketName(marketName); + message.setMenuId(6); + + // 发送到RabbitMQ + rabbitTemplate.convertAndSend(RabbitMQConfig.COIN_RECHARGE_EXCHANGE, "coin.recharge.save", message); + return Result.success("CZ_" + orderNumber); } //根据订单单号获取订单信息(重复充值/消费提示) diff --git a/src/main/java/com/example/demo/serviceImpl/coin/RefundServiceImpl.java b/src/main/java/com/example/demo/serviceImpl/coin/RefundServiceImpl.java index 3f8c919..58f64d3 100644 --- a/src/main/java/com/example/demo/serviceImpl/coin/RefundServiceImpl.java +++ b/src/main/java/com/example/demo/serviceImpl/coin/RefundServiceImpl.java @@ -1,5 +1,6 @@ package com.example.demo.serviceImpl.coin; +import com.example.demo.config.RabbitMQConfig; import com.example.demo.domain.entity.UserGoldRecord; import com.example.demo.mapper.coin.*; import com.example.demo.service.coin.MarketService; @@ -7,6 +8,7 @@ import com.example.demo.service.coin.RefundService; import com.example.demo.Util.LanguageTranslationUtil; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; +import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -47,10 +49,12 @@ public class RefundServiceImpl implements RefundService { @Autowired private RechargeMapper rechargeMapper; - // 注入多语言工具类 @Autowired private LanguageTranslationUtil languageTranslationUtil; + @Autowired + private RabbitTemplate rabbitTemplate; + //查找全部退款 @Override public PageInfo selectAll(Integer pageNum, Integer pageSize, RefundUser refundUser) throws Exception { @@ -222,6 +226,24 @@ public class RefundServiceImpl implements RefundService { } refundMapper.add(userGoldRecord); consumeMapper.updateIsRefund(orderCode); + + // 发送金币退款创建消息 + Messages message = new Messages(); + message.setJwcode(refundUser.getJwcode()); + message.setName(goldUser.getName()); + message.setStatus(10); + message.setDesc(refundUser.getJwcode() + "的金币退款申请待审核,前往确认"); + message.setTitle("金币管理--金币审核--退款审核"); + message.setType(1); + message.setTypeId(userGoldRecord.getId()); + message.setMarket(Integer.valueOf(goldUser.getMarket())); + String marketName = marketMapper.getMarketNameById(String.valueOf(message.getMarket())); + message.setMarketName(marketName); + message.setMenuId(13); + + // 发送到RabbitMQ + rabbitTemplate.convertAndSend(RabbitMQConfig.COIN_REFUND_EXCHANGE, "coin.refund.save", message); + String successMsg = languageTranslationUtil.translate("操作成功", lang); return Result.success(successMsg); }