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

EasyExcel快速导出 100W 数据

一. 简介

导出是后台管理系统的常用功能,当数据量特别大的时候会内存溢出和卡顿页面,曾经自己封装过一个导出,采用了分批查询数据来避免内存溢出和使用SXSSFWorkbook方式缓存数据到文件上以解决下载大文件EXCEL卡死页面的问题。

不过一是存在封装不太友好使用不方便的问题,二是这些poi的操作方式仍然存在内存占用过大的问题,三是存在空循环和整除的时候数据有缺陷的问题,以及存在内存溢出的隐患。

无意间查询到阿里开源的EasyExcel框架,发现可以将解析的EXCEL的内存占用控制在KB级别,并且绝对不会内存溢出(内部实现待研究),还有就是速度极快,大概100W条记录,十几个字段,只需要70秒即可完成下载。

遂抛弃自己封装的,转战研究阿里开源的EasyExcel. 不过 说实话,当时自己封装的那个还是有些技术含量的,例如:外观模式,模板方法模式,以及委托思想,组合思想,可以看看。另外,微信搜索关注Java技术栈,发送:设计模式,可以获取我整理的 Java 设计模式实战教程。

EasyExcel的github地址是:https://github.com/alibaba/easyexcel

二. 案例

2.1 POM依赖

<!-- 阿里开源EXCEL -->
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>1.1.1</version>
</dependency>

2.2 POJO对象

package com.authorization.privilege.excel;import java.util.Date;/*** @author qjwyss* @description*/
public class User {private String uid;private String name;private Integer age;private Date birthday;public User() {}public User(String uid, String name, Integer age, Date birthday) {this.uid = uid;this.name = name;this.age = age;this.birthday = birthday;}public String getUid() {return uid;}public void setUid(String uid) {this.uid = uid;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}
}

2.3 测试环境

2.3.1.数据量少的(20W以内吧):一个SHEET一次查询导出

如果数据量过大,不要用传统分页,利用where id> #{lastMaxId} order by id limit 100,解决分页慢的问题

/*** 针对较少的记录数(20W以内大概)可以调用该方法一次性查出然后写入到EXCEL的一个SHEET中* 注意: 一次性查询出来的记录数量不宜过大,不会内存溢出即可。** @throws IOException*/
@Test
public void writeExcelOneSheetOnceWrite() throws IOException {// 生成EXCEL并指定输出路径OutputStream out = new FileOutputStream("E:\\temp\\withoutHead1.xlsx");ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);// 设置SHEETSheet sheet = new Sheet(1, 0);sheet.setSheetName("sheet1");// 设置标题Table table = new Table(1);List<List<String>> titles = new ArrayList<List<String>>();titles.add(Arrays.asList("用户ID"));titles.add(Arrays.asList("名称"));titles.add(Arrays.asList("年龄"));titles.add(Arrays.asList("生日"));table.setHead(titles);// 查询数据导出即可 比如说一次性总共查询出100条数据List<List<String>> userList = new ArrayList<>();for (int i = 0; i < 100; i++) {userList.add(Arrays.asList("ID_" + i, "小明" + i, String.valueOf(i), new Date().toString()));}writer.write0(userList, sheet, table);writer.finish();
}

2.3.2.数据量适中(100W以内):一个SHEET分批查询导出

/*** 针对105W以内的记录数可以调用该方法分多批次查出然后写入到EXCEL的一个SHEET中* 注意:* 每次查询出来的记录数量不宜过大,根据内存大小设置合理的每次查询记录数,不会内存溢出即可。* 数据量不能超过一个SHEET存储的最大数据量105W** @throws IOException*/
@Test
public void writeExcelOneSheetMoreWrite() throws IOException {// 生成EXCEL并指定输出路径OutputStream out = new FileOutputStream("E:\\temp\\withoutHead2.xlsx");ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);// 设置SHEETSheet sheet = new Sheet(1, 0);sheet.setSheetName("sheet1");// 设置标题Table table = new Table(1);List<List<String>> titles = new ArrayList<List<String>>();titles.add(Arrays.asList("用户ID"));titles.add(Arrays.asList("名称"));titles.add(Arrays.asList("年龄"));titles.add(Arrays.asList("生日"));table.setHead(titles);// 模拟分批查询:总记录数50条,每次查询20条,  分三次查询 最后一次查询记录数是10Integer totalRowCount = 50;Integer pageSize = 20;Integer writeCount = totalRowCount % pageSize == 0 ? (totalRowCount / pageSize) : (totalRowCount / pageSize + 1);// 注: 此处仅仅为了模拟数据,实用环境不需要将最后一次分开,合成一个即可, 参数为:currentPage = i+1;  pageSize = pageSizefor (int i = 0; i < writeCount; i++) {// 前两次查询 每次查20条数据if (i < writeCount - 1) {List<List<String>> userList = new ArrayList<>();for (int j = 0; j < pageSize; j++) {userList.add(Arrays.asList("ID_" + Math.random(), "小明", String.valueOf(Math.random()), new Date().toString()));}writer.write0(userList, sheet, table);} else if (i == writeCount - 1) {// 最后一次查询 查多余的10条记录List<List<String>> userList = new ArrayList<>();Integer lastWriteRowCount = totalRowCount - (writeCount - 1) * pageSize;for (int j = 0; j < lastWriteRowCount; j++) {userList.add(Arrays.asList("ID_" + Math.random(), "小明", String.valueOf(Math.random()), new Date().toString()));}writer.write0(userList, sheet, table);}}writer.finish();
}

2.3.3.数据量很大(几百万都行):多个SHEET分批查询导出

/*** 针对几百万的记录数可以调用该方法分多批次查出然后写入到EXCEL的多个SHEET中* 注意:* perSheetRowCount % pageSize要能整除  为了简洁,非整除这块不做处理* 每次查询出来的记录数量不宜过大,根据内存大小设置合理的每次查询记录数,不会内存溢出即可。** @throws IOException*/
@Test
public void writeExcelMoreSheetMoreWrite() throws IOException {// 生成EXCEL并指定输出路径OutputStream out = new FileOutputStream("E:\\temp\\withoutHead3.xlsx");ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);// 设置SHEET名称String sheetName = "测试SHEET";// 设置标题Table table = new Table(1);List<List<String>> titles = new ArrayList<List<String>>();titles.add(Arrays.asList("用户ID"));titles.add(Arrays.asList("名称"));titles.add(Arrays.asList("年龄"));titles.add(Arrays.asList("生日"));table.setHead(titles);// 模拟分批查询:总记录数250条,每个SHEET存100条,每次查询20条  则生成3个SHEET,前俩个SHEET查询次数为5, 最后一个SHEET查询次数为3 最后一次写的记录数是10// 注:该版本为了较少数据判断的复杂度,暂时perSheetRowCount要能够整除pageSize, 不去做过多处理  合理分配查询数据量大小不会内存溢出即可。Integer totalRowCount = 250;Integer perSheetRowCount = 100;Integer pageSize = 20;Integer sheetCount = totalRowCount % perSheetRowCount == 0 ? (totalRowCount / perSheetRowCount) : (totalRowCount / perSheetRowCount + 1);Integer previousSheetWriteCount = perSheetRowCount / pageSize;Integer lastSheetWriteCount = totalRowCount % perSheetRowCount == 0 ?previousSheetWriteCount :(totalRowCount % perSheetRowCount % pageSize == 0 ? totalRowCount % perSheetRowCount / pageSize : (totalRowCount % perSheetRowCount / pageSize + 1));for (int i = 0; i < sheetCount; i++) {// 创建SHEETSheet sheet = new Sheet(i, 0);sheet.setSheetName(sheetName + i);if (i < sheetCount - 1) {// 前2个SHEET, 每个SHEET查5次 每次查20条 每个SHEET写满100行  2个SHEET合计200行  实用环境:参数:currentPage: j+1 + previousSheetWriteCount*i, pageSize: pageSizefor (int j = 0; j < previousSheetWriteCount; j++) {List<List<String>> userList = new ArrayList<>();for (int k = 0; k < 20; k++) {userList.add(Arrays.asList("ID_" + Math.random(), "小明", String.valueOf(Math.random()), new Date().toString()));}writer.write0(userList, sheet, table);}} else if (i == sheetCount - 1) {// 最后一个SHEET 实用环境不需要将最后一次分开,合成一个即可, 参数为:currentPage = i+1;  pageSize = pageSizefor (int j = 0; j < lastSheetWriteCount; j++) {// 前俩次查询 每次查询20条if (j < lastSheetWriteCount - 1) {List<List<String>> userList = new ArrayList<>();for (int k = 0; k < 20; k++) {userList.add(Arrays.asList("ID_" + Math.random(), "小明", String.valueOf(Math.random()), new Date().toString()));}writer.write0(userList, sheet, table);} else if (j == lastSheetWriteCount - 1) {// 最后一次查询 将剩余的10条查询出来List<List<String>> userList = new ArrayList<>();Integer lastWriteRowCount = totalRowCount - (sheetCount - 1) * perSheetRowCount - (lastSheetWriteCount - 1) * pageSize;for (int k = 0; k < lastWriteRowCount; k++) {userList.add(Arrays.asList("ID_" + Math.random(), "小明1", String.valueOf(Math.random()), new Date().toString()));}writer.write0(userList, sheet, table);}}}}writer.finish();
}

2.4 生产环境

2.4.0.Excel常量类

package com.authorization.privilege.constant;/*** @author qjwyss* @description EXCEL常量类*/
public class ExcelConstant {/*** 每个sheet存储的记录数 100W*/public static final Integer PER_SHEET_ROW_COUNT = 1000000;/*** 每次向EXCEL写入的记录数(查询每页数据大小) 20W*/public static final Integer PER_WRITE_ROW_COUNT = 200000;}
注:为了书写方便,此处俩个必须要整除,可以省去很多不必要的判断。另外如果自己测试,可以改为100,20。
分享给你: Spring Boot 学习笔记。

2.4.1.数据量少的(20W以内吧):一个SHEET一次查询导出

@Override
public ResultVO<Void> exportSysSystemExcel(SysSystemVO sysSystemVO, HttpServletResponse response) throws Exception {ServletOutputStream out = null;try {out = response.getOutputStream();ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);// 设置EXCEL名称String fileName = new String(("SystemExcel").getBytes(), "UTF-8");// 设置SHEET名称Sheet sheet = new Sheet(1, 0);sheet.setSheetName("系统列表sheet1");// 设置标题Table table = new Table(1);List<List<String>> titles = new ArrayList<List<String>>();titles.add(Arrays.asList("系统名称"));titles.add(Arrays.asList("系统标识"));titles.add(Arrays.asList("描述"));titles.add(Arrays.asList("状态"));titles.add(Arrays.asList("创建人"));titles.add(Arrays.asList("创建时间"));table.setHead(titles);// 查数据写EXCELList<List<String>> dataList = new ArrayList<>();List<SysSystemVO> sysSystemVOList = this.sysSystemReadMapper.selectSysSystemVOList(sysSystemVO);if (!CollectionUtils.isEmpty(sysSystemVOList)) {sysSystemVOList.forEach(eachSysSystemVO -> {dataList.add(Arrays.asList(eachSysSystemVO.getSystemName(),eachSysSystemVO.getSystemKey(),eachSysSystemVO.getDescription(),eachSysSystemVO.getState().toString(),eachSysSystemVO.getCreateUid(),eachSysSystemVO.getCreateTime().toString()));});}writer.write0(dataList, sheet, table);// 下载EXCELresponse.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName).getBytes("gb2312"), "ISO-8859-1") + ".xls");response.setContentType("multipart/form-data");response.setCharacterEncoding("utf-8");writer.finish();out.flush();} finally {if (out != null) {try {out.close();} catch (Exception e) {e.printStackTrace();}}}return ResultVO.getSuccess("导出系统列表EXCEL成功");
}

2.4.2.数据量适中(100W以内):一个SHEET分批查询导出

@Override
public ResultVO<Void> exportSysSystemExcel(SysSystemVO sysSystemVO, HttpServletResponse response) throws Exception {ServletOutputStream out = null;try {out = response.getOutputStream();ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);// 设置EXCEL名称String fileName = new String(("SystemExcel").getBytes(), "UTF-8");// 设置SHEET名称Sheet sheet = new Sheet(1, 0);sheet.setSheetName("系统列表sheet1");// 设置标题Table table = new Table(1);List<List<String>> titles = new ArrayList<List<String>>();titles.add(Arrays.asList("系统名称"));titles.add(Arrays.asList("系统标识"));titles.add(Arrays.asList("描述"));titles.add(Arrays.asList("状态"));titles.add(Arrays.asList("创建人"));titles.add(Arrays.asList("创建时间"));table.setHead(titles);// 查询总数并 【封装相关变量 这块直接拷贝就行 不要改动】Integer totalRowCount = this.sysSystemReadMapper.selectCountSysSystemVOList(sysSystemVO);Integer pageSize = ExcelConstant.PER_WRITE_ROW_COUNT;Integer writeCount = totalRowCount % pageSize == 0 ? (totalRowCount / pageSize) : (totalRowCount / pageSize + 1);// 写数据 这个i的最大值直接拷贝就行了 不要改for (int i = 0; i < writeCount; i++) {List<List<String>> dataList = new ArrayList<>();// 此处查询并封装数据即可 currentPage, pageSize这个变量封装好的 不要改动PageHelper.startPage(i + 1, pageSize);List<SysSystemVO> sysSystemVOList = this.sysSystemReadMapper.selectSysSystemVOList(sysSystemVO);if (!CollectionUtils.isEmpty(sysSystemVOList)) {sysSystemVOList.forEach(eachSysSystemVO -> {dataList.add(Arrays.asList(eachSysSystemVO.getSystemName(),eachSysSystemVO.getSystemKey(),eachSysSystemVO.getDescription(),eachSysSystemVO.getState().toString(),eachSysSystemVO.getCreateUid(),eachSysSystemVO.getCreateTime().toString()));});}writer.write0(dataList, sheet, table);}// 下载EXCELresponse.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName).getBytes("gb2312"), "ISO-8859-1") + ".xls");response.setContentType("multipart/form-data");response.setCharacterEncoding("utf-8");writer.finish();out.flush();} finally {if (out != null) {try {out.close();} catch (Exception e) {e.printStackTrace();}}}return ResultVO.getSuccess("导出系统列表EXCEL成功");
}

2.4.3.数据里很大(几百万都行):多个SHEET分批查询导出

@Override
public ResultVO<Void> exportSysSystemExcel(SysSystemVO sysSystemVO, HttpServletResponse response) throws Exception {ServletOutputStream out = null;try {out = response.getOutputStream();ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);// 设置EXCEL名称String fileName = new String(("SystemExcel").getBytes(), "UTF-8");// 设置SHEET名称String sheetName = "系统列表sheet";// 设置标题Table table = new Table(1);List<List<String>> titles = new ArrayList<List<String>>();titles.add(Arrays.asList("系统名称"));titles.add(Arrays.asList("系统标识"));titles.add(Arrays.asList("描述"));titles.add(Arrays.asList("状态"));titles.add(Arrays.asList("创建人"));titles.add(Arrays.asList("创建时间"));table.setHead(titles);// 查询总数并封装相关变量(这块直接拷贝就行了不要改)Integer totalRowCount = this.sysSystemReadMapper.selectCountSysSystemVOList(sysSystemVO);Integer perSheetRowCount = ExcelConstant.PER_SHEET_ROW_COUNT;Integer pageSize = ExcelConstant.PER_WRITE_ROW_COUNT;Integer sheetCount = totalRowCount % perSheetRowCount == 0 ? (totalRowCount / perSheetRowCount) : (totalRowCount / perSheetRowCount + 1);Integer previousSheetWriteCount = perSheetRowCount / pageSize;Integer lastSheetWriteCount = totalRowCount % perSheetRowCount == 0 ?previousSheetWriteCount :(totalRowCount % perSheetRowCount % pageSize == 0 ? totalRowCount % perSheetRowCount / pageSize : (totalRowCount % perSheetRowCount / pageSize + 1));for (int i = 0; i < sheetCount; i++) {// 创建SHEETSheet sheet = new Sheet(i, 0);sheet.setSheetName(sheetName + i);// 写数据 这个j的最大值判断直接拷贝就行了,不要改动for (int j = 0; j < (i != sheetCount - 1 ? previousSheetWriteCount : lastSheetWriteCount); j++) {List<List<String>> dataList = new ArrayList<>();// 此处查询并封装数据即可 currentPage, pageSize这俩个变量封装好的 不要改动PageHelper.startPage(j + 1 + previousSheetWriteCount * i, pageSize);List<SysSystemVO> sysSystemVOList = this.sysSystemReadMapper.selectSysSystemVOList(sysSystemVO);if (!CollectionUtils.isEmpty(sysSystemVOList)) {sysSystemVOList.forEach(eachSysSystemVO -> {dataList.add(Arrays.asList(eachSysSystemVO.getSystemName(),eachSysSystemVO.getSystemKey(),eachSysSystemVO.getDescription(),eachSysSystemVO.getState().toString(),eachSysSystemVO.getCreateUid(),eachSysSystemVO.getCreateTime().toString()));});}writer.write0(dataList, sheet, table);}}// 下载EXCELresponse.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName).getBytes("gb2312"), "ISO-8859-1") + ".xls");response.setContentType("multipart/form-data");response.setCharacterEncoding("utf-8");writer.finish();out.flush();} finally {if (out != null) {try {out.close();} catch (Exception e) {e.printStackTrace();}}}return ResultVO.getSuccess("导出系统列表EXCEL成功");
}

三、总结

造的假数据,100W条记录,18个字段,测试导出是70s。在实际上产环境使用的时候,具体的还是要看自己写的sql的性能。sql性能快的话,会很快。

有一点推荐一下:在做分页的时候使用单表查询, 对于所需要处理的外键对应的冗余字段,在外面一次性查出来放到map里面(推荐使用@MapKey注解),然后遍历list的时候根据外键从map中获取对应的名称。

一个宗旨:少发查询sql, 才能更快的导出。

题外话:如果数据量过大,不要用传统分页,利用where id> #{lastMaxId} order by id limit 100,解决分页慢的问题

相关文章:

EasyExcel快速导出 100W 数据

一. 简介 导出是后台管理系统的常用功能&#xff0c;当数据量特别大的时候会内存溢出和卡顿页面&#xff0c;曾经自己封装过一个导出&#xff0c;采用了分批查询数据来避免内存溢出和使用SXSSFWorkbook方式缓存数据到文件上以解决下载大文件EXCEL卡死页面的问题。 不过一是存…...

SpingBoot的项目实战--模拟电商【5.沙箱支付】

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringBoot电商项目的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一. 沙箱支付是什么 二.Sp…...

How to collect data

How to collect data 爬虫JavaPythonurllibrequestsBeautifulSoup 反爬虫信息校验型反爬虫动态渲染反爬虫文本混淆反爬虫特征识别反爬虫App反爬虫验证码 自动化测试工具SeleniumAppiumQMetry Automation StudioTestComplete RPA商业化产品艺赛旗影刀UIPath 开源产品Robot Frame…...

二刷Laravel 教程(用户注册)总结Ⅳ

一、显示用户信息 1&#xff09;resource Route::resource(users, UsersController); 相当于下面这7个路由 我们先用 Artisan 命令查看目前应用的路由&#xff1a; php artisan route:list 2&#xff09; compact 方法 //我们将用户对象 $user 通过 compact 方法转化为一个关联…...

跨国制造业组网方案解析,如何实现总部-分支稳定互联?

既要控制成本&#xff0c;又要稳定高效&#xff0c;可能吗&#xff1f; 在制造企业积极向“智造”发展、数字化转型的当下&#xff0c;物联网、人工智能、机器人等新型设备加入到生产、管理环节&#xff0c;为企业内部数据传输提出了更高的要求。而当企业规模扩大&#xff0c;数…...

网络的设置

一、网络设置 1.1查看linux基础的网络设置 网关 route -n ip地址ifconfigDNS服务器cat /etc/resolv.conf主机名hostname路由 route -n 网络连接状态ss 或者 netstat域名解析nslookup host 例题&#xff1a;除了ping&#xff0c;什么命令可以测试DNS服务器来解…...

CentOS常用命令

CentOS常用命令 1 背景知识1.1 Centos 简介1.2 centos 和ubuntu的区别1.3 安装centos的时候需要注意什么 2 常用命令集锦2.1 文件目录类&#xff1a;2.2 驱动挂载类&#xff1a;2.3 关机命令&#xff1a;2.4 查看系统信息命令&#xff1a;2.5 文本命令2.6 系统管理命令&#xf…...

Linux运维之切换到 root 用户

春花秋月何时了,往事知多少。此付费专栏不要订阅,不要订阅,听人劝。 🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 系列专栏目录 [Java项目实战] 介绍Java…...

【2024系统架构设计】 系统架构设计师第二版-层次式架构设计理论与实践

目录 一 表现层框架设计 二 中间层架构设计 三 数据访问层设计 四 数据架构规划与设计 五 物联网层次架构设计 六 层次式架构案例分析...

SpringSecurity的注解@PreAuthorize的失效问题

问题&#xff1a;测试响应式框架时&#xff0c;测试框架对于权限与角色的拦截问题&#xff0c;对于/delete的访问报错访问拒绝&#xff0c;但是数据里面配置了权限。 配置详情 原因&#xff1a;调用roles方法时源码会重新new一个list将authorities的数据覆盖&#xff0c;导致…...

k8s的集群调度

1、scheduler&#xff1a;负责调度资源&#xff0c;把pod调度到指定的node节点 &#xff08;1&#xff09;预算策略 &#xff08;2&#xff09;优先策略 2、List-watch &#xff08;1&#xff09;在k8s集群中&#xff0c;通过List-watch的机制进行每个组件的协作&#xff0…...

简单易懂的理解 PyTorch 中 Transformer 组件

目录 torch.nn子模块transformer详解 nn.Transformer Transformer 类描述 Transformer 类的功能和作用 Transformer 类的参数 forward 方法 参数 输出 示例代码 注意事项 nn.TransformerEncoder TransformerEncoder 类描述 TransformerEncoder 类的功能和作用 Tr…...

搭建Eureka服务注册中心

一、前言 我们在别的章节中已经详细讲解过eureka注册中心的作用&#xff0c;本节会简单讲解eureka作用&#xff0c;侧重注册中心的搭建。 Eureka作为服务注册中心可以进行服务注册和服务发现&#xff0c;注册在上面的服务可以到Eureka上进行服务实例的拉取&#xff0c;主要作用…...

【React】react-router-dom中的HashRouter和BrowserRouter实现原理

1. 前言 在之前整理BOM的五个对象时&#xff0c;提到&#xff1a; location.hash发生改变后&#xff0c;会触发hashchange事件&#xff0c;且history栈中会增加一条记录&#xff0c;但页面不会重新加载——实现HashRouter的关键history.pushState(state, , URL)执行后&#xf…...

生物信息学中的可重复性研究

科学就其本质而言&#xff0c;是累积渐进的。无论你是使用基于网络的还是基于命令行的工具&#xff0c;在进行研究时都应保证该研究可被其他研究人员重复。这有利于你的工作的累积与进展。在生物信息学领域&#xff0c;这意味着如下内容。 工作流应该有据可查。这可能包括在电脑…...

css-img图像同比缩小

1. HTML 中使图像按比例缩小 CSS 来控制图像的大小&#xff0c;并保持其宽高比 <!DOCTYPE html> <html> <head><style>.image-container {width: 300px; /* 设置容器宽度 */height: auto; /* 让高度自适应 */}.image-container img {width: 100%; /* …...

SpringBoot+Prometheus+Grafana搭建应用监控系统

1.应用监控系统介绍 SpringBoot的应用监控方案比较多&#xff0c;SpringBootPrometheusGrafana是比较常用的一种解决方案&#xff0c;主要的监控数据的处理逻辑如下&#xff1a; SpringBoot 的 actuator 提供了应用监控端点&#xff0c;可以对外暴露监控数据信息。Prometheu…...

QT c++和qml交互实例

文章目录 一、demo效果图二、c和qml交互的基本方式1、qml 调用 C 类对象2、C 类对象调用 qml3、qml 给 C 发送信号4、C 给 qml 发送信号 三、关键代码1、工程结构图2、c代码MainWindow.cppMainQuickView.cppStudentInfoView.cppStudentInfoModel.cpp 3、qml代码main.qmlMainQui…...

mysql基础-数据操作之增删改

目录 1.新增数据 1.1单条数据新增 1.2多条数据新增 1.3查询数据新增 2.更新 2.1单值更新 2.2多值更新 2.3批量更新 2.3.1 批量-单条件更新 2.3.2批量-多条件更新 2.4 插入或更新 2.5 联表更新 3.删除 本次分享一下数据库的DML操作语言。 操作表的数据结构&#xf…...

写字母(文件)

请编写函数&#xff0c;将大写字母写入文件中。 函数原型 void WriteLetter(FILE *f, int n);说明&#xff1a;参数 f 为文件指针&#xff0c;n 为字母数目(1 ≤ n ≤ 26)。函数将前 n 个大写英文字母写入 f 所指示的文件中。 裁判程序 #include <stdio.h> #include &…...

基于Jackson自定义json数据的对象转换器

1、问题说明 后端数据表定义的id主键是Long类型&#xff0c;一共有20多位。 前端在接收到后端返回的json数据时&#xff0c;Long类型会默认当做数值类型进行处理。但前端处理20多位的数值会造成精度丢失&#xff0c;于是导致前端查询数据出现问题。 测试前端Long类型的代码 …...

【Java】缓存击穿解决方案

文章目录 什么是SingleFlight&#xff1f;优化缺点优化策略 什么是SingleFlight&#xff1f; SingleFlight是go语言中sync包中的一个东西。它用于确保在并发环境下某个操作&#xff08;例如&#xff0c;函数调用&#xff09;即使被多个goroutine同时请求&#xff0c;也只会被执…...

【HarmonyOS】掌握 Stage 模型的核心概念与应用

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…...

2024年甘肃省职业院校技能大赛 “信息安全管理与评估”赛项样题卷①

2024年甘肃省职业院校技能大赛 高职学生组电子与信息大类信息安全管理与评估赛项样题 第一阶段&#xff1a;第二阶段&#xff1a;模块二 网络安全事件响应、数字取证调查、应用程序安全第二阶段 网络安全事件响应第一部分 网络安全事件响应第二部分 数字取证调查第三部分 应用程…...

我的AI之旅开始了

知道重要&#xff0c;但是就是不动。 今天告诉自己&#xff0c;必须开始学习了。 用这篇博文作为1月份AI学习之旅的起跑点吧。 从此&#xff0c;无惧AI&#xff0c;无惧编程。 AI之路就在脚下。 AI&#xff0c;在我理解&#xff0c;就是让机器变得更加智能&#…...

Day25 235二叉搜索树的公共祖先 701二叉搜索树插入 450二叉搜索树删除

235 二叉搜索树的最近公共祖先 如果利用普通二叉树的方法&#xff0c;就是利用后序遍历回溯从低向上搜索&#xff0c;遇到左子树有p&#xff0c;右子树有q&#xff0c;那么当前结点就是最近公共祖先。本题是二叉搜索树&#xff0c;所以说是有序的&#xff0c;一定能够简化上面…...

android系列-init 挂载文件系统

1.init 挂载文件系统 //android10\system\core\init\main.cppint main(int argc, char** argv) {return FirstStageMain(argc, argv); } //android10\system\core\init\first_stage_init.cppint FirstStageMain(int argc, char** argv) {CHECKCALL(mount("tmpfs",…...

Spring 七种事务传播性介绍

作者&#xff1a;vivo 互联网服务器团队 - Zhou Shaobin 本文主要介绍了Spring事务传播性的相关知识。 Spring中定义了7种事务传播性&#xff1a; PROPAGATION_REQUIRED PROPAGATION_SUPPORTS PROPAGATION_MANDATORY PROPAGATION_REQUIRES_NEW PROPAGATION_NOT_SUPPORTED…...

Count the Colors ZOJ - 1610

题目链接 题意&#xff1a; 给定n个区间[ l, r ]和颜色c, 每次给[l, r]涂上c这个颜色. 后面的涂色会覆盖之前的涂色. 最后要求输出区间[0, 8000]中每种颜色及其出现的次数, 如果该颜色没有出现过则不输出. 思路&#xff1a;典型的线段树区间染色问题&#xff0c;一般这种题…...

MATLAB点云处理总目录

一、点云滤波 原始点云包含过多噪点和冗余点&#xff0c;滤波和采样往往是点云预处理的必要步骤 1.滤波 重复点去除 NAN或INF无效点去除 自定义半径滤波 2.采样 基于空间格网的点云抽稀 随机下采样 均匀体素下采样 非均匀体素下采样 二、邻近搜索 如何组织点云快速获取当前…...

做电子外贸网站建设/sem是指什么

DataTable myDt dt;//删除列myDt.Columns.Remove("minArea");myDt.Columns.Remove("maxArea");//调整列顺序 &#xff0c;列排序从0开始myDt.Columns["num"].SetOrdinal(1);//修改列标题名称dt.Columns["num"].ColumnName "搜索…...

有哪些做软件的网站有哪些/市场营销毕业后做什么工作

本系列探寻AngularJS的路由机制&#xff0c;在WebStorm下开发。 AngularJS路由系列包括&#xff1a;1、AngularJS路由系列(1)--基本路由配置2、AngularJS路由系列(2)--刷新、查看路由,路由事件和URL格式&#xff0c;获取路由参数&#xff0c;路由的Resolve3、AngularJS路由系列…...

济宁市网站建设/网页制作流程

今天给大家带来这篇首页UI设计的文章,准备工作,给大家介绍一下需要用的几样工具,首先是微信小程序开发者工具,微信小程序开发文档.,LinUI组件安装包等.有了这几样工具,小程序的UI设计,就像搭积木一样方便.再加上自己个性化的设计.下面先看看我搭建微信小程序首页效果.小程序UI样…...

包头住房与城乡建设局网站/seo服务优化

C#概览 C#语言是微软于2000年发布&#xff0c;基于.NET Framewrok框架的、面向对象的高级语言。经过近十三年的发展&#xff0c;经历了5次大的升级&#xff0c;最新版本为C#5.0(对应于.NET Framework 4.5)&#xff0c;下面是C#语言发展过程的简单性总结&#xff1a;C#版本.NET …...

深圳网站建设 site/盘古百晋广告营销是干嘛

一般编程语言中喜欢用符号来判断java中两个字符串是否相等&#xff0c;例如c。c提供了操作符的重载&#xff0c;所以可以重载运算符来判断。 但是由于java中&#xff0c;没有提供运算符重载&#xff0c;而且java中没有提供基本的string类型、也没有把string看成char数组&#x…...

前端开发一个月多少钱/seo建站营销

转自&#xff1a;http://blog.csdn.net/helencoder/article/details/50328629 近期项目中&#xff0c;遇到数据表去重要求&#xff0c;对于ThinkPHP的去重有了更加准确的认识和体会。 两种去重方式&#xff1a; $test_data M(hot); //实例化数据表 $data $test_data->Di…...