easyExcel - 按模板导出

目录

  • 前言
  • 一、情景介绍
  • 二、文档介绍
    • 2.1 读取模板
    • 2.2 填充模板
  • 三、代码示例
    • 3.1 案例一:工资表
    • 3.2 案例二:报价单
  • 四、我所遇到的问题


前言

Java-easyExcel入门教程:https://blog.csdn.net/xhmico/article/details/134714025

之前有介绍过如何使用 easyExcel,以及写了两个入门的 demo ,这两个 demo 能应付在开发中大多数的导入和导出需求,不过有时候面对一些复杂的表格,就会有点不够用,该篇是如何使用模板实现导出功能


一、情景介绍

在实际的开发过程中可能会遇到需要导出一些带有复杂表头的表格,比如:工资表和考勤表

在这里插入图片描述

在这里插入图片描述

或者是类似于发票、报价单这种具有模板性质的表格

在这里插入图片描述

在这里插入图片描述

如果仅仅通过代码去实现是比较困难的,通常情况下会写一个模板 excel,模板中的需要变动的数据用占位符替代,导出的文件按照该模板填充数据


二、文档介绍

easyexcel 也提供了根据模板写入的功能,可以用较为简单的方式实现上述功能,其基本步骤为:

  • ① 读取模板文件
  • ② 填充模板中的占位符

2.1 读取模板

官方文档:根据模板写入

在这里插入图片描述

在官方文档中给出了如何使用 easyexcel 读取模板的代码示例:

官网代码示例:

    /*** 根据模板写入* <p>1. 创建excel对应的实体对象 参照{@link IndexData}* <p>2. 使用{@link ExcelProperty}注解指定写入的列* <p>3. 使用withTemplate 写取模板* <p>4. 直接写即可*/@Testpublic void templateWrite() {String templateFileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";String fileName = TestFileUtil.getPath() + "templateWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 这里要注意 withTemplate 的模板文件会全量存储在内存里面,所以尽量不要用于追加文件,如果文件模板文件过大会OOM// 如果要再文件中追加(无法在一个线程里面处理,可以在一个线程的建议参照多次写入的demo) 建议临时存储到数据库 或者 磁盘缓存(ehcache) 然后再一次性写入EasyExcel.write(fileName, DemoData.class).withTemplate(templateFileName).sheet().doWrite(data());}

从上述示例代码中可以看到读取模板文件的方法为:withTemplate()

    public ExcelWriterBuilder withTemplate(InputStream templateInputStream) {this.writeWorkbook.setTemplateInputStream(templateInputStream);return this;}public ExcelWriterBuilder withTemplate(File templateFile) {this.writeWorkbook.setTemplateFile(templateFile);return this;}public ExcelWriterBuilder withTemplate(String pathName) {return this.withTemplate(new File(pathName));}

2.2 填充模板

官方文档:填充Excel

注意:这里建议先去看下官方文档中给的示例,会比较好理解

在这里插入图片描述

  • 在模板中占位符用 {变量} 表示,比如 {name}{age}
    在这里插入图片描述
  • 如果占位符为列表,则使用 {.变量} 表示,比如:{.name}{.age}
    在这里插入图片描述

进行填充的方法为:fill()

    public ExcelWriter fill(Object data, WriteSheet writeSheet) {return this.fill((Object)data, (FillConfig)null, writeSheet);}public ExcelWriter fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) {this.excelBuilder.fill(data, fillConfig, writeSheet);return this;}public ExcelWriter fill(Supplier<Object> supplier, WriteSheet writeSheet) {return this.fill((Object)supplier.get(), (FillConfig)null, writeSheet);}public ExcelWriter fill(Supplier<Object> supplier, FillConfig fillConfig, WriteSheet writeSheet) {this.excelBuilder.fill(supplier.get(), fillConfig, writeSheet);return this;}

EasyExcel 中,FillConfig 类用于配置单元格填充相关的设置。

以下是一些 FillConfig 类中常用的配置项:

  • forceNewRow:是否强制写入到新行。当设置为 true 时,每次写入都会创建新的行,而不是在现有行上进行覆盖
  • direction:填充方向,可以指定是水平填充还是垂直填充
    • 属性:
      • WriteDirectionEnum.VERTICAL:垂直填充
      • WriteDirectionEnum.HORIZONTAL:水平填充

如果有多列组合填充的情况,通过 {前缀.变量} 的形式区分不同的列表,例如

使用 FillWrapper 构建 Excel 写入时的填充模板

			...excelWriter.fill(new FillWrapper("data1", data()), writeSheet);excelWriter.fill(new FillWrapper("data2", data()), writeSheet);excelWriter.fill(new FillWrapper("data3", data()), writeSheet);...

三、代码示例

简单介绍了 easyexcel 如何使用模板进行导出,接下来就通过几个简单的案例进行演示

以下案例使用的模板文件均可在文章顶部下载


3.1 案例一:工资表

编写 excel 模板:

在这里插入图片描述

实体类:

StaffSalaryEntity.java

import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StaffSalaryEntity {@ApiModelProperty(value = "姓名")private String name;@ApiModelProperty(value = "职称")private String post;@ApiModelProperty(value = "月薪")private BigDecimal mouthSalary;@ApiModelProperty(value = "时薪")private BigDecimal hourSalary;@ApiModelProperty(value = "应出勤天数")private Double shouldAttend;@ApiModelProperty(value = "出勤天数")private Double actualAttend;@ApiModelProperty(value = "平时加班时数")private Double overtime;@ApiModelProperty(value = "周末加班时数")private Double weekOvertime;@ApiModelProperty(value = "国假天数")private Double holiday;@ApiModelProperty(value = "正班薪资")private BigDecimal normalSalary;@ApiModelProperty(value = "平时加班薪资")private BigDecimal overtimeSalary;@ApiModelProperty(value = "周末加班薪资")private BigDecimal weekOvertimeSalary;@ApiModelProperty(value = "国假薪资")private BigDecimal holidaySalary;@ApiModelProperty(value = "岗位津贴")private BigDecimal postSubsidy;@ApiModelProperty(value = "全勤补贴")private BigDecimal fullAttendSubsidy;@ApiModelProperty(value = "全勤奖")private BigDecimal award;@ApiModelProperty(value = "事假缺勤扣款")private BigDecimal deduction;@ApiModelProperty(value = "社保费用")private BigDecimal social;@ApiModelProperty(value = "应得薪资")private BigDecimal shouldSalary;@ApiModelProperty(value = "个人扣税")private BigDecimal selfTax;@ApiModelProperty(value = "实发薪资")private BigDecimal actualSalary;@ApiModelProperty(value = "员工签名")private BigDecimal sign;
}

实体类中的字段要跟模板中占位符中的变量对应

代码示例:

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.mike.server.system.domain.excel.ProductOfferExcelEntity;
import com.mike.server.system.entity.StaffSalaryEntity;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;public class TestDemo {/*** 案例一:工资表*/@Testpublic void salaryList() {// 模板文件路径String templateFilePath = "D:\\excel-files\\gzb-template.xlsx";// 输出文件路径String outFilePath = "D:\\excel-files\\gzb.xlsx";// 创建 ExcelWriter 实例ExcelWriter writer = EasyExcel// 写入到.write(outFilePath)// 指定模板.withTemplate(templateFilePath).build();WriteSheet sheet = EasyExcel.writerSheet().build();// 获取员工工资数据List<StaffSalaryEntity> staffSalaryEntities = getStaffSalaryEntities();FillConfig fillConfig = FillConfig.builder()// 开启填充换行.forceNewRow(true).build();// 执行填充操作writer.fill(staffSalaryEntities, fillConfig, sheet);// 结束writer.finish();}public List<StaffSalaryEntity> getStaffSalaryEntities() {List<StaffSalaryEntity> list = new ArrayList<>();list.add(StaffSalaryEntity.builder().name("米大傻").post("开发").mouthSalary(new BigDecimal(1320)).hourSalary(new BigDecimal("7.59")).shouldAttend(21.0).actualAttend(21.0).overtime(21.0).weekOvertime(8.0).holiday(0.0).normalSalary(new BigDecimal(1320)).overtimeSalary(new BigDecimal("238.97")).weekOvertimeSalary(new BigDecimal("242.76")).holidaySalary(new BigDecimal(0)).postSubsidy(new BigDecimal(0)).award(new BigDecimal(20)).deduction(new BigDecimal(0)).social(new BigDecimal("113.6")).shouldSalary(new BigDecimal("1688.12")).selfTax(new BigDecimal(0)).actualSalary(new BigDecimal("1688.1")).build());list.add(StaffSalaryEntity.builder().name("曹大力").post("店长").mouthSalary(new BigDecimal(13200)).hourSalary(new BigDecimal("7.59")).shouldAttend(21.0).actualAttend(21.0).overtime(21.0).weekOvertime(8.0).holiday(0.0).normalSalary(new BigDecimal(1320)).overtimeSalary(new BigDecimal("238.97")).weekOvertimeSalary(new BigDecimal("242.76")).holidaySalary(new BigDecimal(0)).postSubsidy(new BigDecimal(0)).award(new BigDecimal(20)).deduction(new BigDecimal(0)).social(new BigDecimal("113.6")).shouldSalary(new BigDecimal("13200.12")).selfTax(new BigDecimal(0)).actualSalary(new BigDecimal("13200.1")).build());list.add(StaffSalaryEntity.builder().name("张大仙").post("经理").mouthSalary(new BigDecimal(13200)).hourSalary(new BigDecimal("7.59")).shouldAttend(21.0).actualAttend(21.0).overtime(21.0).weekOvertime(8.0).holiday(0.0).normalSalary(new BigDecimal(1320)).overtimeSalary(new BigDecimal("238.97")).weekOvertimeSalary(new BigDecimal("242.76")).holidaySalary(new BigDecimal(0)).postSubsidy(new BigDecimal(0)).deduction(new BigDecimal(0)).social(new BigDecimal("113.6")).shouldSalary(new BigDecimal("13200.12")).selfTax(new BigDecimal(0)).actualSalary(new BigDecimal("13200.1")).build());return list;}
}

展示:

在这里插入图片描述


3.2 案例二:报价单

编写模板:

在这里插入图片描述

模板文件放在项目的 resources 目录下的 templates/excel 文件夹下

在这里插入图片描述

实体类:

OfferDetailEntity.java

import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OfferDetailEntity {@ApiModelProperty(value = "公司名称")private String companyName;@ApiModelProperty(value = "报价日期")private String offerDate;@ApiModelProperty(value = "报价有效期")private String offerValidDate;@ApiModelProperty(value = "客户名称")private String customerName;@ApiModelProperty(value = "客户地址")private String customerAddress;@ApiModelProperty(value = "联系方式")private String contact;@ApiModelProperty(value = "合计数量")private Integer totalQty;@ApiModelProperty(value = "合计金额")private BigDecimal totalAmount;
}

ProductOfferEntity.java

import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.math.BigDecimal;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ProductOfferEntity {@ApiModelProperty(value = "产品名称")private String productName;@ApiModelProperty(value = "型号及规格")private String typeSpec;@ApiModelProperty(value = "数量")private Integer quantity;@ApiModelProperty(value = "单价")private BigDecimal price;@ApiModelProperty(value = "金额")private BigDecimal amount;@ApiModelProperty(value = "备注")private String remark;}

代码示例:

TestController.java

    @GetMapping("/export/by-template")@ApiOperation(value = "导出-按模板格式", produces = "application/octet-stream")public ResponseBean<String> exportByTemplate(HttpServletResponse response) {testService.exportByTemplate(response);return ResponseBean.success();}

TestService.java

    /*** 导出-按模板格式*/void exportByTemplate(HttpServletResponse response);

TestServiceImpl.java

    @SneakyThrows@Overridepublic void exportByTemplate(HttpServletResponse response) {ServletOutputStream out = response.getOutputStream();EasyExcelUtil.initResponse(response, "报价单");// 文件模板输入流,将 excel 模板放到 resources 目录下InputStream templateFile = new ClassPathResource("templates/excel/bjd.xlsx").getInputStream();ExcelWriter writer = EasyExcel.write(out).withTemplate(templateFile).build();WriteSheet sheet = EasyExcel.writerSheet().build();/*HashMap<String, Object> offerDetail = new HashMap<>();offerDetail.put("companyName", "多加辣科技");offerDetail.put("offerDate", "2024-04-07");offerDetail.put("offerValidDate", "2024-04-11");offerDetail.put("customerName", "米大傻");offerDetail.put("customerAddress", "广东省广州市");offerDetail.put("contact", "078-182****4568");offerDetail.put("totalQty", 5);offerDetail.put("totalAmount", new BigDecimal(10300));*/OfferDetailEntity offerDetail = OfferDetailEntity.builder().companyName("多加辣科技").offerDate("2024-04-07").offerValidDate("2024-04-11").customerName("米大傻").customerAddress("广东省广州市").contact("078-182****4568").totalQty(5).totalAmount(new BigDecimal(10300)).build();// 填充普通占位符// 这里 data 使用对象或者 Map 都可以writer.fill(offerDetail, sheet);List<ProductOfferEntity> list = new ArrayList<>();list.add(ProductOfferEntity.builder().productName("电脑").typeSpec("联想").price(new BigDecimal(5000)).quantity(2).amount(new BigDecimal(10000)).build());list.add(ProductOfferEntity.builder().productName("鼠标").typeSpec("联想").price(new BigDecimal(100)).quantity(3).amount(new BigDecimal(300)).build());// 填充配置,开启组合填充换行FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();// 填充列表占位符writer.fill(list, fillConfig, sheet);//填充完成writer.finish();}

相关工具类:

EasyExcelUtil.java

package com.mike.common.core.utils.excel;import com.mike.common.core.constant.DateFormatConstant;
import com.mike.common.core.utils.StringUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;public class EasyExcelUtil {/*** 初始化响应体* @param response 请求头* @param fileName 导出名称*/public static void initResponse(HttpServletResponse response, String fileName) {// 最终文件名:文件名_(截止yyyy-MM-dd)  --> 这块地方得根据你们自己项目做更改了String finalFileName = fileName + "_(截止"+ StringUtils.getNowTimeStr(DateFormatConstant.Y0M0D)+")";// 设置content—type 响应类型response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");try {// 这里URLEncoder.encode可以防止中文乱码finalFileName = URLEncoder.encode(finalFileName, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}response.setHeader("Content-disposition", "attachment;filename=" + finalFileName + ".xlsx");}
}

测试:

在这里插入图片描述

在这里插入图片描述


四、我所遇到的问题

(1)驼峰命名导致填充数据失败

我在编写工资条案例时,最开始的模板如下:

在这里插入图片描述

导出效果:

在这里插入图片描述

数据都有,但是导出的表格中有些字段填充失败

这个我也不知道具体原因是为什么,不过测了几组数据之后,得出以下结论:

如果占位符中的变量采用的是驼峰命名的方式,且组成变量的 “单词” 存在过于简单的时就会出现该状况,比如说:

月薪的占位符 {.mSalary} 中的 mSalary 是由 msalary 组成,m 只有一个字母, {.mSalary} 填充不上,但是如果单独使用 {.m} 或者 {.salary} 却可以填充上去,或者把每个组成的单词写复杂一点,比如写成 {.mouthSalary} 也是可以填充上的

解决方案:要么就不要用驼峰命名,要么驼峰命名就写规范点,不要简写

(3)模板单元格样式消失

如果你使用模板导出发现有些单元格的样式消失了,比如:

在这里插入图片描述

这是因为在 write() 方法中添加了表格头的 class 对象

在这里插入图片描述

通过模板导出的方式不需要设置这个类对象,去掉即可

        ExcelWriter writer = EasyExcel.write(out).withTemplate(templateFile).build();



参考文章:

easyexcel导出excel表格:https://blog.csdn.net/qq_57732418/article/details/136944211

SpringBoot集成阿里EasyExcel导出excel高级实战:https://blog.csdn.net/Blueeyedboy521/article/details/128257388

springboot 使用 EasyExcel 通过模板导出EXCEL 带多个动态列表:https://www.cnblogs.com/guanxiaohe/p/17719954.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/801692.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VSCode配置AI自动补全插件Tabnine

面向软件开发人员的 AI 助手 使用 AI 代码完成更快地编写代码 什么是Tabnine Tabnine 是一款 AI 代码助手&#xff0c;可让您成为更好的开发人员。Tabnine 将通过所有最流行的编码语言和 IDE 的实时代码完成、聊天和代码生成来提高您的开发速度。 无论您将其称为 IntelliSens…

Java基础知识总结(45)

&#xff08;3&#xff09;类和对象 类是面向对象的重要内容&#xff0c;可以把类当做一种自定义类型&#xff0c;可以使用类来定义变量&#xff0c;这种类型的变量统称为引用类型变量。 &#xff08;4&#xff09;定义类 类是对一批对象的抽象&#xff0c;可以…

一文读懂CSS中的阴影:box-shadow,text-shadow,drop-shadow的区别与使用方式

一、区别 box-shadow 应用于元素&#xff0c;为元素本身添加阴影效果。 text-shadow 应用于文本&#xff0c;为文本内容添加阴影效果。 drop-shadow 是filter属性的一部分&#xff0c;通常用于图像&#xff0c;为其添加阴影效果。 二、box-shadow box-shadow属性用于为元素&…

无线局域网安全协议-WEP,WPA,WAPI,

目录 一、WEP&#xff08;有线等效保密&#xff09; 二、WPA&#xff08;Wi-Fi网络安全接入&#xff09; ​编辑 三、WAPI&#xff08;无线局域网鉴别和保密基础结构&#xff09; WLAN&#xff08;Wireless Local Area Network&#xff09;指应用无线通信技术将计算机设备互…

C语言程序的编译与链接

目录 1.翻译环境和运行环境2.翻译环境2.1 预处理&#xff08;预编译&#xff09;2.2 编译2.3 汇编2.4 链接 3.运行环境 1.翻译环境和运行环境 在ANSI C的任何一种实现中&#xff0c;存在两个不同的环境。 翻译环境&#xff1a;在这个环境中源代码被转换为可执⾏的机器指令&am…

计算机网络(一)--网络发展和协议

网络发展和协议 计算机网络背景从独立模式到网络互联模式计算机网络发展七个阶段1. 批处理2. 分时系统3. 计算机之间的通信4. 计算机网络的产生5. 互联网的普及6. 以互联网技术为中心的时代7. 单纯建立连接 到 安全建立连接 协议例子:人与人之间的对话计算机中的协议 协议分层O…

Linux CentOS基础操作

Linux CentOS基础操作 1. 查看Linux服务器当前主机名等 hostname 2. 查看当前系统日期和时间 date -d -y 3. 显示网络接口信息&#xff0c;获取当前网卡状态&#xff0c;启动、停止网卡&#xff0c;网卡等闪烁显示30秒&#xff0c;配置网卡(网卡名称&#xff1a;eth1)的IP地址…

Redis主从同步机制

Redis主从同步机制是一种分布式数据库架构设计&#xff0c;用于确保主数据库&#xff08;Master&#xff09;和从数据库&#xff08;Slave&#xff09;之间的数据一致性&#xff0c;从而实现数据冗余、负载均衡、故障转移等功能。以下是Redis主从同步机制的关键要点&#xff1a…

每日OJ题_两个数组dp⑤_力扣10. 正则表达式匹配

目录 力扣10. 正则表达式匹配 解析代码 力扣10. 正则表达式匹配 10. 正则表达式匹配 难度 困难 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符* 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c…

springboot 整合 mybatis(配置版)

代码及配置整合 创建实体类,与数据库对应 创建 mapper、service 和 controller @AutowiredUserService userService;@ResponseBody@GetMapping("/user")public com.vazquez.bootstudy.model.User getById(@RequestParam("id") Long id) {return userServ…

XC7A35T-2FGG484 嵌入式FPGA现场可编程门阵列 Xilinx

XC7A35T-2FGG484 是一款由Xilinx&#xff08;赛灵思&#xff09;制造的FPGA&#xff08;现场可编程门阵列&#xff09;芯片 以下是XC7A35T-2FGG484 的主要参数&#xff1a; 1. 系列&#xff1a;Artix-7 2. 逻辑单元数量&#xff1a;33280个 3. 工艺技术&#xff1a;28nm 4. …

设计模式之中介者模式讲解

概念&#xff1a;也称为调停者模式。用一个中介者对象封装一系列对象的交互&#xff0c;中介者使各对象不需要显示地相互作用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。 抽象中介者&#xff1a;定义中介者的操作。具体中介者&#xff1a;实现…

【HTML】简单制作一个动态变色光束花

目录 前言 开始 HTML部分 效果图 ​编辑​编辑​编辑​编辑总结 前言 无需多言&#xff0c;本文将详细介绍一段代码&#xff0c;具体内容如下&#xff1a; 开始 首先新建文件夹&#xff0c;创建一个文本文档&#xff0c;其中HTML的文件名改为[index.html]&a…

目标检测YOLO实战应用案例100讲-基于卷积神经网络的多尺度特征融合目标检测

目录 前言 存在的挑战 2 相关技术基础 2.1 卷积神经网络 2.2 损失函数

【CTF】rip--堆栈的简单认识

前言 最近在学二进制&#xff0c;准备拿BUUCTF的pwn试试手&#xff0c;还在摸索的阶段&#xff0c;有什么思路出错的地方还请指出。 解题思路 下载文件到kali&#xff0c;查看文件为 64-bit的ELF&#xff08;ELF为Linux下的可执行文件&#xff0c;相当于Windows的exe&#xff0…

python-flask后端知识点

anki 简单介绍&#xff1a; 在当今信息爆炸的时代&#xff0c;学习已经不再仅仅是获取知识&#xff0c;更是一项关于有效性和持续性的挑战。幸运的是&#xff0c;我们有幸生活在一个科技日新月异的时代&#xff0c;而ANKI&#xff08;Anki&#xff09;正是一款旗舰级的学习工具…

GD32F470_GY-68 BMP180 新款 BOSCH温度 代替BMP085 气压传感器模块

2.23 BMP180气压传感器 1BMP180是一款高精度、小体积、低能耗的压力传感器&#xff0c;可以轻松应用在移动设备中.在测量海拔高度时&#xff0c;传统的做法是通过测量某一高度的大气压力&#xff0c;再经过换算才能得到高度数据。BMP180不仅可以实时的测量大气压力&#xff0c…

基于velero和minio实现k8s数据的备份

1.30部署minio rootk8s-harbor:/etc/kubeasz/clusters/k8s-cluster1# docker run \ -d --restartalways -p 9000:9000 -p 9090:9090 –name minio -v /data/minio/data:/data -e “MINIO_ROOT_USERadmin” -e “MINIO_ROOT_PASSWORD12345678” quay.io/minio/minio server…

Netty框架介绍并编写WebSocket服务端与客户端

一、Netty 介绍 Netty 是一个基于 Java NIO&#xff08;Non-blocking I/O&#xff0c;非阻塞 I/O&#xff09;的网络通信框架&#xff0c;旨在帮助开发者轻松地编写高性能、高可靠性的网络应用程序。由于其出色的设计和强大的功能&#xff0c;Netty 在企业级应用和开源项目中得…

智慧安防系统EasyCVR视频汇聚平台接入大华设备无法语音对讲的原因排查与解决

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台支持7*24小时实时高清视频监控&#xff0c;能同时播放多路监控视频流&#xff0c;视频画面1、4、9、16个可选&#xff0c;支持自定义视频轮播。EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标…