【EasyExcel实践】万能导出,一个接口导出多张表以及任意字段(可指定字段顺序)-简化升级版

文章目录

  • 前言
  • 正文
    • 一、项目简介
    • 二、核心代码
      • 2.1 pom.xml 依赖配置
      • 2.2 ExcelHeadMapFactory
      • 2.3 ExcelDataLinkedHashMap
      • 2.4 自定义注解 ExcelExportBean
      • 2.5 自定义注解 ExcelColumnTitle
      • 2.6 建造器接口 Builder
      • 2.7 表格工具类 ExcelUtils
      • 2.8 GsonUtil
      • 2.9 模版类 ExportDynamicColumnTemplate
      • 2.10 模版建造器 ExportDynamicColumnTemplateBuilder
    • 三、控制器&调试Bean的定义
      • 3.1 StudentDemo
      • 3.2 NameAndFactoryDemo
      • 3.3 控制器 ExcelDemoController
    • 四、启动类
    • 五、测试

前言

关于万能导出,前一阵子写过一个,功能是实现了的。
就是在使用时,感觉如果需要导出的页面比较多,那就会出现比较多的重复代码。就想着优化+简化一下,能够更方便的使用。

原版代码仓库和这一版的代码仓库相同:
https://gitee.com/fengsoshuai/excel-demo

原版中额外增加了转换器,枚举转换等功能,但是总觉得会让整体功能变复杂,所以在这一版中就去掉了。如果有兴趣看看的话,可以切换到master分支查看。

简化升级的这一版的代码分支是:simple-dynamic-column-export

正文

一、项目简介

本次简化升级,本着对使用者友好的目的去实现的。

另外,本文会粘贴全部代码!!

在这里插入图片描述

在使用上的简化体现在真正导出时,只需要几行代码,就能实现功能。可以让你更加专注于业务参数的组装。而且代码比较简洁。
举个例子:

@GetMapping("/exportDy")
public String exportDy(@RequestParam("table") List<String> table, HttpServletResponse response) throws IOException {// 构造导出模版ExportDynamicColumnTemplate<StudentDemo> dynamicColumnTemplate = new ExportDynamicColumnTemplateBuilder<>(StudentDemo.class).columnNameList(table).build();// 制造假数据dynamicColumnTemplate.appendExportDataList(studentDemos());// 转换为excel的字节数组byte[] bytes = dynamicColumnTemplate.toExcelByteArray();// 响应到webString fileName = System.currentTimeMillis() + ".xlsx";response.setHeader("Content-disposition", "attachment;filename=" + fileName);response.setContentType("application/x-msdownload");response.setCharacterEncoding("utf-8");response.getOutputStream().write(bytes);response.getOutputStream().flush();return "success";
}

简化后的代码,只需要3步操作:

  1. 根据导出bean,使用建造器生成模版实例;
  2. 给模版实例中填充业务数据;
  3. 填充完数据后,将数据转换为excel格式的字节数组;

当我们抡完这三板斧之后,剩下的就是将字节数组响应到web导出。

二、核心代码

2.1 pom.xml 依赖配置

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.2.0.RELEASE</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.11</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion></exclusions></dependency><!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.10.1</version></dependency>
</dependencies>

2.2 ExcelHeadMapFactory

表格头映射工厂,提供了注册表格头和获取表格头配置的静态方法。

package org.feng.export.factory;import org.feng.export.system.ExcelColumnTitle;
import org.feng.export.system.ExcelExportBean;import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;/*** 表格头映射工厂** @author feng*/
public class ExcelHeadMapFactory {/*** 全局表头名映射,key内部变量的变量名和中文名映射为value*/private static final Map<Class<?>, Map<String, String>> HEAD_NAME_MAP = new HashMap<>();public static void addHeadClass(Class<?> headClass) {if (!headClass.isAnnotationPresent(ExcelExportBean.class)) {throw new RuntimeException("HeadClass必须使用注解ExcelExportBean");}HEAD_NAME_MAP.put(headClass, mapToPrepareHead(headClass));}public static Map<String, String> getHeadMap(Class<?> headClass) {return HEAD_NAME_MAP.get(headClass);}public static boolean containsHeadClass(Class<?> headClass) {return HEAD_NAME_MAP.containsKey(headClass);}private static Map<String, String> mapToPrepareHead(Class<?> excelHeadClass) {Map<String, String> namedMap = new HashMap<>();Field[] declaredFields = excelHeadClass.getDeclaredFields();for (Field declaredField : declaredFields) {boolean annotationPresent = declaredField.isAnnotationPresent(ExcelColumnTitle.class);if (annotationPresent) {ExcelColumnTitle excelProperty = declaredField.getAnnotation(ExcelColumnTitle.class);String chineseFieldName = excelProperty.value();// 保存字段名和中文变量名namedMap.put(declaredField.getName(), chineseFieldName);}}return namedMap;}
}

2.3 ExcelDataLinkedHashMap

自定义LinkedHashMap,用于实现字段的顺序,以及动态字段展示。
只提供put 和 putAll方法的实现。想要别的put方法的话,读者请自行实现。

package org.feng.export.system;import org.springframework.util.CollectionUtils;import java.util.*;
import java.util.stream.Collectors;/*** 表格数据专用的map,带顺序,而且初始化的时候,依据指定的表头变量字段名确定导出数据的顺序** @author feng*/
public class ExcelDataLinkedHashMap extends LinkedHashMap<String, Object> {private static final long serialVersionUID = -8554095999151235982L;/*** 头部字段名缓存*/private final Set<String> headColumnNamesCache;/*** 指定被忽略的列名*/private final Set<String> ignoreColumnSet;/*** ExcelDataLinkedHashMap构造器** @param headColumnNames 表头字段变量名,例如:[name,studentNo,age,className]*/public ExcelDataLinkedHashMap(List<Object> headColumnNames, String... ignoreColumns) {if (ignoreColumns != null && ignoreColumns.length > 0) {ignoreColumnSet = new HashSet<>(Arrays.asList(ignoreColumns));} else {ignoreColumnSet = Collections.emptySet();}// 字段名去重List<String> headColumnStringNames = headColumnNames.stream().distinct().map(Object::toString).collect(Collectors.toList());// 构建字段名缓存this.headColumnNamesCache = new HashSet<>(headColumnStringNames);// 指定列数据排列顺序for (String headColumnName : headColumnStringNames) {this.put(headColumnName, null);}}@Overridepublic Object put(String key, Object value) {// 只保存字段名缓存中的key以及valueif (headColumnNamesCache.contains(key)) {// 设置了被忽略的列,进行判断处理,匹配到了就不保存if (!CollectionUtils.isEmpty(ignoreColumnSet) && ignoreColumnSet.contains(key)) {return null;}return super.put(key, value);}return null;}@Overridepublic void putAll(Map<? extends String, ?> map) {map.forEach(this::put);}
}

2.4 自定义注解 ExcelExportBean

package org.feng.export.system;import java.lang.annotation.*;/*** 指定表格导出的bean** @author feng*/
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelExportBean {
}

2.5 自定义注解 ExcelColumnTitle

package org.feng.export.system;import java.lang.annotation.*;/*** 列名标题注解,标注列的标题** @author feng*/
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelColumnTitle {String value();
}

2.6 建造器接口 Builder

package org.feng.export.util;/*** 建造器接口** @author feng*/
public interface Builder<T> {T build();
}

2.7 表格工具类 ExcelUtils

提供将数据写入表格的静态方法。

package org.feng.export.util;import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.WriteSheet;import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;/*** excel工具类** @author feng*/
public class ExcelUtils {/*** 导出数据(单sheet)** @param exportData key 是sheet名称,value是每个sheet里面的数据,支持自定义表头*/public static byte[] easyOut(List<Map<String, Object>> exportData) {return easyOut("Sheet", exportData);}/*** 导出数据(单sheet)** @param exportData key 是sheet名称,value是每个sheet里面的数据,支持自定义表头*/public static byte[] easyOut(String sheetName, List<Map<String, Object>> exportData) {return easyOut(Collections.singletonMap(sheetName, exportData));}/*** 导出数据(多sheet)** @param exportData key 是sheet名称,value是每个sheet里面的数据,可以自定义*/public static byte[] easyOut(Map<String, List<Map<String, Object>>> exportData) {// 导出数据ByteArrayOutputStream out = new ByteArrayOutputStream();com.alibaba.excel.ExcelWriter excelWriter = EasyExcel.write(out).build();int i = 0;for (Map.Entry<String, List<Map<String, Object>>> entry : exportData.entrySet()) {WriteSheet writeSheet = EasyExcel.writerSheet(i, entry.getKey()).head(head(entry.getValue().get(0))).build();i++;excelWriter.write(data(entry.getValue(), true), writeSheet);}excelWriter.finish();return out.toByteArray();}private static List<List<String>> head(Map<String, Object> cellData) {List<List<String>> head = new ArrayList<>();for (String key : cellData.keySet()) {head.add(Collections.singletonList(key));}return head;}private static List<List<Object>> data(List<Map<String, Object>> sheetData, boolean skipHead) {List<List<Object>> data = new ArrayList<>();for (int i = 0; i < sheetData.size(); i++) {if (i == 0 && skipHead) {continue;}data.add(new ArrayList<>(sheetData.get(i).values()));}return data;}
}

2.8 GsonUtil

gson工具类,提供json处理、转换的静态方法。

package org.feng.export.util;import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;import java.util.Map;/*** gson工具类** @version v1.0* @author: fengjinsong* @date: 2023年08月26日 15时00分*/
public class GsonUtil {/*** 不会序列化空字段的Gson对象*/private static final Gson GSON = new GsonBuilder().create();/*** 可以序列化空字段的Gson对象*/private static final Gson GSON_WITH_NULL = new GsonBuilder().serializeNulls().create();private static final Gson GSON_WITH_DISABLE_HTML_ESCAPING = new GsonBuilder().disableHtmlEscaping().create();public static Gson gson() {return GSON;}/*** 转换对象为json字符串(不会序列化空字段)** @param object 目标对象* @return 一个json字符串*/public static String toJson(Object object) {return GSON.toJson(object);}/*** 转换对象为json字符串(可以序列化空字段)** @param object 目标对象* @return 一个json字符串*/public static String toJsonWithNull(Object object) {return GSON_WITH_NULL.toJson(object);}/*** 转换对象为json字符串(禁止html转义)** @param object 目标对象* @return 一个json字符串*/public static String toJsonWithDisableTtmlEscaping(Object object) {return GSON_WITH_DISABLE_HTML_ESCAPING.toJson(object);}public static <T> T fromJson(String jsonStr, Class<T> clazz) {return GSON.fromJson(jsonStr, clazz);}public static Map<String, String> toStringMap(String jsonStr) {return GSON.fromJson(jsonStr, new TypeToken<Map<String, String>>() {}.getType());}/*** 校验字符串是否是一个json格式* <br> 注意:{@code "{}"} 也是符合条件的json** @param jsonStr 目标字符串* @return true表示目标是一个正确的json格式*/public static boolean validateJson(String jsonStr) {JsonElement jsonElement;try {jsonElement = JsonParser.parseString(jsonStr);} catch (Exception e) {return false;}if (jsonElement == null) {return false;}return jsonElement.isJsonObject();}
}

2.9 模版类 ExportDynamicColumnTemplate

package org.feng.export;import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.feng.export.factory.ExcelHeadMapFactory;
import org.feng.export.system.ExcelDataLinkedHashMap;
import org.feng.export.util.ExcelUtils;
import org.feng.export.util.GsonUtil;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;import java.util.*;/*** 导出动态列模版** @author feng*/
@Slf4j
@Getter
public class ExportDynamicColumnTemplate<T> {/*** 导出的bean类型*/private Class<T> exportBean;/*** 导出的数据*/private List<Map<String, Object>> exportData;/*** 当前表头映射*/private Map<String, Object> currentHeadMap;/*** 真正导出的列名*/private List<Object> realExportColumnNameList;/*** 是否转换前打印导出数据(含表头)*/@Setterprivate boolean logExportData;/*** 是否转换前打印实际的表头信息*/@Setterprivate boolean logCurrentHead;ExportDynamicColumnTemplate(Class<T> exportBean, List<String> columnNameList) {this(exportBean, columnNameList, false, true);}ExportDynamicColumnTemplate(Class<T> exportBean, List<String> columnNameList, boolean logExportData, boolean logCurrentHead) {init(exportBean, columnNameList);this.logExportData = logExportData;this.logCurrentHead = logCurrentHead;}/*** 追加导出数据** @param data          数据* @param ignoreColumns 设置忽略的列名*/public void appendExportData(T data, String... ignoreColumns) {Objects.requireNonNull(data);ExcelDataLinkedHashMap dataMap = new ExcelDataLinkedHashMap(realExportColumnNameList, ignoreColumns);exportData.add(dataMap);String dataJson = GsonUtil.toJson(data);dataMap.putAll(GsonUtil.toStringMap(dataJson));}/*** 追加导出数据列表** @param dataList      数据列表* @param ignoreColumns 设置忽略的列名*/public void appendExportDataList(List<T> dataList, String... ignoreColumns) {if (CollectionUtils.isEmpty(dataList)) {return;}dataList.forEach(data -> appendExportData(data, ignoreColumns));}/*** 将当前需要导出的数据转换为表格的字节数组** @return 字节数组*/public byte[] toExcelByteArray() {return toExcelByteArray("Sheet");}/*** 将当前需要导出的数据转换为表格的字节数组** @param sheetName 指定sheet名* @return 字节数组*/public byte[] toExcelByteArray(String sheetName) {if (logExportData) {logExportData();}if (logCurrentHead) {log.info("导出数据表头信息:{}", currentHeadMap);}return ExcelUtils.easyOut(sheetName, exportData);}private void logExportData() {for (int i = 0; i < exportData.size(); i++) {Map<String, Object> data = exportData.get(i);log.info("导出数据[{}]:{}", i, data);}}/*** 初始化导出模版信息,主要是表头信息** @param exportBean     导出bean的类型* @param columnNameList 需要导出的字段名列表*/private void init(Class<T> exportBean, List<String> columnNameList) {this.exportBean = exportBean;exportData = new ArrayList<>();currentHeadMap = new LinkedHashMap<>();// 获取代码配置的表头信息if (!ExcelHeadMapFactory.containsHeadClass(exportBean)) {ExcelHeadMapFactory.addHeadClass(exportBean);}Map<String, String> headMap = ExcelHeadMapFactory.getHeadMap(exportBean);Assert.notEmpty(headMap, "表头不能为空,请检查exportBean的类型");// 初始化真正的表头信息,过滤无效配置或找不到的列名realExportColumnNameList = new ArrayList<>();for (String field : columnNameList) {String fieldChineseName = headMap.get(field);if (StringUtils.isEmpty(fieldChineseName)) {log.info("代码配置的导出表头不完整,不存在字段:{}", field);} else {currentHeadMap.put(fieldChineseName, field);realExportColumnNameList.add(field);}}// 记录当前的表头信息exportData.add(currentHeadMap);}
}

2.10 模版建造器 ExportDynamicColumnTemplateBuilder

用于生成模版实例。

package org.feng.export;import lombok.AccessLevel;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.feng.export.system.ExcelExportBean;
import org.feng.export.util.Builder;
import org.springframework.util.Assert;import java.util.List;/*** 导出动态列模版建造器** @author feng*/
@Accessors(chain = true, fluent = true)
@Setter
public class ExportDynamicColumnTemplateBuilder<T> implements Builder<ExportDynamicColumnTemplate<T>> {/*** 字段名列表*/private List<String> columnNameList;/*** 导出的bean类型*/@Setter(AccessLevel.NONE)private final Class<T> exportBean;/*** 是否转换前打印导出数据(含表头)*/private Boolean logExportData;/*** 是否转换前打印实际的表头信息*/private Boolean logCurrentHead;public ExportDynamicColumnTemplateBuilder(Class<T> exportBean) {if (!exportBean.isAnnotationPresent(ExcelExportBean.class)) {throw new RuntimeException("ExportBean必须使用注解ExcelExportBean");}this.exportBean = exportBean;}@Overridepublic ExportDynamicColumnTemplate<T> build() {check();ExportDynamicColumnTemplate<T> template = new ExportDynamicColumnTemplate<>(exportBean, columnNameList);if(logCurrentHead != null) {template.setLogCurrentHead(logCurrentHead);}if(logExportData != null) {template.setLogExportData(logExportData);}return template;}private void check() {Assert.notNull(exportBean, "导出的实例类型不能为空");Assert.notEmpty(columnNameList, "字段名列表不能为空");}
}

三、控制器&调试Bean的定义

这一部分是非核心代码,属于对核心代码使用的一种演示。读者可以按照对应的写法来实现功能。

注意:导出的bean定义,需要使用注解 ExcelExportBean,其中的字段需要使用注解ExcelColumnTitle

3.1 StudentDemo

package org.feng.headbean;import org.feng.export.system.ExcelColumnTitle;
import lombok.Data;
import org.feng.export.system.ExcelExportBean;/*** 学生demo导出bean** @author feng*/
@Data
@ExcelExportBean
public class StudentDemo {@ExcelColumnTitle("姓名")private String name;@ExcelColumnTitle("年龄")private String age;@ExcelColumnTitle("性别")private String sex;@ExcelColumnTitle("学号")private String studentNo;@ExcelColumnTitle("班级")private String className;
}

3.2 NameAndFactoryDemo

该类对本次演示无实际意义,保留着是因为,需要演示加载多个配置表头的实例时的写法。
具体的可以查看启动类ExcelDemoApplication中的内容。

package org.feng.headbean;import org.feng.export.system.ExcelColumnTitle;
import lombok.Data;
import org.feng.export.system.ExcelExportBean;/*** TODO** @author feng*/
@Data
@ExcelExportBean
public class NameAndFactoryDemo {@ExcelColumnTitle("名字")private String name;@ExcelColumnTitle("工厂")private String factory;
}

3.3 控制器 ExcelDemoController

package org.feng.controller;import org.feng.export.ExportDynamicColumnTemplate;
import org.feng.export.ExportDynamicColumnTemplateBuilder;
import org.feng.headbean.StudentDemo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;@Controller
@RequestMapping("/excel")
public class ExcelDemoController {@GetMapping("/exportDy")public String exportDy(@RequestParam("table") List<String> table, HttpServletResponse response) throws IOException {// 构造导出模版ExportDynamicColumnTemplate<StudentDemo> dynamicColumnTemplate = new ExportDynamicColumnTemplateBuilder<>(StudentDemo.class).columnNameList(table).build();// 制造假数据dynamicColumnTemplate.appendExportDataList(studentDemos());// 转换为excel的字节数组byte[] bytes = dynamicColumnTemplate.toExcelByteArray();// 响应到webString fileName = System.currentTimeMillis() + ".xlsx";response.setHeader("Content-disposition", "attachment;filename=" + fileName);response.setContentType("application/x-msdownload");response.setCharacterEncoding("utf-8");response.getOutputStream().write(bytes);response.getOutputStream().flush();return "success";}private List<StudentDemo> studentDemos() {List<StudentDemo> studentDemos = new ArrayList<>();for (int i = 0; i < 5; i++) {StudentDemo studentDemo = new StudentDemo();studentDemo.setStudentNo(100 + "-" + i);studentDemo.setAge(String.valueOf(20 + i));studentDemo.setSex(i > 2 ? "男" : "女");studentDemo.setClassName("一班");studentDemo.setName("小米" +(i+1));studentDemos.add(studentDemo);}return studentDemos;}
}

四、启动类

启动项目时,加载代码配置信息。

package org.feng;import org.feng.export.factory.ExcelHeadMapFactory;
import org.feng.headbean.NameAndFactoryDemo;
import org.feng.headbean.StudentDemo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;import java.util.ArrayList;
import java.util.List;@SpringBootApplication
public class ExcelDemoApplication implements CommandLineRunner {public static void main(String[] args) {SpringApplication.run(ExcelDemoApplication.class, args);}@Overridepublic void run(String... args) throws Exception {List<Class<?>> needRegisterExcelHeadClassList = new ArrayList<>();needRegisterExcelHeadClassList.add(NameAndFactoryDemo.class);needRegisterExcelHeadClassList.add(StudentDemo.class);needRegisterExcelHeadClassList.forEach(ExcelHeadMapFactory::addHeadClass);}
}

五、测试

在谷歌浏览器访问:
http://localhost:8080/excel/exportDy?table=name,className,studentNo

会下载得到这样的文件:
在这里插入图片描述

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

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

相关文章

概率中的50个具有挑战性的问题[02/50]:连续获胜

一、说明 我最近对与概率有关的问题产生了兴趣。我偶然读到了弗雷德里克莫斯特勒&#xff08;Frederick Mosteller&#xff09;的《概率论中的五十个具有挑战性的问题与解决方案》&#xff08;Fifty Challenge Problems in Probability with Solutions&#xff09;一书。我认为…

HarmonyOS构建第一个ArkTS应用(FA模型)

构建第一个ArkTS应用&#xff08;FA模型&#xff09; 创建ArkTS工程 若首次打开DevEco Studio&#xff0c;请点击Create Project创建工程。如果已经打开了一个工程&#xff0c;请在菜单栏选择File > New > Create Project来创建一个新工程。 选择Application应用开发&a…

十三、W5100S/W5500+RP2040之MicroPython开发<MQTT新版OneNET示例>

文章目录 1. 前言2. 平台操作流程3. WIZnet以太网芯片4. 示例讲解以及使用4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 烧录验证 5. 注意事项6. 相关链接 1. 前言 在这个智能硬件和物联网时代&#xff0c;MicroPython和树莓派PICO正以其独特的优势引领着嵌入式开发…

【SpringBoot】之Security集成使用(入门级)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringBoot开发之Security系列》。&#x1f3af…

【SpringBoot】之Security进阶使用

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringBoot开发之Security系列》。&#x1f3af…

k8s启动docker容器Error: Could not find or load main class ${start-class}报错

前行提要&#xff1a; 今天部署采集点服务&#xff08;docker项目&#xff09;发现报这个错误。 提出假设&#xff1a; 1&#xff0c;配置文件错误&#xff08;工程需要配置的东西比较多&#xff09; 之后开始一一排查&#xff0c;发现配置有问题&#xff0c;但是不是这个错误…

modbus_tcp的实现 through python.

0.引言 当前科技似乎处于加速发展期&#xff0c;各个模块都在快速迭代&#xff0c;迭代的速度会让既有的一些经验产生问题&#xff0c;在用python实现modbus_tcp协议时&#xff0c;网上流传的一些代码中import语句会出现问题。导致pymodbus模块用起来很不好用。 这个原因出在…

【ps】常见工具说明

1&#xff1a;污点修复工具 》内容识别 去除脸部珍珠 》创建纹理 2&#xff1a;修复画笔工具 按住ALT选择一处你想移动的地方 3&#xff1a;修补工具 》内容识别 选择一个区域 将区域内的东西移动到 另一处皮肤上

C语言之字符串

目录 字符串字面量 ​编辑 字符串字面量的长度 ◆具有静态生命周期 ◆对于同一个字符串字面量的处理方式依赖于编译器 字符串 字符数组的初始化赋值 空字符串 字符串的读取 在前面的学习中就会发现&#xff0c;仅仅能用一个字符表示的事物少之又少&#xff0c;对于地…

日志服务 SLS 深度解析:拥抱云原生和 AI,基于 SLS 的可观测分析创新

云布道师 10 月 31 日&#xff0c;杭州云栖大会上&#xff0c;日志服务 SLS 研发负责人简志和产品经理孟威等人发表了《日志服务 SLS 深度解析&#xff1a;拥抱云原生和 AI&#xff0c;基于 SLS 的可观测分析创新》的主题演讲&#xff0c;对阿里云日志服务 SLS 产品服务创新以…

2023/12/21作业

思维导图 代码 .text .global _start _start: 灯1 gpio时钟使能 [4]->1 0x5000A28 LDR R0,0x50000A28 指定寄存器地址 LDR R1,[R0]将寄存器取出放到R1 ORR R1,R1,#(0x1<<4)将第四位设置为1 STR R1,[R0]读取R0寄存器到R1 PE…

Ubuntu 常用命令之 reboot 命令用法介绍

&#x1f4d1;Linux/Ubuntu 常用命令归类整理 reboot命令在Ubuntu系统中用于重新启动系统。这个命令通常需要管理员权限才能执行。 reboot命令的参数如下 -f 或 --force&#xff1a;强制重启&#xff0c;不调用shutdown -r进行友好重启。-p 或 --poweroff&#xff1a;在重启…

arm和x86架构服务器拉取arm64架构的docker镜像

dockerhub提供的镜像部分支持arm64架构 Docker arm架构服务器拉取docker镜像&#xff0c;默认是arm架构 # docker pull centos Using default tag: latest latest: Pulling from library/centos 52f9ef134af7: Pull complete Digest: sha256:a27fd8080b517143cbbbab9dfb7c8…

HarmonyOS布局之scroll

对于Scroll 布局官方讲解非常好&#xff0c;我在这做个总结&#xff0c;主要结合实际应用进行补充 Scroll — 首先他是一个容器布局&#xff0c;所有的容器布局都可包含子布局&#xff0c;因此scroll 布局也可包含子组件但是&#xff08;他只能包含一个子组件&#xff09;&…

nodejs微信小程序+python+PHP医院挂号系统-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

0基础学习VR全景平台篇第130篇:曝光三要素—感光度

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 众所周知&#xff0c;摄影是一门用光的艺术。随着天气、地点、时间的变化&#xff0c;我们所处环境的光线也随之发生改变。而在不同的环境下该如何去正确的调节曝光&#xff0c;是…

PyTorch加载数据以及Tensorboard的使用

一、PyTorch加载数据初认识 Dataset:提供一种方式去获取数据及其label 如何获取每一个数据及其label 总共有多少的数据 Dataloader:为后面的网络提供不同的数据形式 数据集 在编译器中导入Dataset from torch.utils.data import Dataset 可以在jupyter中查看Dataset官方文档&…

confluence操作手册

文章目录 快捷键插入宏插入代码块 自动为标题编号使用方法&#xff1a; 移动页面到其它目录层级下 快捷键 插入宏 英文输入法下输入{ 插入代码块 输入三个会跳出 点编辑可以调整样式 自动为标题编号 安装插件Numbered Headings 下载链接&#xff1a;https://appfire.…

微服务 Spring Cloud 10,如何追踪微服务调用?服务治理的常见手段

目录 一、服务追踪的作用1、优化系统瓶颈2、优化链路调用3、故障排查4、性能优化5、生成网络拓扑图4、透明传输数据 二、节点管理1、服务调用失败一般有两类原因造成&#xff1a;2、服务调用失败的解决方式&#xff1a;3、服务调用失败的具体解决方式&#xff1a; 三、负载均衡…

ansible的控制语句

本章内容主要介绍 playbook 中的控制语句 使用when判断语句block-rescue判断循环语句 一个play中可以包含多个task&#xff0c;如果不想所有的task全部执行&#xff0c;可以设置只有满足某个条件才执行这个task&#xff0c;不满足条件则不执行此task。本章主要讲解when 和 blo…