EasyExcel多线程批量导出数据,动态表头,静态资源访问
1.导入依赖
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version></dependency>
2.建立实体
@Data
public class ActResultLogVO implements Serializable {private static final long serialVersionUID = 1L;@ExcelProperty(value = "onlineseqid",index = 0)private String onlineseqid;@ExcelProperty(value = "businessid",index = 1)private String businessid;@ExcelProperty(value = "becifno",index = 2)private String becifno;@ExcelProperty(value = "ivisresult",index = 3)private String ivisresult;@ExcelProperty(value = "createdby",index = 4)private String createdby;@ExcelProperty(value = "createddate",index = 5)private LocalDate createddate;@ExcelProperty(value = "updateby",index = 6)private String updateby;@ExcelProperty(value = "updateddate",index = 7)private LocalDate updateddate;@ExcelProperty(value = "risklevel",index = 8)private String risklevel;/*** 分页开始数量*/private Integer start;/*** 分页 size*/private Integer size;
}
3.多线程异步导出
@Async@Transactionalpublic void exportExcel(String filePath) {//filePath 文件路径ExcelWriter writer = EasyExcel.write(filePath, ActResultLogVO.class).build();// 根据数据读写速度来调整,一般来说读的逻辑复杂,比较慢,如果读比写快,这里设为1int N = 2;// 大小设置为2就可以,作为缓冲BlockingQueue<List<ActResultLogVO>> queue = new ArrayBlockingQueue<>(2);AtomicInteger start = new AtomicInteger(0);AtomicInteger num = new AtomicInteger(0);AtomicInteger sheet = new AtomicInteger(1);// 分页大小可以适当调整int pageSize = 100000;//开启多个线程分页查数据for (int i = 0; i < N; i++) {executorService.submit(() -> {while (true) {//自增int startNum= start.getAndAdd(pageSize);try {long l = System.currentTimeMillis();logger.info("[多线程,分页查询] 线程:{},开始执行查询:startNum :{},时间:{}",Thread.currentThread().getName(),startNum,l);List<ActResultLogVO> list = selectActResultLogVOPage(startNum, pageSize);logger.info("[多线程,分页查询] 线程:{},执行查询完成 startNum :{} 用时:{}",Thread.currentThread().getName(),startNum,System.currentTimeMillis()-l);if (CollectionUtils.isEmpty(list)) {//读到没数据也要放入空集合queue.put(Collections.EMPTY_LIST);break;}queue.put(list);} catch (Exception e) {//异常情况也要放入空集合,防止写线程无法退出循环try {queue.put(Collections.EMPTY_LIST);} catch (InterruptedException ex) {throw new RuntimeException(ex);}throw new RuntimeException(e);}}});}Future<?> submit = executorService.submit(() -> {int count = 0;while (true) {List<ActResultLogVO> list = null;try {list = queue.take();} catch (InterruptedException e) {Thread.interrupted();}if (CollectionUtils.isEmpty(list)) {count++;// 当获取到两次空集合时,说明已经读完if (count == N) {break;}continue;}if(num.get()>=500000){sheet.getAndAdd(1);num.getAndSet(0);}num.getAndAdd(list.size());long l = System.currentTimeMillis();logger.info("[多线程,写入Excel] 线程:{},开始执行写入:sheet :{},num:{}时间:{}",Thread.currentThread().getName(),sheet.get(),num.get(),l);writer.write(list, EasyExcel.writerSheet("Sheet"+sheet).build());logger.info("[多线程,写入Excel] 线程:{},开始执行写入结束:sheet :{},num:{},时间:{}",Thread.currentThread().getName(),sheet.get(),num.get(),System.currentTimeMillis()-l);}writer.finish();});try {// 阻塞等待完成,异步处理也可以去掉这段代码submit.get();} catch (Exception e) {}}
4.动态表头
@Autowired@Qualifier("excelThreadPool")private ExecutorService executorService;@Async@Transactionalpublic void exportExcel(String filePath,LinkedHashMap<String, DynamicExcelData> nameMap) {// 指定写入的文件ExcelWriter writer = EasyExcel.write(filePath).head(ExcelUtils.getHead(nameMap)).build();// 根据数据读写速度来调整,一般来说读的逻辑复杂,比较慢,如果读比写快,这里设为1int N = 2;// 大小设置为2就可以,作为缓冲BlockingQueue<List<Map<String,Object>>> queue = new ArrayBlockingQueue<>(2);AtomicInteger num = new AtomicInteger(0);AtomicInteger sheet = new AtomicInteger(1);// 分页大小可以适当调整int pageSize = ExcelConstants.SELECT_TO_DB_ROWS_MYBATIS;//开启多个线程分页查数据getData(lvnengAllCardBillVo,queue,pageSize);Future<?> submit = executorService.submit(() -> {int count = 0;while (true) {List<Map<String,Object>> list = null;try {list = queue.take();} catch (InterruptedException e) {Thread.interrupted();}if (CollectionUtils.isEmpty(list)) {count++;// 当获取到两次空集合时,说明已经读完if (count == N) {break;}continue;}if(num.get()>=600000){sheet.getAndAdd(1);num.getAndSet(0);}num.getAndAdd(list.size());List<List<String>> dataList = ExcelUtils.getDataList(nameMap, list);writer.write(dataList, EasyExcel.writerSheet("Sheet"+sheet).build());}writer.finish();});try {// 阻塞等待完成,异步处理也可以去掉这段代码submit.get();} catch (Exception e) {}}
public void getData(ActResultLogVO actResultLogVO,BlockingQueue<List<Map<String,Object>>> queue,int pageSize) {// 根据数据读写速度来调整,一般来说读的逻辑复杂,比较慢,如果读比写快,这里设为1int N = 2;AtomicInteger start = new AtomicInteger(0);for (int i = 0; i < N; i++) {executorService.submit(() -> {while (true) {//自增int startNum = start.getAndAdd(pageSize);List<Map<String, Object>> list = new ArrayList<>();try {ActResultLogVO actResultLogVO1 = DeepCopyUtil.deepCopy(actResultLogVO);actResultLogVO1.setStart(startNum);List<Map<String, Object>> list = selectactResultLogVOPage(actResultLogVO1);if (CollectionUtils.isEmpty(list)) {//读到没数据也要放入空集合queue.put(Collections.EMPTY_LIST);break;}queue.put(list);} catch (Exception e) {//异常情况也要放入空集合,防止写线程无法退出循环try {queue.put(Collections.EMPTY_LIST);} catch (InterruptedException ex) {throw new RuntimeException(ex);}throw new RuntimeException(e);}}});}logger.info("查询数据完成");}
@Configuration
public class ThreadPoolConfig {@Bean("excelThreadPool")public ExecutorService buildExcelThreadPool() {int cpuNum = Runtime.getRuntime().availableProcessors();BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(1000);ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("excel-pool-%d").build();return new ThreadPoolExecutor(10 * cpuNum, 30 * cpuNum,1, TimeUnit.MINUTES, workQueue, threadFactory);}
}
public class ExcelConstants {public static final Integer PER_SHEET_ROW_COUNT = 100*10000;public static final Integer PER_WRITE_ROW_COUNT = 20*10000;public static final Integer SHEET_WRITE_ROW_COUNT = 50*10000;public static final Integer SELECT_TO_DB_ROWS = 10*10000;public static final Integer SELECT_TO_DB_ROWS_MYBATIS = 5*10000;
}
@Data
public class DynamicExcelData {//列名private String name;//默认值private String defaultValue;public DynamicExcelData(String name, String defaultValue) {this.name = name;this.defaultValue = defaultValue;}
}
5,用到的util
5.1 EasyUtils
public class ExcelUtils {public static void dynamicExportByURL(String filePath,LinkedHashMap<String, DynamicExcelData> nameMap,List<Map<String, Object>> list,String sheetName) throws IOException {//首先判断是否有数据,没有就返回if(CollUtil.isEmpty(list)){return;}//这里的map使用LinkedHashMap,实现字段的顺序功能if(nameMap==null){throw new RuntimeException("请填写好映射表数据");}File file = getFile(filePath);dynamicExportByURL(file,nameMap,list,sheetName);}public static void dynamicExport(HttpServletResponse response,LinkedHashMap<String, DynamicExcelData> nameMap,List<Map<String, Object>> list,String sheetName) throws IOException {//首先判断是否有数据,没有就返回if(CollUtil.isEmpty(list)){return;}//这里的map使用LinkedHashMap,实现字段的顺序功能if(nameMap==null){throw new RuntimeException("请填写好映射表数据");}response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");//使用EasyExcel write进行写出EasyExcel.write(response.getOutputStream()).head(getHead(nameMap)).sheet(sheetName).doWrite(getDataList(nameMap,list));}public static ArrayList<List<String>> getHead(LinkedHashMap<String, DynamicExcelData> nameMap) {//获取表头ArrayList<List<String>> head = new ArrayList<>();for (Map.Entry<String, DynamicExcelData> titleMap : nameMap.entrySet()) {DynamicExcelData data = titleMap.getValue();head.add(Collections.singletonList(data.getName()));}return head;}public static List<List<String>> getDataList(LinkedHashMap<String, DynamicExcelData> nameMap, List<Map<String, Object>> list) {//先初始化一下传入int size = list.size();List<List<String>> dataList = new ArrayList<>();for (int i = 0; i < size; i++) {dataList.add(new ArrayList<>());}//数据重组for (int i = 0; i < list.size(); i++) {Map<String, Object> map = list.get(i);List<String> columns = dataList.get(i);for (Map.Entry<String, DynamicExcelData> sortNameEntry : nameMap.entrySet()) {String key = sortNameEntry.getKey();Object value = map.get(key);columns.add(value != null ? String.valueOf(value) : sortNameEntry.getValue().getDefaultValue());}}return dataList;}public static File getFile(String filePath) throws IOException {File file = new File(filePath);if (!file.exists()) {file.createNewFile();}return file;}public static void dynamicExportByURL(File file,LinkedHashMap<String, DynamicExcelData> nameMap, List date,String sheetName) {long startTime = 0;ExcelWriter excelWriter = null;try {startTime = System.currentTimeMillis();// 获取 sheet 的个数int sheetNum = getSheetNum(date.size());// 获取每个sheet 写入的次数int writeNumPerSheet = getWriteNumPerSheet();// 最后一个 sheet 写入的数量int writeNumLastSheet = date.size() - (sheetNum - 1) * ExcelConstants.PER_SHEET_ROW_COUNT;// 最后一个 sheet 写入的次数int writeNumPerLastSheet = writeNumLastSheet % ExcelConstants.PER_WRITE_ROW_COUNT == 0 ? writeNumLastSheet / ExcelConstants.PER_WRITE_ROW_COUNT : writeNumLastSheet / ExcelConstants.PER_WRITE_ROW_COUNT + 1;// 指定写入的文件excelWriter = EasyExcel.write(file).head(getHead(nameMap)).build();for (int i = 0; i < sheetNum; i++) {String sheet = sheetName + i;WriteSheet writeSheet = EasyExcel.writerSheet(i, sheet).build();int writeNum = i == sheetNum - 1 ? writeNumPerLastSheet : writeNumPerSheet; // 每个sheet 写入的次数int endEndNum = i == sheetNum - 1 ? date.size() : (i + 1) * ExcelConstants.PER_SHEET_ROW_COUNT; // 每个sheet 最后一次写入的最后行数for (int j = 0; j < writeNum; j++) {long l = System.currentTimeMillis();int startNum = i * ExcelConstants.PER_SHEET_ROW_COUNT + j * ExcelConstants.PER_WRITE_ROW_COUNT;int endNum = j == writeNum - 1 ? endEndNum : i * ExcelConstants.PER_SHEET_ROW_COUNT + (j + 1) * ExcelConstants.PER_WRITE_ROW_COUNT;excelWriter.write(getDataList(nameMap,date.subList(startNum, endNum)), writeSheet);}}} catch (Exception e) {} finally {// 需要放入 finally 中if (excelWriter != null) {excelWriter.finish();}}}public static void writeExcel(String filePath, Class clazz, List date,String sheetName) throws Exception{File file = getFile(filePath);long startTime = System.currentTimeMillis();// 获取 sheet 的个数int sheetNum = getSheetNum(date.size());// 获取每个sheet 写入的次数int writeNumPerSheet = getWriteNumPerSheet();// 最后一个 sheet 写入的数量int writeNumLastSheet = date.size() - (sheetNum - 1) * ExcelConstants.PER_SHEET_ROW_COUNT;// 最后一个 sheet 写入的次数int writeNumPerLastSheet = writeNumLastSheet % ExcelConstants.PER_WRITE_ROW_COUNT == 0 ? writeNumLastSheet / ExcelConstants.PER_WRITE_ROW_COUNT : writeNumLastSheet / ExcelConstants.PER_WRITE_ROW_COUNT + 1;// 指定写入的文件ExcelWriter excelWriter = EasyExcel.write(file, clazz).build();for (int i = 0; i < sheetNum; i++) {String sheet = sheetName + i;WriteSheet writeSheet = EasyExcel.writerSheet(i, sheet).build();int writeNum = i == sheetNum - 1 ? writeNumPerLastSheet : writeNumPerSheet; // 每个sheet 写入的次数int endEndNum = i == sheetNum - 1 ? date.size() : (i + 1) * ExcelConstants.PER_SHEET_ROW_COUNT; // 每个sheet 最后一次写入的最后行数for (int j = 0; j < writeNum; j++) {long l = System.currentTimeMillis();int startNum = i * ExcelConstants.PER_SHEET_ROW_COUNT + j * ExcelConstants.PER_WRITE_ROW_COUNT;int endNum = j == writeNum - 1 ? endEndNum : i * ExcelConstants.PER_SHEET_ROW_COUNT + (j + 1) * ExcelConstants.PER_WRITE_ROW_COUNT;excelWriter.write(date.subList(startNum, endNum), writeSheet);}}// 需要放入 finally 中if (excelWriter != null) {excelWriter.finish();}}public static int getSheetNum(int dateSize){return dateSize % ExcelConstants.PER_SHEET_ROW_COUNT == 0 ? (dateSize / ExcelConstants.PER_SHEET_ROW_COUNT) : (dateSize / ExcelConstants.PER_SHEET_ROW_COUNT + 1);}public static int getWriteNumPerSheet(){return ExcelConstants.PER_SHEET_ROW_COUNT % ExcelConstants.PER_WRITE_ROW_COUNT == 0 ? (ExcelConstants.PER_SHEET_ROW_COUNT / ExcelConstants.PER_WRITE_ROW_COUNT) : (ExcelConstants.PER_SHEET_ROW_COUNT / ExcelConstants.PER_WRITE_ROW_COUNT + 1);}public static List<String> objectToList(Object obj){ArrayList<String> list = new ArrayList<>();//获取obj类中的所有字段Field[] fields = obj.getClass().getDeclaredFields();//遍历所有属性for (Field field : fields) {try {field.setAccessible(true);list.add(field.get(obj).toString());} catch (IllegalAccessException e) {throw new RuntimeException(e);}}return list;}public static Map<String,Object> objectToMap(Object obj){HashMap<String, Object> map = new HashMap<>();//获取obj类中的所有字段Field[] fields = obj.getClass().getDeclaredFields();//遍历所有属性for (Field field : fields) {try {field.setAccessible(true);map.put(field.getName(),field.get(obj));} catch (IllegalAccessException e) {throw new RuntimeException(e);}}return map;}/*** 通过反射方式将头部作为公共部分进行设置*/public static List<List<String>> setTitles(Class clazz) {List<List<String>> titles = new ArrayList<List<String>>();for (Field declaredField : clazz.getDeclaredFields()) {ExcelProperty annotation = declaredField.getAnnotation(ExcelProperty.class);if (null != annotation) {titles.add(Arrays.asList(annotation.value()));}}return titles;}
}
5.2 深拷贝
public class DeepCopyUtil {public static <T extends Serializable> T deepCopy(T object) {try {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);objectOutputStream.writeObject(object);ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);return (T) objectInputStream.readObject();} catch (IOException | ClassNotFoundException e) {throw new RuntimeException(e);}}
}
配置静态资源访问
@Configuration
public class MyStaticConfig extends WebMvcConfigurationSupport {@Value("${download.url}")private String fileDir;@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/uploads/**").addResourceLocations("classpath:/META-INF/resources/", "classpath:/resources/","classpath:/static/", "classpath:/public/","file:"+fileDir);}
}
相关文章:
EasyExcel多线程批量导出数据,动态表头,静态资源访问
1.导入依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version></dependency>2.建立实体 Data public class ActResultLogVO implements Serializable {private static…...

树莓派界面改成中文
安装完树莓派系统(Raspberry Pi OS with Desktop),第一次启动时,时会有如下面二个图所示,让你选择区域时区和语言。 树莓派默认的语言为英文,如果你在安装时没有选择的话,默认的区域为英国,语言为英国英文&…...

软件工程期末复习
● 用例:借书 ●参与者:管理员,借阅者 ●操作流: ① 管理员进入图书借阅界面,用例开始。 ② 系统要求输入借阅者的借书证编码。 ③系统检验借书证编码,如果正确,则显示借阅者的信息。 A1:借书证编码有错。 A2: 如果该借…...
【linux】select实现定时器
/*秒级定时器*/ void seconds_sleep(unsigned long seconds) {if(seconds 0) return;struct timeval tv;tv.tv_secseconds;tv.tv_usec0;int err;do{errselect(0,NULL,NULL,NULL,&tv);}while(err<0 && errnoEINTR); }/*毫秒定时器*/void milliseconds_slee…...

Android 13 - Media框架(28)- MediaCodec(三)
上一节我们了解到 ACodec 执行完 start 流程后,会把所有的 input buffer 都提交给 MediaCodec 层,MediaCodec 是如何处理传上来的 buffer 呢?这一节我们就来了解一下这部分内容。 1、ACodecBufferChannel::fillThisBuffer ACodec 通过调用 A…...

Azure 学习总结
文章目录 1. Azure Function1.1 Azure Function 概念1.2 Azure Function 实现原理1.3 Azure Function 本地调试1.4 Azure Function 云部署 2. Azure API Managment 概念 以及使用2.1 Azure API 概念2.2 Azure API 基本使用 3. Service Bus 应用场景及相关特性3.1 Service Bus 基…...
数据库是否可以直接作为数据仓库的数据源
在数据仓库使用数据时,我们是否可以直接将数据库作为数据源?如果使用了,会存在哪些问题? 数据库中存储的是业务数据,存储方式是行式存储;而数据仓库中数据是以列式存储的;如果数据仓库要想使用…...

IntelliJ IDE 插件开发 | (四)开发一个时间管理大师插件
系列文章 IntelliJ IDE 插件开发 |(一)快速入门IntelliJ IDE 插件开发 |(二)UI 界面与数据持久化IntelliJ IDE 插件开发 |(三)消息通知与事件监听IntelliJ IDE 插件开发 |(四)开发一…...

【ChatGPT 默认强化学习策略】PPO 近端策略优化算法
PPO 近端策略优化算法 PPO 概率比率裁剪 演员-评论家算法演员-评论家算法:多智能体强化学习核心框架概率比率裁剪:逐步进行变化的方法PPO 目标函数的设计重要性采样KL散度 PPO 概率比率裁剪 演员-评论家算法 论文链接:https://arxiv.org…...

【银行测试】金融银行-理财项目面试/分析总结(二)
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 银行理财相关的项…...

张江智荟毁约offer
毕业8年后,找工作被国企歧视学历!已经收到了offer,在入职前一周被通知要撤回offer,拒绝录用,理由居然是他们只要本科211以上的人 这是我今天(2023-12-26)亲身经历的事,听说过面试前…...
ubuntu 系统终端颜色设置
1 开启终端颜色 # 第一步: 在 ~/.bashrc 中设置 force_color_promptyes# 第二步: 执行 source ~/.bashrc2 对于精减的 .bashrc 在 ~/.bashrc 中添加以下内容,再执行 source ~/.bashrc : # uncomment for a colored prompt, if…...

【Vue】class与style绑定
✨ 专栏介绍 在当今Web开发领域中,构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架,正是为了满足这些需求而诞生。它采用了MVVM架构模式,并通过数据驱动和组件化的方式,使…...

大厂前端面试题总结(百度、字节跳动、腾讯、小米.....),附上热乎面试经验!
先简单介绍下自己,我“平平无奇小天才”一枚,毕业于南方普通985普通学生,有幸去百度、字节面试,感觉大公司就是不一样,印象最深的是字节,所以有必要总结一下面试经验,以及面试中遇到的一些问题&…...

EXPLORING DIFFUSION MODELS FOR UNSUPERVISED VIDEO ANOMALY DETECTION 论文阅读
EXPLORING DIFFUSION MODELS FOR UNSUPERVISED VIDEO ANOMALY DETECTION 论文阅读 ABSTRACT1. INTRODUCTION2. RELATEDWORK3. METHOD4. EXPERIMENTAL ANALYSIS AND RESULTS4.1. Comparisons with State-Of-The-Art (SOTA)4.2. Diffusion Model Analysis4.3. Qualitative Result…...
当 ML 遇到 DevOps:如何理解 MLOps
近年来,人工智能 (AI) 和机器学习 (ML) 已经席卷全球,几乎成为任何行业的重要组成部分,从零售和娱乐到医疗保健和银行业。这些技术能够通过分析大量数据实现运营自动化、降低成本和促进决策&…...

vue+element+springboot实现多张图片上传
1.需求说明 2.实现思路 3.el-upload组件主要属性说明 4.前端传递MultipartFile数组与服务端接收说明 5.完整代码 1.需求说明 动态模块新增添加动态功能,支持多张图片上传.实现过程中对el-upload组件不是很熟悉,踩了很多坑,当然也参考过别的文章,发现处理很…...
react使用useState更新数组失败
失败案例: const [addBox, setAddBox] useState([])const itemAdd (item) >{addBox.push(item);setAddBox(addBox)console.log(addBox,点击添加按钮)} 原因:react的useState hook监听的是浅监听 在 React 中,使用 useState Hook 来更新…...
《LIO-SAM阅读笔记》3.后端优化
前言: LIO-SAM后端优化部分写在了mapOptimization.cpp文件中,本部分主要进行了激光帧的scan-to-map匹配,回环检测以及关键帧的因子图优化。本部分主要有两个环节同步进行,一个单独开辟了回环检测线程,另外一个是lidar…...

mac下jd-gui提示没有找到合适的jdk版本
mac下jd-gui提示jdk有问题 背景解决看一下是不是真有问题了方法一:修改启动脚本方法二:设置launchd环境变量 扩展动态切jdk脚本(.bash_profile) 背景 配置了动态jdk后,再次使用JD-GUI提示没有找到合适的jdk版本。 解决 看一下是不是真有问题…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
用js实现常见排序算法
以下是几种常见排序算法的 JS实现,包括选择排序、冒泡排序、插入排序、快速排序和归并排序,以及每种算法的特点和复杂度分析 1. 选择排序(Selection Sort) 核心思想:每次从未排序部分选择最小元素,与未排…...

vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能
vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能 查看官网:https://vxetable.cn 效果 代码 通过 checkbox-config.isShift 启用批量选中,启用后按住快捷键和鼠标批量选取 <template><div><vxe-grid v-bind"gri…...

Spring AI中使用ChatMemory实现会话记忆功能
文章目录 1、需求2、ChatMemory中消息的存储位置3、实现步骤1、引入依赖2、配置Spring AI3、配置chatmemory4、java层传递conversaionId 4、验证5、完整代码6、参考文档 1、需求 我们知道大型语言模型 (LLM) 是无状态的,这就意味着他们不会保…...
触发DMA传输错误中断问题排查
在STM32项目中,集成BLE模块后触发DMA传输错误中断(DMA2_Stream1_IRQHandler进入错误流程),但单独运行BLE模块时正常,表明问题可能源于原有线程与BLE模块的交互冲突。以下是逐步排查与解决方案: 一、问题根源…...