easyexcel调用公共导出方法导出数据
easyexcel备忘
@Slf4j
public class ConditionDownloadUtil {//扫描在xboot 包下所有IService 接口的子类, 每次启动服务后, 重新扫描public final static Class[] classesExtendsIService = ClassUtil.scanPackageBySuper("cn.exrick.xboot", IService.class).toArray(new Class[1]);public static <T, E> void nonMultiQueryDownload(Class<T> clazz,QueryWrapper<T> queryWrapper,String excelName,Class<E> excelClazz,HttpServletResponse response) {if (ObjectUtils.isNotEmpty(clazz)) {//1. 根据入参中的class 来获取对应的IService BeanIService<T> targetIService = getTargetIService(clazz);/** 2. 由于查询/排序字段在每个模块中不同, 所以需要让调用方提供, 不再统一提供* 调用IService 的list() 方法获取查询符合条件的数据*/List<T> list = targetIService.list(queryWrapper);if (list == null || list.size() == 0) {throw ExceptionUtil.wrapRuntime("数据为空, 无法下载excel!");}//3. 将实体类List 转换为Excel 类ListList<E> excelList = list.stream().map(x -> BeanUtil.toBean(x, excelClazz, CopyOptions.create().setIgnoreError(true))).collect(Collectors.toList());//4. 调用EasyExcel 通用方法输出ExcelafterMultiQueryDownload(excelName, excelList, excelClazz, new CustomMergeStrategy(excelClazz, excelList.size()), response);} else {throw ExceptionUtil.wrapRuntime("实体类不能为空!");}}public static <E> void afterMultiQueryDownload(String excelName,List<E> excelList,Class<E> excelClass,WriteHandler writeHandler,HttpServletResponse response) {//1. 判断需要输入的Excel List 是否为空, 如果不为空, 则输入, 否则, 抛出异常if (CollectionUtil.isNotEmpty(excelList)) {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename=" + URLUtil.encode(excelName, StandardCharsets.UTF_8) + ".xlsx");//2. 输入Exceltry {ExcelWriterSheetBuilder excelWriterSheetBuilder = EasyExcel.write(response.getOutputStream()).excelType(ExcelTypeEnum.XLSX).head(excelClass).sheet();if (ObjectUtil.isNotEmpty(writeHandler)) {excelWriterSheetBuilder.registerWriteHandler(writeHandler);}//3. 清除Convertor 中的线程变量DictConverter.removeThreadLocal();excelWriterSheetBuilder.doWrite(excelList);} catch (Exception e) {StringWriter sw = new StringWriter();PrintWriter pw = new PrintWriter(sw);e.printStackTrace(pw);log.error(sw.toString());if (e.getCause() instanceof ExcelDataConvertException) {ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) e.getCause();String cellMsg = "";CellData cellData = excelDataConvertException.getCellData();//这里有一个celldatatype的枚举值,用来判断CellData的数据类型CellDataTypeEnum type = cellData.getType();if (type.equals(CellDataTypeEnum.NUMBER)) {cellMsg = cellData.getNumberValue().toString();} else if (type.equals(CellDataTypeEnum.STRING)) {cellMsg = cellData.getStringValue();} else if (type.equals(CellDataTypeEnum.BOOLEAN)) {cellMsg = cellData.getBooleanValue().toString();}String errorMsg = String.format("excel表格:第%s行,第%s列,数据值为:%s,该数据值不符合要求,请检验后重新导入!<span style=\"color:red\">请检查其他的记录是否有同类型的错误!</span>", excelDataConvertException.getRowIndex() + 1, excelDataConvertException.getColumnIndex(), cellMsg);log.error(errorMsg);}}} else {throw ExceptionUtil.wrapRuntime("数据为空, 无法下载excel!");}}public <T, E> void dynamicHeadDownload(List<List<String>> headList,String excelName,List data,HttpServletResponse response) {//1. 判断Head List 是否为空, 如果不为空, 则输入, 否则, 抛出异常if (ObjectUtil.isNotEmpty(headList)) {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename=" + excelName + ".xlsx");//2. 输入Exceltry {EasyExcel.write(response.getOutputStream()).head(headList).sheet().doWrite(data);} catch (Exception e) {StringWriter sw = new StringWriter();PrintWriter pw = new PrintWriter(sw);e.printStackTrace(pw);log.error(sw.toString());if (e.getCause() instanceof ExcelDataConvertException) {ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) e.getCause();String cellMsg = "";CellData cellData = excelDataConvertException.getCellData();//这里有一个celldatatype的枚举值,用来判断CellData的数据类型CellDataTypeEnum type = cellData.getType();if (type.equals(CellDataTypeEnum.NUMBER)) {cellMsg = cellData.getNumberValue().toString();} else if (type.equals(CellDataTypeEnum.STRING)) {cellMsg = cellData.getStringValue();} else if (type.equals(CellDataTypeEnum.BOOLEAN)) {cellMsg = cellData.getBooleanValue().toString();}String errorMsg = String.format("excel表格:第%s行,第%s列,数据值为:%s,该数据值不符合要求,请检验后重新导入!<span style=\"color:red\">请检查其他的记录是否有同类型的错误!</span>", excelDataConvertException.getRowIndex() + 1, excelDataConvertException.getColumnIndex(), cellMsg);log.error(errorMsg);}}} else {throw new RuntimeException("数据为空, 无法下载excel!");}}/*** 添加表头* @param head* @param headers*/public static void addHead(String head, List<List<String>> headers) {ArrayList<String> list = new ArrayList<>(1);list.add(head);headers.add(list);}/*@SneakyThrowspublic void tablesDownload(ReportDownloadModel reportDownloadModel, HttpServletResponse response) {String excelName = URLEncoder.encode(reportDownloadModel.getExcelName(), "utf-8");List<ReportTableModel> tableList = reportDownloadModel.getTables();response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename=" + excelName + ".xlsx");ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();WriteSheet writeSheet = EasyExcel.writerSheet().registerWriteHandler(new CustomCellWriteHandler()).registerWriteHandler(new CustomCellWriteHeightConfig()).needHead(Boolean.TRUE).build();//1. 定义标题二维数组ArrayList<List<String>> titleHead = new ArrayList<>();//2. 定义最终输出的excel 二维数组ArrayList<List<Object>> finalData = new ArrayList<>();//3. 定义空行ArrayList<Object> emptyLine = new ArrayList<>();emptyLine.add("");try {for (int i = 0; i < tableList.size() * 2; i = i + 2) {ReportTableModel reportTableModel = tableList.get(i / 2);List<List<String>> heads = reportTableModel.getHeads();List<List<Object>> data = reportTableModel.getData();String title = reportTableModel.getTitle();//3. 定义表名行ArrayList<String> titleLine = new ArrayList<>();titleLine.add(title);titleHead.add(titleLine);for (int j = 0; j < heads.size() - 1; j++) {ArrayList<String> empty = new ArrayList<>();empty.add("");titleHead.add(empty);}WriteTable writeTableForTitle = EasyExcel.writerTable(i).needHead(Boolean.TRUE).head(titleHead).build();excelWriter.write(null, writeSheet, writeTableForTitle);//4. 在表数据后添加空行finalData.addAll(data);finalData.add(emptyLine);WriteTable writeTableForData = EasyExcel.writerTable(i + 1).needHead(Boolean.TRUE).head(heads).build();excelWriter.write(finalData, writeSheet, writeTableForData);titleHead.clear();finalData.clear();}} catch (Exception e) {throw new RuntimeException("导出Excel 失败, 原因:" + e.getMessage());} finally {if (excelWriter != null) {excelWriter.finish();}}}*//*** 根据入参的类, 查找IService 中第一个泛型类型为入参类型的IService Bean* @param referenceType* @return*/private static <T> IService<T> getTargetIService(Class<T> referenceType) {Class targetClass = Arrays.stream(classesExtendsIService).filter(classExtendsIService -> ClassUtil.getTypeArgument(classExtendsIService).equals(referenceType)).findFirst().orElseThrow(() -> ExceptionUtil.wrapRuntime("没有对应的类!"));return (IService<T>) SpringUtil.getBean(targetClass);}}
public class CustomMergeStrategy implements RowWriteHandler {/*** 主键下标*/private Integer pkIndex;/*** 需要合并的列的下标集合*/private List<Integer> needMergeColumnIndex = new ArrayList<>();/*** DTO数据类型*/private Class<?> elementType;private Integer total;public CustomMergeStrategy(Class<?> elementType, Integer total) {this.elementType = elementType;this.total = total;}@Overridepublic void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {// 如果是标题,则直接返回if (isHead) {return;}// 获取当前sheetSheet sheet = writeSheetHolder.getSheet();if (null == pkIndex) {this.lazyInit(writeSheetHolder);}// 判断是否需要和上一行进行合并// 不能和标题合并,只能数据行之间合并if (row.getRowNum() <= 1) {return;}// 获取上一行数据Row lastRow = sheet.getRow(row.getRowNum() - 1);// 将本行和上一行是同一类型的数据(通过主键字段进行判断),则需要合并if (!lastRow.getCell(pkIndex).getStringCellValue().equalsIgnoreCase(row.getCell(pkIndex).getStringCellValue())|| row.getRowNum() == total) {int maxRow = sheet.getMergedRegions().stream().max(Comparator.comparingInt(CellRangeAddressBase::getLastRow)).orElse(new CellRangeAddress(0, 0, 0, 0)).getLastRow();needMergeColumnIndex.forEach(needMerIndex -> {int rowStart = maxRow + 1;int rowEnd = row.getRowNum() == total ? row.getRowNum() : row.getRowNum() - 1;if (rowEnd > rowStart) {sheet.addMergedRegionUnsafe(new CellRangeAddress(rowStart,rowEnd,needMerIndex,needMerIndex));}});}}/*** 初始化主键下标和需要合并字段的下标*/private void lazyInit(WriteSheetHolder writeSheetHolder) {// 获取当前sheetSheet sheet = writeSheetHolder.getSheet();// 获取标题行Row titleRow = sheet.getRow(0);// 获取DTO的类型Class<?> eleType = this.elementType;// 获取DTO所有的属性Field[] fields = eleType.getDeclaredFields();// 遍历所有的字段,因为是基于DTO的字段来构建excel,所以字段数 >= excel的列数Arrays.stream(fields).forEach(field -> {// 获取@ExcelProperty注解,用于获取该字段对应在excel中的列的下标ExcelProperty easyExcelAnno = field.getAnnotation(ExcelProperty.class);// 为空,则表示该字段不需要导入到excel,直接处理下一个字段if (null == easyExcelAnno) {return;}// 获取自定义的注解,用于合并单元格CustomMerge customMerge = field.getAnnotation(CustomMerge.class);// 没有@CustomMerge注解的默认不合并if (null == customMerge) {return;}for (int index = 0; index < fields.length; index++) {Cell theCell = titleRow.getCell(index);// 当配置为不需要导出时,返回的为null,这里作一下判断,防止NPEif (null == theCell) {continue;}// 将字段和excel的表头匹配上if (easyExcelAnno.value()[0].equalsIgnoreCase(theCell.getStringCellValue())) {if (customMerge.isPk()) {pkIndex = index;}if (customMerge.needMerge()) {needMergeColumnIndex.add(index);}}}});// 没有指定主键,则异常if (null == this.pkIndex) {throw new IllegalStateException("使用@CustomMerge注解必须指定主键");}}}
@Data
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER, verticalAlignment = VerticalAlignmentEnum.CENTER, wrapped = BooleanEnum.TRUE)
public class RiskAnnualExcel implements Serializable {@ExcelProperty("风险编号")@CustomMerge(needMerge = true, isPk = true)@ColumnWidth(15)@NotNullprivate String number;@ExcelProperty(value = "风险类别", converter = DictConverter.class)@DictType("risk-type")@CustomMerge(needMerge = true)@ColumnWidth(15)@NotNullprivate String type;@ExcelProperty("风险名称")@CustomMerge(needMerge = true)@ColumnWidth(15)@NotNullprivate String name;@ExcelProperty("风险描述")@CustomMerge(needMerge = true)@ColumnWidth(30)@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT, verticalAlignment = VerticalAlignmentEnum.CENTER, wrapped = BooleanEnum.TRUE)@NotNullprivate String description;@ExcelProperty("可能造成的后果")@CustomMerge(needMerge = true)@ColumnWidth(15)@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT, verticalAlignment = VerticalAlignmentEnum.CENTER, wrapped = BooleanEnum.TRUE)@NotNullprivate String consequence;@ExcelProperty(value = "风险等级", converter = DictConverter.class)@DictType("risk-level-for-company")@CustomMerge(needMerge = true)@ColumnWidth(15)@NotNullprivate String level;@ExcelProperty(value = "风险性质", converter = DictConverter.class)@DictType("risk-character")@CustomMerge(needMerge = true)@ColumnWidth(15)@NotNullprivate String character;@ExcelProperty(value = "风险主要防控措施")@ColumnWidth(80)@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT, verticalAlignment = VerticalAlignmentEnum.CENTER, wrapped = BooleanEnum.TRUE)@NotNullprivate String precaution;@ExcelProperty(value = "措施等级", converter = DictConverter.class)@DictType("risk-precaution-level")@ColumnWidth(15)@NotNullprivate String precautionLevel;@ExcelProperty("风险认领领导")@ColumnWidth(20)private String leaders;@ExcelProperty("管控部门")@ColumnWidth(20)@NotNullprivate String deptsResponsible;@ExcelProperty("风险涉及单位")@ColumnWidth(20)private String deptsInvolved;@ExcelProperty("措施类型")@ColumnWidth(15)@NotNullprivate String typeMeasures;@ExcelProperty("措施类别")@ColumnWidth(15)@NotNullprivate String categoryMeasures;@ExcelProperty("预警条件")@CustomMerge(needMerge = true)@ColumnWidth(15)@NotNullprivate String warningConditions;@ExcelProperty("风险点")@CustomMerge(needMerge = true)@ColumnWidth(15)@NotNullprivate String riskPoints;@ExcelProperty("应急措施")@CustomMerge(needMerge = true)@ColumnWidth(15)@NotNullprivate String emergencyMeasure;@ExcelProperty("备注")@CustomMerge(needMerge = true)@ColumnWidth(15)private String remark;}
调用公共导出方法导出数据
ConditionDownloadUtil.
afterMultiQueryDownload(riskBankAnnual.getName(),excelList, RiskAnnualExcel.class, new CustomMergeStrategy(RiskAnnualExcel.class,excelList.size()), httpServletResponse);
相关文章:
easyexcel调用公共导出方法导出数据
easyexcel备忘 Slf4j public class ConditionDownloadUtil {//扫描在xboot 包下所有IService 接口的子类, 每次启动服务后, 重新扫描public final static Class[] classesExtendsIService ClassUtil.scanPackageBySuper("cn.exrick.xboot", IService.class).toArra…...

C语言插入排序算法及代码
一、原理 在待排序的数组里,从数组的第二个数字开始,通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。 二、代码部分 #include<stdio.h> #include<stdlib.h> int ma…...

2023年中国法拍房用户画像和数据分析
法拍房主要平台 法拍房主要平台有3家,分别是阿里、京东和北交互联平台。目前官方认定纳入网络司法拍卖的平台共有7家,其中阿里资产司法拍卖平台的挂拍量最大。 阿里法拍房 阿里法拍房数据显示2017年,全国法拍房9000套;2018年&a…...
Android 清除临时文件,清空缓存
python 代码: import os import shutil import tracebackdef delete_folder(path):if os.path.exists(path):print(f"删除文件夹: {path}")shutil.rmtree(path)print("删除完成")def delete_file(path):if os.path.exists(path):print(f"删…...

Guava限流神器:RateLimiter使用指南
1. 引言 可能有些小伙伴听到“限流”这个词就觉得头大,感觉像是一个既复杂又枯燥的话题。别急,小黑今天就要用轻松易懂的方式,带咱们一探RateLimiter的究竟。 想象一下,当你去超市排队结账时,如果收银台开得越多&…...

【六大排序详解】开篇 :插入排序 与 希尔排序
插入排序 与 希尔排序 六大排序之二 插入排序 与 希尔排序1 排序1.1排序的概念 2 插入排序2.1 插入排序原理2.2 排序步骤2.3 代码实现 3 希尔排序3.1 希尔排序原理3.2 排序步骤3.3 代码实现 4 时间复杂度分析 Thanks♪(・ω・)ノ下一篇文章见&am…...
凸优化问题求解
这里写目录标题 1. 线性规划基本定理2.单纯形法2.1 转轴运算 3. 内点法3.1 线性规划的内点法 1. 线性规划基本定理 首先我们指出,线性规划均可等价地化成如下标准形式 { min c T x , s . t A x b , x ⪰ 0 , \begin{align}\begin{cases}\min~c^Tx,\\\mathrm{s.…...

文件操作入门指南
目录 一、为什么使用文件 二、什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 三、文件的打开和关闭 3.1 文件指针 3.2 文件的打开和关闭 四、文件的顺序读写 编辑 🌻深入理解 “流”: 🍂文件的顺序读写函数介绍: …...

Axure之交互与情节与一些实例
目录 一.交互与情节简介 二.ERP登录页到主页的跳转 三.ERP的菜单跳转到各个页面的跳转 四.省市联动 五.手机下拉加载 今天就到这里了,希望帮到你哦!!! 一.交互与情节简介 "交互"通常指的是人与人、人与计算机或物体…...
【数据库设计和SQL基础语法】--连接与联接--多表查询与子查询基础(二)
一、子查询基础 1.1 子查询概述 子查询是指在一个查询语句内部嵌套另一个查询语句的过程。子查询可以嵌套在 SELECT、FROM、WHERE 或 HAVING 子句中,用于从数据库中检索数据或执行其他操作。子查询通常返回一个结果集,该结果集可以被包含它的主查询使用…...

Android studio中导入opencv库
具体opencv库的导入流程参考链接:Android Studio开发之路 (五)导入OpenCV以及报错解决 一、出现的错误:NullPointerException: Cannot invoke “java.io.File.toPath()” because “this.mySdkLocation” is null 解决办法&#…...
Linux(1)_基础知识
第一部分 一、Linux系统概述 创始人:芬兰大学大一的学生写的Linux内核,李纳斯托瓦兹。 Linux时unix的类系统; 特点:多用户 多线程的操作系统; 开源操作系统; 开源项目:操作系统,应用…...
网络相关面试题
简述 TCP 连接的过程(淘系) 参考答案: TCP 协议通过三次握手建立可靠的点对点连接,具体过程是: 首先服务器进入监听状态,然后即可处理连接 第一次握手:建立连接时,客户端发送 syn 包…...
Vue2面试题:说一下对跨域的理解?
http请求分为两大类:普通http请求(如百度请求)和ajax请求(跨域是出现在ajax请求) 同源策略:在浏览器发起ajax请求时,当前的网址和被请求的网址协议、域名、端口号必须完全一致,目的是…...

Axure中如何使用交互样式交互事件交互动作情形
🎬 艳艳耶✌️:个人主页 🔥 个人专栏 :《产品经理如何画泳道图&流程图》 ⛺️ 越努力 ,越幸运 目录 一、Axure中交互样式 1、什么是交互样式? 2、交互样式的作用? 3、Axure中如何…...
1112. 迷宫(DFS之连通性模型)
1112. 迷宫 - AcWing题库 一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由 n∗n 的格点组成,每个格点只有2种状态,.和#,前者表示可以通行后者表示不能通行。 同时当Extense处在某个格点时,他只…...

飞天使-k8s知识点1-kubernetes架构简述
文章目录 名词功能要点 k8s核心要素CNCF 云原生框架简介k8s组建介绍 名词 CI 持续集成, 自动化构建和测试:通过使用自动化构建工具和自动化测试套件,持续集成可以帮助开发人员自动构建和测试他们的代码。这样可以快速检测到潜在的问题,并及早…...
linux中deadline调度原理与代码注释
简介 deadline调度是比rt调度更高优先级的调度,它没有依赖于优先级的概念,而是给了每个实时任务一定的调度时间,这样的好处是:使多个实时任务场景的时间分配更合理,不让一些实时任务因为优先级低而饿死。deadline调度…...
jquery、vue、uni-app、小程序的页面传参方式
jQuery、Vue、Uni-app 和小程序(例如微信小程序)都有它们自己的页面传参方式。下面分别介绍这几种方式的页面传参方式: jQuery: 在jQuery中,页面传参通常是通过URL的查询参数来实现的。例如: <a href"page2…...

ModuleNotFoundError: No module named ‘openai.error‘
ModuleNotFoundError: No module named ‘openai.error’ result self.fn(*self.args, **self.kwargs) File “H:\chatGPTWeb\chatgpt-on-wechat\channel\chat_channel.py”, line 168, in _handle reply self._generate_reply(context) File “H:\chatGPTWeb\chatgpt-on-wec…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...