From e56cb9744f377b85c006eb1070940f500f9e2555 Mon Sep 17 00:00:00 2001 From: huangqizhen <15552608129@163.com> Date: Mon, 30 Jun 2025 15:56:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E8=B7=91=EF=BC=88=E4=B8=8D=E5=90=88?= =?UTF-8?q?=E5=B9=B6=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/controller/GoldDetailController.java | 4 +- .../example/demo/exception/SystemException.java | 13 ++++ .../com/example/demo/mapper/GoldDetailMapper.java | 3 +- .../service/listen/AiEmotionExportListener.java | 84 ++++++++++++++++++++++ .../service/queue/AbstractMessageListener.java | 69 ++++++++++++++++++ .../demo/serviceImpl/GoldDetailServiceImpl.java | 10 ++- src/main/resources/mapper/GoldDetailMapper.xml | 5 +- 7 files changed, 180 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/example/demo/exception/SystemException.java create mode 100644 src/main/java/com/example/demo/service/listen/AiEmotionExportListener.java create mode 100644 src/main/java/com/example/demo/service/queue/AbstractMessageListener.java diff --git a/src/main/java/com/example/demo/controller/GoldDetailController.java b/src/main/java/com/example/demo/controller/GoldDetailController.java index 41ba378..e188e13 100644 --- a/src/main/java/com/example/demo/controller/GoldDetailController.java +++ b/src/main/java/com/example/demo/controller/GoldDetailController.java @@ -72,7 +72,7 @@ public class GoldDetailController { } return Result.success(goldDetailService.getGold(page.getPageNum(), page.getPageSize(), page.getUser())); } - @PostMapping("export") + @PostMapping("/export") public Result export(@Valid @RequestBody GoldDetailDTO dto) { String lockKey = "export:lock:" + dto.getToken(); // 锁的 Key(可按用户/业务区分) String requestId = UUID.randomUUID().toString(); // 请求 ID(防止误删锁) @@ -83,7 +83,7 @@ public class GoldDetailController { throw new BusinessException("操作太频繁,请稍后重试"); } // 执行业务逻辑 - return GoldDetailService.addExportRecord(dto); + return goldDetailService.addExportRecord(dto); } finally { // 释放锁 redisLockUtil.unlock(lockKey, requestId); diff --git a/src/main/java/com/example/demo/exception/SystemException.java b/src/main/java/com/example/demo/exception/SystemException.java new file mode 100644 index 0000000..5a049f1 --- /dev/null +++ b/src/main/java/com/example/demo/exception/SystemException.java @@ -0,0 +1,13 @@ +package com.example.demo.exception; + +public class SystemException extends RuntimeException { + public SystemException(String message) { + super(message); + } + + + public SystemException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/src/main/java/com/example/demo/mapper/GoldDetailMapper.java b/src/main/java/com/example/demo/mapper/GoldDetailMapper.java index eaf1ee7..0bbaf61 100644 --- a/src/main/java/com/example/demo/mapper/GoldDetailMapper.java +++ b/src/main/java/com/example/demo/mapper/GoldDetailMapper.java @@ -3,6 +3,7 @@ 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 lombok.Data; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -22,6 +23,7 @@ public interface GoldDetailMapper { Total getTotal(GoldDetail goldDetail); List getGold(User user); Total GoldTotal(User user); + @Data public static class ExportRecordIdHolder{ private Long id; } @@ -34,5 +36,4 @@ public interface GoldDetailMapper { @Param("fileName") String fileName, @Param("dataNum") Integer dataNum ); - ); } diff --git a/src/main/java/com/example/demo/service/listen/AiEmotionExportListener.java b/src/main/java/com/example/demo/service/listen/AiEmotionExportListener.java new file mode 100644 index 0000000..c2b3903 --- /dev/null +++ b/src/main/java/com/example/demo/service/listen/AiEmotionExportListener.java @@ -0,0 +1,84 @@ +package com.example.demo.service.listen; + +import cn.hutool.core.util.StrUtil; + + +import com.example.demo.Util.ExecutionContextUtil; +import com.example.demo.Util.FeiShuAlertUtil; +import com.example.demo.Util.RedisUtil; +import com.example.demo.domain.vo.ExecutionContext; +import com.example.demo.service.ExportExcelService; +import com.example.demo.service.queue.AbstractMessageListener; + + + + + + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import static java.lang.Thread.sleep; + + +@Component +public class AiEmotionExportListener extends AbstractMessageListener { + + + //注入ExportExcelService + @Autowired + private ExportExcelService exportExcelService; + + @Autowired + public AiEmotionExportListener( + RedisUtil redisQueueUtil + + ) { + super(redisQueueUtil, "hwgold:queue:export_queue"); + System.out.println("监听器已启动,队列: "); + } + + @Override + protected void handleMessage(String message) { + if (StrUtil.isBlank(message)) { + System.err.println("redis消息队列数据为空" + message); + } + try { + Thread.sleep(5000); + exportExcelService.handleExcelExportData(message); + } catch (Exception e) { + logError(e, message); + throw new RuntimeException("Failed to process AI emotion export: " + e.getMessage(), e); + } + + + } + + private void logError(Exception e, String message) { + System.err.println("Export data listener exception: " + e.getMessage()); + e.printStackTrace(); + try { + ExecutionContext context = ExecutionContextUtil.getExecutionContext(); + String cause = ""; + if (e.getCause() != null) { + cause = e.getCause().getMessage(); + } + FeiShuAlertUtil.sendAlertMessage( + context, + e.getStackTrace()[0].getFileName(), + e.getStackTrace()[0].getLineNumber(), + "AI Emotion Export Error: " + e.getMessage() + " 底层错误: " + cause , + "Failed message: " + message + ); + } catch (Exception alertEx) { + System.err.println("Failed to send Feishu alert: " + alertEx.getMessage()); + } + } + + @Override + protected void handleError(Exception e, String message) { + System.err.println("处理消息失败: " + message); + e.printStackTrace(); + } + +} diff --git a/src/main/java/com/example/demo/service/queue/AbstractMessageListener.java b/src/main/java/com/example/demo/service/queue/AbstractMessageListener.java new file mode 100644 index 0000000..db165db --- /dev/null +++ b/src/main/java/com/example/demo/service/queue/AbstractMessageListener.java @@ -0,0 +1,69 @@ +package com.example.demo.service.queue; + + + +import com.example.demo.Util.RedisUtil; +import jakarta.annotation.PostConstruct; + + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * 抽象消息监听器 + */ +public abstract class AbstractMessageListener { + + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + protected final RedisUtil redisQueueUtil; + protected final String queueName; + + public AbstractMessageListener(RedisUtil redisQueueUtil, String queueName) { + this.redisQueueUtil = redisQueueUtil; + this.queueName = queueName; + } + + @PostConstruct + public void init() { + executorService.submit(this::listen); + } + + private void listen() { + System.out.println("消费者消费数据" + queueName + ""); + while (!Thread.currentThread().isInterrupted()) { + try { + Object message = redisQueueUtil.blockingGetMessage(queueName, 1); + if (message != null) { + try { + handleMessage((T) message); + } catch (Exception e) { + handleError(e, (T) message); + } + } + } catch (Exception e) { + System.err.println("监听队列异常: " + e.getMessage()); + try { + Thread.sleep(5000); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + } + } + + /** + * 处理消息 + * @param message 消息内容 + */ + protected abstract void handleMessage(T message); + + /** + * 处理错误 + * @param e 异常 + * @param message 消息内容 + */ + protected void handleError(Exception e, T message) { + System.err.println("处理消息异常: " + e.getMessage()); + } + +} diff --git a/src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java b/src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java index 98bcb28..7d0dbcf 100644 --- a/src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java +++ b/src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java @@ -1,10 +1,12 @@ package com.example.demo.serviceImpl; +import com.example.demo.Util.RedisUtil; import com.example.demo.domain.DTO.GoldDetailDTO; import com.example.demo.domain.entity.User; import com.example.demo.domain.vo.GoldDetail; import com.example.demo.domain.vo.Result; import com.example.demo.domain.vo.Total; +import com.example.demo.exception.SystemException; import com.example.demo.mapper.GoldDetailMapper; import com.example.demo.service.GoldDetailService; import com.fasterxml.jackson.databind.ObjectMapper; @@ -33,6 +35,8 @@ public class GoldDetailServiceImpl implements GoldDetailService { @Autowired private GoldDetailMapper goldDetailMapper; + @Autowired + private RedisUtil redisUtil; @Override public PageInfo getGoldDetail(Integer pageNum, Integer pageSize, GoldDetail goldDetail) { @@ -76,7 +80,7 @@ public class GoldDetailServiceImpl implements GoldDetailService { dto.setDataNum(0); try{ // 调用方式 - GoldDetailMapper.ExportRecordIdHolder idHolder = new AiEmotionMapper.ExportRecordIdHolder(); + GoldDetailMapper.ExportRecordIdHolder idHolder = new GoldDetailMapper.ExportRecordIdHolder(); goldDetailMapper.insertExportRecord( idHolder, // 用于接收主键 dto.getJwcode(), @@ -111,6 +115,6 @@ public class GoldDetailServiceImpl implements GoldDetailService { } } - } -} + + diff --git a/src/main/resources/mapper/GoldDetailMapper.xml b/src/main/resources/mapper/GoldDetailMapper.xml index 8e0c357..10d027b 100644 --- a/src/main/resources/mapper/GoldDetailMapper.xml +++ b/src/main/resources/mapper/GoldDetailMapper.xml @@ -1,8 +1,9 @@ - - insert into + + insert into excprt (jwcode,type,state,url,file_name,data_num) + values(#{jwcode},#{type},#{state},#{url},#{fileName},#{dataNum})