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

【JAVA】一篇聊透百万级数据导入导出场景问题、大数据处理策略及优化方案、EasyExcel 和 EasyPOI的玩法详解

在这里插入图片描述

文章目录

    • 名词介绍
    • 场景问题分析解决
      • 导入问题解决方案
        • 内存溢出(分批导入)
        • DB插入(分批插入)
      • 导出问题解决方案
    • 导入导出的策略
      • 定时导入导出
      • 实时导入导出
    • EasyPOI

更多相关内容可查看

玩之前先了解几个关键名词(大佬可省略):Apache POI、EasyExcel、EasyPOI

名词介绍

简单了解,详情可以扒拉官方文档

Apache POI:

官方文档:https://www.w3ccoo.com/apache_poi/apache_poi_overview.html

Apache POI是一个用于在Java程序中读写Microsoft Office文档(如Excel、Word和PowerPoint)的开源库

EasyExcel

官方文档:https://easyexcel.opensource.alibaba.com/

EasyExcel是一个Java库,用于快速、高效地读写Excel文件。它特别适合处理大数据量的Excel文件,相比其他库,EasyExcel在处理大文件时更节省内存,也更简单易用。

EasyPOI

源码地址:https://github.com/jueyue/easypoi

处理Excel文件的Java库,设计得比较简单易用,使得操作Excel文件的工作变得不那么复杂


场景问题分析解决

百万级或者千万级数据量导入导出的场景面临的一些问题,拆开解决:

导入问题解决方案

内存溢出(分批导入)

问题:传统的Apache POI在读取Excel文件时会创建大量的Java对象来表示文件中的每一个单元格和行,当数据量超级大,使用传统的POI方式来完成导入会内存溢出,并且效率会非常低;

解决:EasyExcel通过流式读取和写入数据,只在内存中处理当前的数据块,避免了一次性加载整个文件,从而有效降低了内存消耗。分批读取读取Excel中的百万级的数据,这一点EasyExcel只需要把它分批的参数3000调大即可。我是用的20w;

EasyExcel底层采用了什么技术解决的这个问题:

  • 基于流的API:EasyExcel使用了流式API来处理Excel文件。它使用了InputStream和OutputStream来逐步读取和写入数据,而不是一次性将整个文件加载到内存中。这样可以处理数据块,逐步读取和写入文件。
  • 事件驱动模型:EasyExcel采用了事件驱动的方式,特别是在读取时,库会触发事件(如行读取事件),开发者可以在这些事件发生时处理数据。这样,只有当前正在处理的行会被加载到内存中,其他数据仍然保留在文件中。
  • 按需加载:在读取过程中,EasyExcel只会加载当前需要处理的数据,而不是整个文件。它会在读取数据时动态地从磁盘加载数据块,然后处理完这些数据块后将其从内存中清除。
  • 低级别的文件操作:EasyExcel使用了底层的文件操作技术,如BufferedInputStream,来高效地读取文件内容,减少内存占用和提高读取速度。
DB插入(分批插入)

问题:其次就是往DB里插入,怎么去插入这20w条数据,当然不能一条一条的循环,应该批量插入这20w条数据,同样也不能使用Mybatis的批量插入,因为效率也低。可以参考下面链接【Myabtis批量插入和JDBC批量插入性能对比】

解决:使用JDBC+事务的批量操作将数据插入到数据库。(分批读取+JDBC分批插入+手动事务控制)

核心代码:

// EasyExcel的读取Excel数据的API
@Test
public void import2DBFromExcel10wTest() {String fileName = "D:\\StudyWorkspace\\JavaWorkspace\\java_project_workspace\\idea_projects\\SpringBootProjects\\easyexcel\\exportFile\\excel300w.xlsx";//记录开始读取Excel时间,也是导入程序开始时间long startReadTime = System.currentTimeMillis();System.out.println("------开始读取Excel的Sheet时间(包括导入数据过程):" + startReadTime + "ms------");//读取所有Sheet的数据.每次读完一个Sheet就会调用这个方法EasyExcel.read(fileName, new EasyExceGeneralDatalListener(actResultLogService2)).doReadAll();long endReadTime = System.currentTimeMillis();System.out.println("------结束读取Excel的Sheet时间(包括导入数据过程):" + endReadTime + "ms------");
}
// 事件监听
public class EasyExceGeneralDatalListener extends AnalysisEventListener<Map<Integer, String>> {/*** 处理业务逻辑的Service,也可以是Mapper*/private ActResultLogService2 actResultLogService2;/*** 用于存储读取的数据*/private List<Map<Integer, String>> dataList = new ArrayList<Map<Integer, String>>();public EasyExceGeneralDatalListener() {}public EasyExceGeneralDatalListener(ActResultLogService2 actResultLogService2) {this.actResultLogService2 = actResultLogService2;}@Overridepublic void invoke(Map<Integer, String> data, AnalysisContext context) {//数据add进入集合dataList.add(data);//size是否为100000条:这里其实就是分批.当数据等于10w的时候执行一次插入if (dataList.size() >= ExcelConstants.GENERAL_ONCE_SAVE_TO_DB_ROWS) {//存入数据库:数据小于1w条使用Mybatis的批量插入即可;saveData();//清理集合便于GC回收dataList.clear();}}/*** 保存数据到DB** @param* @MethodName: saveData* @return: void*/private void saveData() {actResultLogService2.import2DBFromExcel10w(dataList);dataList.clear();}/*** Excel中所有数据解析完毕会调用此方法** @param: context* @MethodName: doAfterAllAnalysed* @return: void*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {saveData();dataList.clear();}
}
//JDBC工具类
public class JDBCDruidUtils {private static DataSource dataSource;/*创建数据Properties集合对象加载加载配置文件*/static {Properties pro = new Properties();//加载数据库连接池对象try {//获取数据库连接池对象pro.load(JDBCDruidUtils.class.getClassLoader().getResourceAsStream("druid.properties"));dataSource = DruidDataSourceFactory.createDataSource(pro);} catch (Exception e) {e.printStackTrace();}}/*获取连接*/public static Connection getConnection() throws SQLException {return dataSource.getConnection();}/*** 关闭conn,和 statement独对象资源** @param connection* @param statement* @MethodName: close* @return: void*/public static void close(Connection connection, Statement statement) {if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}}/*** 关闭 conn , statement 和resultset三个对象资源** @param connection* @param statement* @param resultSet* @MethodName: close* @return: void*/public static void close(Connection connection, Statement statement, ResultSet resultSet) {close(connection, statement);if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}}/*获取连接池对象*/public static DataSource getDataSource() {return dataSource;}}
# druid.properties配置driverClassName=oracle.jdbc.driver.OracleDriverurl=jdbc:oracle:thin:@localhost:1521:ORCLusername=mrkaypassword=******initialSize=10maxActive=50maxWait=60000// Service中具体业务逻辑/*** 测试用Excel导入超过10w条数据,经过测试发现,使用Mybatis的批量插入速度非常慢,所以这里可以使用 数据分批+JDBC分批插入+事务来继续插入速度会非常快** @param* @MethodName: import2DBFromExcel10w* @return: java.util.Map<java.lang.String, java.lang.Object>*/@Overridepublic Map<String, Object> import2DBFromExcel10w(List<Map<Integer, String>> dataList) {HashMap<String, Object> result = new HashMap<>();//结果集中数据为0时,结束方法.进行下一次调用if (dataList.size() == 0) {result.put("empty", "0000");return result;}//JDBC分批插入+事务操作完成对10w数据的插入Connection conn = null;PreparedStatement ps = null;try {long startTime = System.currentTimeMillis();System.out.println(dataList.size() + "条,开始导入到数据库时间:" + startTime + "ms");conn = JDBCDruidUtils.getConnection();//控制事务:默认不提交conn.setAutoCommit(false);String sql = "insert into ACT_RESULT_LOG (onlineseqid,businessid,becifno,ivisresult,createdby,createddate,updateby,updateddate,risklevel) values";sql += "(?,?,?,?,?,?,?,?,?)";ps = conn.prepareStatement(sql);//循环结果集:这里循环不支持"烂布袋"表达式for (int i = 0; i < dataList.size(); i++) {Map<Integer, String> item = dataList.get(i);ps.setString(1, item.get(0));ps.setString(2, item.get(1));ps.setString(3, item.get(2));ps.setString(4, item.get(3));ps.setString(5, item.get(4));ps.setTimestamp(6, new Timestamp(System.currentTimeMillis()));ps.setString(7, item.get(6));ps.setTimestamp(8, new Timestamp(System.currentTimeMillis()));ps.setString(9, item.get(8));//将一组参数添加到此 PreparedStatement 对象的批处理命令中。ps.addBatch();}//执行批处理ps.executeBatch();//手动提交事务conn.commit();long endTime = System.currentTimeMillis();System.out.println(dataList.size() + "条,结束导入到数据库时间:" + endTime + "ms");System.out.println(dataList.size() + "条,导入用时:" + (endTime - startTime) + "ms");result.put("success", "1111");} catch (Exception e) {result.put("exception", "0000");e.printStackTrace();} finally {//关连接JDBCDruidUtils.close(conn, ps);}return result;}

导出问题解决方案

问题:如果一次性查询数据库百万条数据会很慢

解决:

  • 首先在查询数据库层面,需要分批进行查询(我使用的是每次查询20w)
  • 每查询一次结束,就使用EasyExcel工具将这些数据写入一次
  • 当一个Sheet写满了100w条数据,开始将查询的数据写入到另一个Sheet中
  • 如此循环直到数据全部导出到Excel完毕

注意:

1、我们需要计算Sheet个数,以及循环写入次数。特别是最后一个Sheet的写入次数

因为你不知道最后一个Sheet选哟写入多少数据,可能是100w,也可能是25w因为我们这里的300w只是模拟数据,有可能导出的数据比300w多也可能少

2、我们需要计算写入次数,因为我们使用的分页查询,所以需要注意写入的次数。

其实查询数据库多少次就是写入多少次

核心代码:

//导出逻辑代码
public void dataExport300w(HttpServletResponse response) {{OutputStream outputStream = null;try {long startTime = System.currentTimeMillis();System.out.println("导出开始时间:" + startTime);outputStream = response.getOutputStream();ExcelWriter writer = new ExcelWriter(outputStream, ExcelTypeEnum.XLSX);String fileName = new String(("excel100w").getBytes(), "UTF-8");//titleTable table = new Table(1);List<List<String>> titles = new ArrayList<List<String>>();titles.add(Arrays.asList("onlineseqid"));titles.add(Arrays.asList("businessid"));titles.add(Arrays.asList("becifno"));titles.add(Arrays.asList("ivisresult"));titles.add(Arrays.asList("createdby"));titles.add(Arrays.asList("createddate"));titles.add(Arrays.asList("updateby"));titles.add(Arrays.asList("updateddate"));titles.add(Arrays.asList("risklevel"));table.setHead(titles);//模拟统计查询的数据数量这里模拟100wint count = 3000001;//记录总数:实际中需要根据查询条件进行统计即可Integer totalCount = actResultLogMapper.findActResultLogByCondations(count);//每一个Sheet存放100w条数据Integer sheetDataRows = ExcelConstants.PER_SHEET_ROW_COUNT;//每次写入的数据量20wInteger writeDataRows = ExcelConstants.PER_WRITE_ROW_COUNT;//计算需要的Sheet数量Integer sheetNum = totalCount % sheetDataRows == 0 ? (totalCount / sheetDataRows) : (totalCount / sheetDataRows + 1);//计算一般情况下每一个Sheet需要写入的次数(一般情况不包含最后一个sheet,因为最后一个sheet不确定会写入多少条数据)Integer oneSheetWriteCount = sheetDataRows / writeDataRows;//计算最后一个sheet需要写入的次数Integer lastSheetWriteCount = totalCount % sheetDataRows == 0 ? oneSheetWriteCount : (totalCount % sheetDataRows % writeDataRows == 0 ? (totalCount / sheetDataRows / writeDataRows) : (totalCount / sheetDataRows / writeDataRows + 1));//开始分批查询分次写入//注意这次的循环就需要进行嵌套循环了,外层循环是Sheet数目,内层循环是写入次数List<List<String>> dataList = new ArrayList<>();for (int i = 0; i < sheetNum; i++) {//创建SheetSheet sheet = new Sheet(i, 0);sheet.setSheetName("测试Sheet1" + i);//循环写入次数: j的自增条件是当不是最后一个Sheet的时候写入次数为正常的每个Sheet写入的次数,如果是最后一个就需要使用计算的次数lastSheetWriteCountfor (int j = 0; j < (i != sheetNum - 1 ? oneSheetWriteCount : lastSheetWriteCount); j++) {//集合复用,便于GC清理dataList.clear();//分页查询一次20wPageHelper.startPage(j + 1 + oneSheetWriteCount * i, writeDataRows);List<ActResultLog> reslultList = actResultLogMapper.findByPage100w();if (!CollectionUtils.isEmpty(reslultList)) {reslultList.forEach(item -> {dataList.add(Arrays.asList(item.getOnlineseqid(), item.getBusinessid(), item.getBecifno(), item.getIvisresult(), item.getCreatedby(), Calendar.getInstance().getTime().toString(), item.getUpdateby(), Calendar.getInstance().getTime().toString(), item.getRisklevel()));});}//写数据writer.write0(dataList, sheet, table);}}// 下载EXCELresponse.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName).getBytes("gb2312"), "ISO-8859-1") + ".xlsx");response.setContentType("multipart/form-data");response.setCharacterEncoding("utf-8");writer.finish();outputStream.flush();//导出时间结束long endTime = System.currentTimeMillis();System.out.println("导出结束时间:" + endTime + "ms");System.out.println("导出所用时间:" + (endTime - startTime) / 1000 + "秒");} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if (outputStream != null) {try {outputStream.close();} catch (Exception e) {e.printStackTrace();}}}}
}

导入导出的策略

以下几点建议,不管在面试的角度还是架构设计的角度都尽量要考虑到

定时导入导出

  1. 批量处理:定时任务通常处理大量数据,因此可以设计批量处理流程。例如,使用定时任务(如Cron)安排在低流量时段进行数据处理。

  2. 增量更新:避免每次全量导入或导出,使用增量更新策略,仅处理自上次操作以来发生变化的数据。

  3. 数据分片:将数据分成小块进行处理和存储,减少每次操作的负载。例如,按日期或记录ID范围分片处理。

  4. 异常处理和恢复:实现任务失败后的重试机制,并记录失败日志,确保任务能够从失败点继续执行。

  5. 性能优化:优化数据库查询和写入操作,例如使用批量插入或更新,提高导入导出的效率。

实时导入导出

  1. 流式处理:实时数据处理需要即刻反应,因此使用流式处理技术(如Kafka、RabbitMQ)来处理数据流,确保数据能即时处理。

  2. 数据缓存:使用缓存机制(如Redis)减少重复操作,提高响应速度,并减轻数据库负担。

  3. 实时数据同步:使用数据同步工具或技术(如CDC—Change Data Capture)来实现实时数据更新,将数据及时同步到目标系统。

  4. 负载均衡:实现系统负载均衡,确保在高流量情况下系统能够平稳运行,避免单点故障。

  5. 监控和报警:实时监控数据流动和处理状态,设立报警机制,及时响应系统异常或数据处理问题。

在数据量不超过1亿的情况下,Mysql和Oracle的性能其实相差不大,超过1亿,Oracle的各方面优势才会明显


EasyPOI

最后浅聊一下EasyPOI的一些内容,他最大的特点就是用起来简单

  1. 引入依赖
    将 EasyPOI 依赖添加到项目的 pom.xml 中(对于 Maven 项目):

    <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi</artifactId><version>5.0.1</version>
    </dependency>
    
  2. 定义实体类
    创建一个 Java 类来表示 Excel 中的数据结构,并使用 EasyPOI 注解进行配置。例如:

    import cn.afterturn.easypoi.excel.annotation.Excel;public class Person {@Excel(name = "Name")private String name;@Excel(name = "Age")private int age;// Getters and setters
    }
    
  3. 导出 Excel 文件
    使用 EasyPOI 导出 Excel 文件:

    import cn.afterturn.easypoi.excel.ExcelExportUtil;
    import cn.afterturn.easypoi.excel.entity.ExportParams;
    import org.apache.poi.ss.usermodel.Workbook;public class ExportExample {public static void main(String[] args) {List<Person> list = Arrays.asList(new Person("John", 30), new Person("Jane", 25));Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("Person List", "Sheet1"), Person.class, list);try (FileOutputStream fos = new FileOutputStream("person.xlsx")) {workbook.write(fos);} catch (IOException e) {e.printStackTrace();}}
    }
    
  4. 导入 Excel 文件
    使用 EasyPOI 导入 Excel 文件:

    import cn.afterturn.easypoi.excel.ExcelImportUtil;
    import cn.afterturn.easypoi.excel.entity.ImportParams;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.List;public class ImportExample {public static void main(String[] args) {ImportParams params = new ImportParams();params.setHeadRows(1);try (FileInputStream fis = new FileInputStream("person.xlsx")) {List<Person> list = ExcelImportUtil.importExcel(fis, Person.class, params);for (Person person : list) {System.out.println(person.getName() + ": " + person.getAge());}} catch (Exception e) {e.printStackTrace();}}
    }
    

小数据量的导入导出就可以酌情怎么方便怎么来

相关文章:

【JAVA】一篇聊透百万级数据导入导出场景问题、大数据处理策略及优化方案、EasyExcel 和 EasyPOI的玩法详解

文章目录 名词介绍场景问题分析解决导入问题解决方案内存溢出&#xff08;分批导入&#xff09;DB插入&#xff08;分批插入&#xff09; 导出问题解决方案 导入导出的策略定时导入导出实时导入导出 EasyPOI 更多相关内容可查看 玩之前先了解几个关键名词&#xff08;大佬可省略…...

2024年华为9月4日秋招笔试真题题解

2024年华为0904秋招笔试真题 二叉树消消乐好友推荐系统维修工力扣上类似的题--K站中转内最便宜的航班 二叉树消消乐 题目描述 给定原始二叉树和参照二叉树(输入的二叉树均为满二叉树&#xff0c;二叉树节点的值范围为[1,1000]&#xff0c;二叉树的深度不超过1000)&#xff0c…...

Next.js 14 App Router 预渲染 代码实践 静态页面渲染 SSG 服务端渲染代码 SSR

最近学习了Next.js 14框架&#xff0c;总结一下预渲染技术和具体代码用法&#xff0c;如果有理解不对的地方还请大佬指正。 注意以下内容只讨论App Router的新方案&#xff08;getStaticProps已经弃用&#xff09;。 1.简介 预渲染主要分为2种技术&#xff0c;静态页面渲染(…...

阿里云人工智能ACP错题整理.txt

1、TextRank是一种关键词抽取和文档摘要的排序算法&#xff0c;由谷歌的网页重要性排序算法PageRank算法改进而来&#xff0c;利用文本内部的词语间的语义便可以抽取关键词&#xff0c;它能够从一个给定的文本中抽取出该文本的关键词、关键词组&#xff0c;并使用抽取式的自动文…...

为 WebSocket 配置 Nginx 反向代理来支持 Uvicorn 的最佳实践

前景 要为WebSocket(以 ws:// 或 wss:// 协议)配置 Nginx 反向代理来代理 Uvicorn 服务器(或其他支持 WebSocket 的应用),需要确保 Nginx 和 Uvicorn 支持 WebSocket 连接,并做一些特定的配置。WebSocket 协议与 HTTP/HTTPS 不同,因此需要在 Nginx 中设置正确的代理头和…...

Centos7通过Docker安装openGauss5.0.2并配置用户供Navicat连接使用

下载镜像 [rootiZ2ze3qc9ouxm10ykn3cvdZ ~]# docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/enmotech/opengauss:5.0.2 5.0.2: Pulling from ddn-k8s/docker.io/enmotech/opengauss 2ec76a50fe7c: Pull complete e48b50219b49: Pull complete 512e203af4…...

生成树详细配置(STP、RSTP、MSTP)

目录 一. 实验内容 STP配置实验 RSTP配置实验 MSTP配置实验 二. 1 ) STP配置实验 实验拓扑 ​编辑 实验配置 实验结果 2 ) RSTP配置实验 实验拓扑 实验配置 实验结果 3 ) MSTP配置实验 实验拓扑 实验配置 ​编辑 实验结果 三 实验总结 一. 实验内容 1) …...

服务器环境搭建-5 Nexus搭建与使用介绍

背景 本文介绍nexus的安装、配置和使用&#xff0c;之后通过案例的方式演示使用过程。 1.下载和安装 本文使用Nexus 3.x版本进行演示 下载地址&#xff1a;Download Nexus Repository OSS | Sonatype 国外网站下载速度较慢&#xff0c;也可以通过百度网盘下载(提取码:9999): …...

将 Parallels Desktop(PD虚拟机)安装在移动硬盘上,有影响吗?

当我们谈论在移动硬盘上安装 Parallels Desktop&#xff08;简称PD虚拟机&#xff09;及其对性能的影响时&#xff0c;特别是在运行如Unigraphics这样的资源密集型软件时&#xff0c;用户需要在便携性与性能之间找到最佳平衡。本文将深入探讨PD虚拟机装在移动硬盘有影响吗&…...

PHP智能化云端培训考试系统小程序源码

智能化云端培训考试系统&#xff1a;重塑学习评估的未来 &#x1f31f; 引言&#xff1a;迈向智能教育的新时代 在这个日新月异的数字时代&#xff0c;教育也在经历着前所未有的变革。智能化云端培训考试系统的出现&#xff0c;正是这一变革的生动体现。它不仅打破了传统教育的…...

内幕!smardaten无代码平台全方位测评,这些细节你绝对想不到!

目录 一、引言二、测评要点2.1、前后端交互嵌套2.2、兼容性与可扩展性2.2.1、页面集成2.2.2、数据集成2.2.3、接口集成2.2.4、权限集成2.2.5、代码扩展支持 2.3、UI定制2.4、开发环境的隔离2.5、OEM定制2.6、多语言切换2.7、AI大模型能力 三、总结 一、引言 作为一枚IT从业者&…...

计算机专业的真正的就业情况

首先听到计算机行业&#xff0c;大多数人岗位已经饱和&#xff0c;前端已死&#xff0c;程序员35岁危机。但是事实上这些认知都是片面的&#xff0c;今天由我来为大家分析计算机行业的内幕。 疫情过后&#xff0c;过内各种行业都受到了冲击&#xff0c;你们敢说除了体制内的行业…...

Java对象列表属性映射工具类

背景 经常有这种情况&#xff0c;就是获取到一个对象列表之后&#xff0c;需要根据对象里某个字段的值去获取另一个字段的值。如下所示&#xff0c;有个Item对象列表&#xff0c;Item对象里有个id字段和Value字段&#xff0c;现需要根据id的值去查询value的值。 // 测试数据Li…...

.net core 通过Sqlsugar生成实体

通过替换字符串的方式生成代码&#xff0c;其他代码也可以通这种方式生成 直接上代码 设置模板 将这几个模板文件设置为&#xff1a;嵌入资源 模板内容&#xff1a; using SqlSugar;namespace {Namespace}.Domain.Admin.{ModelName}; /// <summary> /// {TableDisplay…...

ORCA-3D避障算法解析

二维ORCA原理参考&#xff1a; https://zhuanlan.zhihu.com/p/669426124 ORCA原理图解 1. 找到避障速度增量 u 碰撞处理分为三种情况&#xff1a; &#xff08;1&#xff09;没有发生碰撞&#xff0c;且相对速度落在小圆里 &#xff08;2&#xff09;没有发生碰撞&#xff0…...

CentOS 7停更官方yum源无法使用,更换阿里源

CentOS 7官方源已经停止维护&#xff0c;导致无法使用yum更新软件。通过尝试使用阿里云、清华大学等第三方源解决&#xff0c;现以阿里云第三方源进行配置&#xff1a; 1、备份原有的yum源配置文件 # cp -a /etc/yum.repos.d /etc/yum.repos.d.bak 2、删除原有的yum源配置文…...

Introduction结构

写好论文的**Introduction&#xff08;引言&#xff09;**部分是至关重要的&#xff0c;因为它为读者提供了背景信息&#xff0c;并引导他们进入论文的核心主题。一个优秀的引言应该具备以下几个关键要素&#xff1a; 1. 背景介绍 概述问题&#xff1a;首先&#xff0c;你需要…...

基于SpringBoot实现SpringMvc上传下载功能实现

SpringMvc上传下载功能实现 1.创建新的项目 1&#xff09;项目信息填写 Spring Initializr (单击选中)Name(填写项目名字)Language&#xff08;选择开发语言&#xff09;Type&#xff08;选择工具Maven&#xff09;Group&#xff08;&#xff09;JDK&#xff08;jdk选择17 &…...

vue 控制组件是否显示

在Vue中&#xff0c;控制组件的显示通常使用v-if、v-else-if、v-else或v-show指令。 1.v-if&#xff1a;条件性地渲染元素&#xff0c;如果条件为假&#xff0c;元素甚至不会被渲染到DOM中。 <template><div><MyComponent v-if"showMyComponent" /&…...

生产部门不给力?精益化生产管理咨询公司为您出谋划策

问题背景 近年来&#xff0c;许多企业的生产部门面临着各种挑战和困难。生产效率低下、产品质量不稳定、生产成本过高等问题频频出现&#xff0c;给企业的发展带来了困扰。面对这一现状&#xff0c;许多企业开始寻求专业的管理咨询公司的帮助&#xff0c;以期能够通过精益生产…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

向量几何的二元性:叉乘模长与内积投影的深层联系

在数学与物理的空间世界中&#xff0c;向量运算构成了理解几何结构的基石。叉乘&#xff08;外积&#xff09;与点积&#xff08;内积&#xff09;作为向量代数的两大支柱&#xff0c;表面上呈现出截然不同的几何意义与代数形式&#xff0c;却在深层次上揭示了向量间相互作用的…...

k8s从入门到放弃之Pod的容器探针检测

k8s从入门到放弃之Pod的容器探针检测 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;容器探测是指kubelet对容器执行定期诊断的过程&#xff0c;以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...

Copilot for Xcode (iOS的 AI辅助编程)

Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot&#xff0c;它能根据上下文补全代码&#xff0c;快速生成常用…...