以下是一个基于 EasyPOI + RocketMQ + 多线程组合方案实现凭证 Excel 文件数据量平滑导入处理的示例代码:
一、引入依赖
在项目的pom.xml文件中添加以下依赖:
xml
复制
二、创建凭证实体类
java
复制
import lombok.Data;
@Data
public class Voucher {
private String field1;
private String field2;
// 其他凭证字段
}
三、创建 Excel 导入工具类
java
复制
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.List;
@Slf4j
public class ExcelImportUtilWrapper {
public static List<Voucher> importVouchersFromExcel(MultipartFile file) {
try (InputStream inputStream = file.getInputStream()) {
ImportParams params = new ImportParams();
// 可以根据实际情况配置导入参数
return ExcelImportUtil.importExcel(inputStream, Voucher.class, params);
} catch (Exception e) {
log.error("导入 Excel 出错", e);
return null;
}
}
}
四、创建 RocketMQ 生产者类
java
复制
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.List;
@Slf4j
@Component
public class RocketMQProducer {
private final String producerGroup = "voucherProducerGroup";
private final String topic = "voucherTopic";
public void sendVouchersToQueue(List<Voucher> vouchers) {
DefaultMQProducer producer = new DefaultMQProducer(producerGroup);
producer.setNamesrvAddr("localhost:9876");
try {
producer.start();
for (Voucher voucher : vouchers) {
Message message = new Message(topic, voucher.toString().getBytes(StandardCharsets.UTF_8));
producer.send(message);
}
} catch (Exception e) {
log.error("发送消息到 RocketMQ 出错", e);
} finally {
producer.shutdown();
}
}
}
五、创建 RocketMQ 消费者类
java
复制
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j
@Component
public class RocketMQConsumer {
private final String consumerGroup = "voucherConsumerGroup";
private final String topic = "voucherTopic";
public void consumeVouchers() {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerGroup);
consumer.setNamesrvAddr("localhost:9876");
try {
consumer.subscribe(topic, "*");
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
ExecutorService executorService = Executors.newFixedThreadPool(10);
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msg : msgs) {
String voucherStr = new String(msg.getBody(), StandardCharsets.UTF_8);
executorService.submit(() -> processVoucher(voucherStr));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
consumer.start();
} catch (Exception e) {
log.error("消费 RocketMQ 消息出错", e);
}
}
private void processVoucher(String voucherStr) {
// 这里将凭证字符串转换为凭证对象并进行入库操作
Voucher voucher = convertToVoucher(voucherStr);
// 假设这里是入库逻辑
log.info("入库凭证:{}", voucher);
}
private Voucher convertToVoucher(String voucherStr) {
// 根据字符串内容解析出凭证对象
// 这里可以使用 JSON 解析或者自定义的解析方式
return null;
}
}
六、创建控制器类用于接收 Excel 文件并触发导入流程
java
复制
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@Slf4j
@RestController
public class VoucherImportController {
@Autowired
private ExcelImportUtilWrapper excelImportUtilWrapper;
@Autowired
private RocketMQProducer rocketMQProducer;
@PostMapping("/importVouchers")
public ResponseEntity<Void> importVouchers(@RequestParam("file") MultipartFile file) {
List<Voucher> vouchers = excelImportUtilWrapper.importVouchersFromExcel(file);
if (vouchers!= null) {
rocketMQProducer.sendVouchersToQueue(vouchers);
return new ResponseEntity<>(HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
请注意,上述代码仅为示例,实际应用中你需要根据实际情况调整 RocketMQ 的配置、数据库连接和入库逻辑等。同时,可以根据实际性能需求调整线程池大小等参数。