当前位置: 首页 > news >正文

EasyExcel实现百万数据批量导出

当数据量比较大时,例如数据量达到百万级,传统的一次读取到内存中在写入excel文件的方法便不再适用了,可能会导致内存溢出;而且一次性将数据写入一张sheet工作表也不太好。
但我们可以选择数据分片的方式批量写入多个工作表。
测试数据100w条,写入到Excel表中,分成5个sheet表,每个sheet表20w条。

1.引入依赖

pom.xml

    <dependencies><!-- web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- mybatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- alibaba easyexcel --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.5</version><exclusions><exclusion><groupId>org.apache.poi</groupId><artifactId>poi</artifactId></exclusion><exclusion><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId></exclusion><exclusion><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId></exclusion></exclusions></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency><!-- mybatis-plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3</version></dependency><!-- jdbc --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!--Mysql依赖包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- hutool --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.16</version></dependency></dependencies>

2. Controller/Service/Mapper

实体类User

import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.time.LocalDateTime;@NoArgsConstructor
@AllArgsConstructor
@Data
@TableName("user")
public class User implements Serializable {@TableId("id")@ExcelProperty("id")private Long id;@ExcelProperty("username")private String username;@ExcelProperty("password")private String password;@ExcelProperty("email")private String email;@ExcelProperty("phoneNumber")private String phoneNumber;@ExcelProperty("createdAt")private LocalDateTime createdAt;@ExcelProperty(value = "updatedAt")private LocalDateTime updatedAt;}

UserCtrl


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.UUID;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.example.excel.config.LocalDateTimeConverter;
import com.example.excel.domain.User;
import com.example.excel.mapper.UserMapper;
import com.example.excel.util.ExcelConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;/*** @author: hong.jian* 09-28 11:37*/
@RestController
@RequiredArgsConstructor
@Slf4j
@RequestMapping("/export")
public class UserCtrl {private final UserMapper userMapper;private final Executor exportThreadPoolExecutor;
}

UserService 和 UserServiceImpl

public interface UserService extends IService<User> {}@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {private final UserMapper userMapper;}

UserMapper


@Mapper
public interface UserMapper extends BaseMapper<User> {List<User> selfSelectList(@Param("currentPage") int currentPage, @Param("pageSize") int pageSize);}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.excel.mapper.UserMapper"><!-- 使用覆盖索引处理深度分页 --><select id="seleSelectList"  resultType="com.example.excel.domain.User">SELECTu.id,u.username,u.PASSWORD,u.email,u.phone_number,u.created_at,u.updated_atFROMUSER u,( SELECT t.id FROM USER t ORDER BY t.id LIMIT #{currentPage}, #{pageSize} ) AS dWHEREu.id = d.id;</select></mapper>

LocalDateTime时间字段转换器

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;/*** 自定义LocalDateTime时间字段类型转换器*/
public class LocalDateTimeConverter implements Converter<LocalDateTime> {private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");@Overridepublic Class<LocalDateTime> supportJavaTypeKey() {return LocalDateTime.class;}@Overridepublic WriteCellData<?> convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {if (value != null) {return new WriteCellData<>(value.format(FORMATTER));}return new WriteCellData<>("");}@Overridepublic LocalDateTime convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {if (cellData.getStringValue() != null) {return LocalDateTime.parse(cellData.getStringValue(), FORMATTER);}return null;}
}

3. 编写Controller方法

    @RequestMapping("/test")public void export(HttpServletResponse response) throws IOException {log.info("*********统计查询列表导出开始!**************");long start = System.currentTimeMillis();// 文件名String fileName = String.valueOf(UUID.randomUUID());OutputStream outputStream = null;try {// 总记录数:实际中需要根据查询条件进行统计即可:一共多少条long totalCount = userMapper.selectCount(null);// 每一个Sheet存放20w条数据Integer sheetDataRows = ExcelConstants.PER_SHEET_ROW_COUNT;// 每次写入的数据量10w,每页查询10WInteger writeDataRows = ExcelConstants.PER_WRITE_ROW_COUNT;// 计算需要的Sheet数量long sheetNum = totalCount % sheetDataRows == 0 ? (totalCount / sheetDataRows) : (totalCount / sheetDataRows + 1);// 计算一般情况下每一个Sheet需要写入的次数(一般情况不包含最后一个sheet,因为最后一个sheet不确定会写入多少条数据)Integer oneSheetWriteCount = sheetDataRows / writeDataRows;// 计算最后一个sheet需要写入的次数long lastSheetWriteCount = totalCount % sheetDataRows == 0 ? oneSheetWriteCount : (totalCount % sheetDataRows % writeDataRows == 0 ?((totalCount % sheetDataRows) / writeDataRows) : ((totalCount % sheetDataRows) / writeDataRows + 1));outputStream = response.getOutputStream();// 必须放到循环外,否则会刷新流ExcelWriter excelWriter = EasyExcel.write(outputStream).build();// 开始分批查询分次写入for (int i = 0; i < sheetNum; i++) {log.info("*********统计查询列表第" + (i + 1) + "页导出开始!**************");// 循环写入次数: j的自增条件是当不是最后一个Sheet的时候写入次数为正常的每个Sheet写入的次数,如果是最后一个就需要使用计算的次数lastSheetWriteCountfor (int j = 0; j < (i != sheetNum - 1 ? oneSheetWriteCount : lastSheetWriteCount); j++) {// 分页查询一次10w// 设置偏移量int currentPage = (j + oneSheetWriteCount * i) * writeDataRows;// 设置每页大小int pageSize = writeDataRows;// 使用覆盖索引避免深度分页List<User> userList = userMapper.selfSelectList(currentPage, pageSize);if (CollUtil.isEmpty(userList)) {  // 记录集合判空continue;}// 写入到excel:// 这里可以通过设置includeColumnFiledNames、excludeColumnFiledNames导出什么字段,可以动态配置,前端传过来那些列,就导出那些列WriteSheet writeSheet = EasyExcel.writerSheet(i, "Sheet" + (i + 1)).head(User.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())   // 自动调整列宽.registerConverter(new LocalDateTimeConverter())    // 时间字段转换器// .includeColumnFiledNames()  // 只导出指定字段集合// .excludeColumnFiledNames()  // 排除指定字段集合.build();excelWriter.write(userList, writeSheet);}log.info("*********统计查询列表第" + (i + 1) + "页导出结束!**************");}// 下载EXCEL,返回给前端stream流response.setContentType("application/octet-stream");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");excelWriter.finish();outputStream.flush();log.info("*********统计查询列表导出结束!**************");log.info("耗时:" + (System.currentTimeMillis() - start));} catch (Exception e) {e.printStackTrace();} finally {if (outputStream != null) {outputStream.close();}}}

4. 测试

100w条数据导出约27s,还是有点慢。

9-28 17:49:27.847  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表导出开始!**************
2024-09-28 17:49:28.744  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第1页导出开始!**************
2024-09-28 17:49:32.857  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第1页导出结束!**************
2024-09-28 17:49:32.857  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第2页导出开始!**************
2024-09-28 17:49:36.955  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第2页导出结束!**************
2024-09-28 17:49:36.955  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第3页导出开始!**************
2024-09-28 17:49:41.007  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第3页导出结束!**************
2024-09-28 17:49:41.007  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第4页导出开始!**************
2024-09-28 17:49:45.109  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第4页导出结束!**************
2024-09-28 17:49:45.109  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第5页导出开始!**************
2024-09-28 17:49:49.272  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第5页导出结束!**************
2024-09-28 17:49:55.630  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表导出结束!**************
2024-09-28 17:49:55.631  INFO 120052 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : 耗时:27784

5. 思考

引入线程池

    @Beanpublic Executor exportThreadPoolExecutor(){return  new ThreadPoolExecutor(5,10,10,TimeUnit.SECONDS,new ArrayBlockingQueue<>(100),new ThreadPoolExecutor.CallerRunsPolicy());}

并在UserController中注入

使用线程池优化代码

    @RequestMapping("/test2")public void export2(HttpServletResponse response) throws IOException {log.info("*********统计查询列表导出开始!**************");long start = System.currentTimeMillis();String fileName = String.valueOf(UUID.randomUUID());OutputStream outputStream = null;try {long totalCount = userMapper.selectCount(null);Integer sheetDataRows = ExcelConstants.PER_SHEET_ROW_COUNT;Integer writeDataRows = ExcelConstants.PER_WRITE_ROW_COUNT;long sheetNum = (totalCount + sheetDataRows - 1) / sheetDataRows;Integer oneSheetWriteCount = sheetDataRows / writeDataRows;long lastSheetWriteCount = totalCount % sheetDataRows == 0 ? oneSheetWriteCount :(totalCount % sheetDataRows + writeDataRows - 1) / writeDataRows;outputStream = response.getOutputStream();ExcelWriter excelWriter = EasyExcel.write(outputStream).build();// 信号枪,配合多线程实现并发编程CountDownLatch latch = new CountDownLatch((int) sheetNum);for (int i = 0; i < sheetNum; i++) {int finalI = i;CompletableFuture.runAsync(() -> {log.info("*********统计查询列表第" + (finalI + 1) + "页导出开始!**************");WriteSheet writeSheet = EasyExcel.writerSheet(finalI, "Sheet" + (finalI + 1)).head(User.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).registerConverter(new LocalDateTimeConverter()).build();try {for (int j = 0; j < (finalI != sheetNum - 1 ? oneSheetWriteCount : lastSheetWriteCount); j++) {int currentPage = (j + oneSheetWriteCount * finalI) * writeDataRows;List<User> userList = userMapper.selfSelectList(currentPage, writeDataRows);if (CollUtil.isEmpty(userList)) {continue;}// 加锁实现互斥写入,确保线程安全synchronized (excelWriter) {excelWriter.write(userList, writeSheet);}}} finally {latch.countDown();log.info("*********统计查询列表第" + (finalI + 1) + "页导出结束!**************");}}, exportThreadPoolExecutor);   // 尝试引入多线程}latch.await();response.setContentType("application/octet-stream");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");excelWriter.finish();outputStream.flush();} catch (Exception e) {e.printStackTrace();} finally {if (outputStream != null) {outputStream.close();}}log.info("*********统计查询列表导出结束!**************");log.info("耗时:" + (System.currentTimeMillis() - start));}

再次测试,耗时约20s

2024-09-28 18:05:54.239  INFO 53952 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表导出开始!**************
2024-09-28 18:05:55.132  INFO 53952 --- [pool-1-thread-2] com.example.excel.controller.UserCtrl    : *********统计查询列表第2页导出开始!**************
2024-09-28 18:05:55.132  INFO 53952 --- [pool-1-thread-3] com.example.excel.controller.UserCtrl    : *********统计查询列表第3页导出开始!**************
2024-09-28 18:05:55.132  INFO 53952 --- [pool-1-thread-4] com.example.excel.controller.UserCtrl    : *********统计查询列表第4页导出开始!**************
2024-09-28 18:05:55.132  INFO 53952 --- [pool-1-thread-5] com.example.excel.controller.UserCtrl    : *********统计查询列表第5页导出开始!**************
2024-09-28 18:05:55.132  INFO 53952 --- [pool-1-thread-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第1页导出开始!**************
2024-09-28 18:06:04.341  INFO 53952 --- [pool-1-thread-3] com.example.excel.controller.UserCtrl    : *********统计查询列表第3页导出结束!**************
2024-09-28 18:06:05.483  INFO 53952 --- [pool-1-thread-4] com.example.excel.controller.UserCtrl    : *********统计查询列表第4页导出结束!**************
2024-09-28 18:06:06.591  INFO 53952 --- [pool-1-thread-5] com.example.excel.controller.UserCtrl    : *********统计查询列表第5页导出结束!**************
2024-09-28 18:06:07.795  INFO 53952 --- [pool-1-thread-1] com.example.excel.controller.UserCtrl    : *********统计查询列表第1页导出结束!**************
2024-09-28 18:06:08.871  INFO 53952 --- [pool-1-thread-2] com.example.excel.controller.UserCtrl    : *********统计查询列表第2页导出结束!**************
2024-09-28 18:06:14.907  INFO 53952 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : *********统计查询列表导出结束!**************
2024-09-28 18:06:14.907  INFO 53952 --- [nio-8080-exec-1] com.example.excel.controller.UserCtrl    : 耗时:20667

可以发现,性能有提升,但提升不是很明显。我个人理解是为了避免多个线程同时写入excel产生的线程安全问题,采用了加锁的方式,确保线程间使用excelwriter写入excel文件的操作是互斥的,这导致性能收到了影响。

参考链接:使用EasyExcel实现excel导出,支持百万大数据量导出

相关文章:

EasyExcel实现百万数据批量导出

当数据量比较大时&#xff0c;例如数据量达到百万级&#xff0c;传统的一次读取到内存中在写入excel文件的方法便不再适用了&#xff0c;可能会导致内存溢出&#xff1b;而且一次性将数据写入一张sheet工作表也不太好。 但我们可以选择数据分片的方式批量写入多个工作表。 测试…...

兆易GD32E508的SHRTIM配置 主从定时器 产生2对相位可调互补PWM 带死区

如有技术问题及技术需求请加作者微信! GD32E5系列MCU是基于Arm Cortex-M33处理器的32位通用微控制器。Cortex-M33处理器基于Armv8架构,处理器主频最高可达180MHz,支持强大的可扩展指令集,包括通用数据处理I/O控制任务、增强的数据处理位域操作、DSP和浮点运算器(FPU)。 GD…...

数据归组工具

利用C#将数据 [ {"name":"A","fzh":1}, {"name":"A","fzh":2}, {"name":"A","fzh":3}, {"name":"B","fzh":4}, {"name":"B",&…...

JavaScript 中的闭包的形成及使用场景

JavaScript 中的闭包 闭包&#xff08;Closure&#xff09; 是 JavaScript 中一个非常重要且独特的概念&#xff0c;它指的是 函数能够记住并访问其词法作用域内的变量&#xff0c;即使这个函数在其词法作用域之外执行。 通俗地说&#xff0c;闭包是 一个函数可以“记住”它在…...

后端返回内容有换行标识,前端如何识别换行

<br/>的话 用 v-html \n 可以用css样式 white-space: pre-wrap 后端返回结果 前端...

服务器被挂马,导致网站首页被更改怎么解决

当服务器被挂马并导致网站首页被篡改时&#xff0c;说明服务器或网站的安全性遭到破坏。为了修复并防止未来的攻击&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1. 立即下线网站 目的&#xff1a;防止恶意软件进一步传播&#xff0c;保护用户数据和防止攻击者继续对网…...

Android 利用OSMdroid开发GIS

1、地址 Github地址&#xff1a;https://gitee.com/mirrors/osmdroid Git地址&#xff1a; GitCode - 全球开发者的开源社区,开源代码托管平台 Git下载包地址&#xff1a;Releases osmdroid/osmdroid GitHub 新建项目 osmdroid在线&#xff1a; &#xff08;1&#xff09…...

一文上手skywalking【上】

一、skywalking预览 1.1 skywalking 概述 ​ Apache SkyWalking, 适用于分布式系统的应用程序性能监控工具&#xff0c;专为微服务、云原生和基于容器的 &#xff08;Kubernetes&#xff09; 架构而设计。官方地址: https://skywalking.apache.org/ 适用于分布式系统的应用程…...

【JavaScript】JQuery基础知识及应用

一、JQuery的导入方法 https://editor.csdn.net/md/?articleId132214798 二、JQuery介绍 JQuery(JQ)&#xff1a;JS的一个类库&#xff08;方法库&#xff1a;包含了大量的、有助于项目开发的属性和方法&#xff09; 第一代版本1.xx.xx: 1.11.3 兼容所有浏览器的&#xff0…...

初始爬虫9

1.元素定位后的操作 “find_element“仅仅能够获取元素&#xff0c;不能够直接获取其中的数据&#xff0c;如果需要获取数据需要使用以下方法”。下面列出了两个方法&#xff1a; 获取文本 element.text 通过定位获取的标签对象的 text 属性&#xff0c;获取文本内容 获取属性…...

从细胞到临床:表观组学分析技术在精准医疗中的角色

中国科学院等科研院所的顶尖人才发起&#xff0c;专注于多组学、互作组、生物医学等领域的研究与服务。在Nature等国际知名期刊发表多篇论文&#xff0c;提供实验整体打包、免费SCI论文润色等四大优势服务。在表观组学分析技术方面&#xff0c;提供DAP-seq、ATAC-seq、H3K4me3 …...

带你0到1之QT编程:二十、QT与MySQL喜结连理,构建数据库应用开发

此为QT编程的第二十谈&#xff01;关注我&#xff0c;带你快速学习QT编程的学习路线&#xff01; 每一篇的技术点都是很很重要&#xff01;很重要&#xff01;很重要&#xff01;但不冗余&#xff01; 我们通常采取总-分-总和生活化的讲解方式来阐述一个知识点&#xff01; …...

梯度下降法及其性能评估

梯度下降法 梯度下降法是一种一阶迭代优化算法&#xff0c;用于寻找函数的局部最小值。在机器学习中&#xff0c;它通常用来最小化损失函数&#xff08;也称为成本函数或误差函数&#xff09;&#xff0c;以提高模型对数据的拟合程度。梯度下降法的基本思想是沿着目标函数当前…...

906. 超级回文数

1. 题目 906. 超级回文数 2. 解题思路 题目意思很简单&#xff0c;在给定范围中找到所有满足&#xff0c;它本身是回文&#xff0c;且它的平方也是回文的数字个数。 这题需要注意题目给定的范围&#xff0c;后面很有用&#xff1a; 因为回文范围是有限的&#xff0c;那么我…...

代码随想录算法训练营||二叉树

前/中/后序遍历 递归方式 参考文章 题目 思路&#xff1a;其实递归方式的前中后序遍历的方式都差不多&#xff0c;区别是在父节点的遍历时间。 前序代码 class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result new…...

线上报名小程序怎么做

在这个数字化、智能化的时代&#xff0c;信息技术的发展正以前所未有的速度改变着我们的生活。无论是学习、工作还是娱乐&#xff0c;互联网都成为了我们不可或缺的一部分。而在线上报名这一领域&#xff0c;小程序的出现更是为广大用户带来了前所未有的便捷与高效。今天&#…...

【测试岗】手撕代码 - 零钱兑换

322. 零钱兑换 题目描述 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。 你可以认为每种…...

菱形继承的类对父类的初始化、组合、多态、多态的原理等的介绍

文章目录 前言一、菱形继承的类对父类的初始化二、组合三、 多态1. 构成多态2. 虚函数3. 虚函数的重写4. 虚函数重写的两个例外1. 协变2. 析构函数的重写 5. C11 final 和 override1. final2. override 6. 设计不想被继承的类7. 重载、覆盖&#xff08;重写&#xff09;、 隐藏…...

React Native 在 build 的时候如果出现 `babel.config.js` 配置文件的错误

React Native 在 build 的时候如果出现以下错误, 就是 babel.config.js 配置文件的错误. Showing Recent Issues node:internal/process/promises:289triggerUncaughtException(err, true /* fromPromise */);^Error: .plugins[0][1] must be an object, false, or undefineda…...

【Linux】包管理器、vim详解及简单配置

&#x1f680;个人主页&#xff1a;小羊 &#x1f680;所属专栏&#xff1a;Linux 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 前言一、包管理器1.1 apt1.2 yum 二、Linux编辑器——vim2.1 vim的三种模式2.2 vim普通模式常用命令2.2.1 移动…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...