【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步操作:
- 根据导出bean,使用建造器生成模版实例;
- 给模版实例中填充业务数据;
- 填充完数据后,将数据转换为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
会下载得到这样的文件:
相关文章:

【EasyExcel实践】万能导出,一个接口导出多张表以及任意字段(可指定字段顺序)-简化升级版
文章目录 前言正文一、项目简介二、核心代码2.1 pom.xml 依赖配置2.2 ExcelHeadMapFactory2.3 ExcelDataLinkedHashMap2.4 自定义注解 ExcelExportBean2.5 自定义注解 ExcelColumnTitle2.6 建造器接口 Builder2.7 表格工具类 ExcelUtils2.8 GsonUtil2.9 模版类 ExportDynamicCo…...

解决 Hive 外部表分隔符问题的实用指南
简介: 在使用 Hive 外部表时,分隔符设置不当可能导致数据导入和查询过程中的问题。本文将详细介绍如何解决在 Hive 外部表中正确设置分隔符的步骤。 问题描述: 在使用Hive外部表时,可能会遇到分隔符问题。这主要是因为Hive在读…...
一文学会 Apache Zeppelin
Zeppelin资料 Zeppelin项目信息 Zeppelin官网 http://zeppelin.apache.org/Zeppelin源码地址 https://github.com/apache/zeppelinZeppelin JIRA: https://issues.apache.org/jira/projects/ZEPPELIN/summaryZeppelin文档 Flink on Zeppelin 文档集中地 https://www.yuque.co…...

ROS学习笔记(七)---参数服务器
ROS学习笔记文章目录 01. ROS学习笔记(一)—Linux安装VScode 02. ROS学习笔记(二)—使用 VScode 开发 ROS 的Python程序(简例) 03. ROS学习笔记(三)—好用的终端Terminator 04. ROS学习笔记(四)—使用 VScode 启动launch文件运行多个节点 05. ROS学习笔…...

【RTOS学习】源码分析(信号量和互斥量 事件组 任务通知)
🐱作者:一只大喵咪1201 🐱专栏:《RTOS学习》 🔥格言:你只管努力,剩下的交给时间! 目录 🍓信号量和互斥量🍅创建🍅Take🍅Give &#x…...
1316:【例4.6】数的计数(Noip2001) 代码+解析
1316:【例4.6】数的计数(Noip2001) 【题目描述】 我们要求找出具有下列性质数的个数(包括输入的自然数n )。先输入一个自然数n(n≤1000),然后对此自然数按照如下方法进行处理:不作任何处理;在它的左边加上一…...

征集倒计时 | 2023年卓越影响力榜单-第四届中国产业创新奖报名即将截止
第四届「ISIG中国产业智能大会」将于2024年3月16日在上海举办。2024 ISIG 以“与科技共赢,与产业共进”为主题,共设立RPA超自动化、 低代码、AIGC大模型、流程挖掘四大主题峰会。届时,大会组委会将颁发2023年度卓越影响力榜单—第四届中国产业…...

vue的语法模板与数据绑定的说明
vue的两大模板语法: 1.插值语法 2.指定语法 插值语法:{{}} 功能:用于解析标签体的内容 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性 指定语法: 功能:用于解析标签(包括:标签属性、标…...

VueCron使用方法
1)什么是vueCron Vue Cron 是基于 Vue.js 的定时任务管理组件,它提供了一种简单易用的方式来设定和管理定时任务。Vue Cron 提供了一个类似于 Linux crontab 的界面,用户可以通过它来创建、编辑和删除定时任务。 2)安装依赖及应…...

SpringBlade export-user SQL 注入漏洞复现
0x01 产品简介 SpringBlade 是一个由商业级项目升级优化而来的 SpringCloud 分布式微服务架构、SpringBoot 单体式微服务架构并存的综合型项目。 0x02 漏洞概述 SpringBlade v3.2.0 及之前版本框架后台 export-user 路径存在安全漏洞,攻击者利用该漏洞可通过组件customSqlS…...
结构体的一些补充知识
1、结构体后面分号前面的名字是什么意思。 在C中,结构体的定义格式为: struct <结构体名> {// 成员变量和成员函数 };在这个定义中,<结构体名>就是结构体的名称,而这个名称位于结构体定义的末尾,分号之前…...

20V升26V 600mA升压型LED驱动芯片,PWM调光芯片-AH1160
AH1160是一个功能强大的升压型LED驱动芯片,专为需要精确控制LED亮度的PWM调光应用而设计。它可将20V输入电压升压至26V,同时提供稳定的600mA电流输出,适用于各种LED照明设备。 芯片特点: 1. 输入电压范围:AH1160可在…...
如何在Go中制作HTTP服务器
引言 许多开发人员至少会花一些时间创建服务器,以便在互联网上分发内容。HTTP (Hypertext Transfer Protocol,超文本传输协议)提供了大部分这些内容,无论是请求一张猫的图片还是请求加载你正在阅读的教程。Go标准库为创建HTTP服务器以提供web内容或向这些服务器发出HTTP请求…...

Linux笔记---系统信息
🍎个人博客:个人主页 🏆个人专栏:Linux学习 ⛳️ 功不唐捐,玉汝于成 目录 前言 命令 1. uname - 显示系统信息 2. hostname - 显示或设置系统主机名 3. top - 显示系统资源使用情况 4. df - 显示磁盘空间使用情…...
最新版android stuido加上namespace
每个 Android 模块都有一个命名空间,此命名空间用作其生成的 命名空间由模块的 build.gradle 文件中的 namespace 属性定义,如以下代码段所示。namespace 最初会设为您在创建项目时选择的软件包名称。 Kotlin Groovy android {namespace "com.ex…...
Wireshark基础及捕获技巧
第一章:Wireshark基础及捕获技巧 1.1 Wireshark基础知识回顾 1.2 高级捕获技巧:过滤器和捕获选项 1.3 Wireshark与其他抓包工具的比较 第二章:网络协议分析 2.1 网络协议分析:TCP、UDP、ICMP等 2.2 高级协议分析:HTTP…...

Windows下Navicat15.0连接Oracle11g报ORA-28547解决
目录 背景 一、相关环境 1、操作系统 2、Navicat版本 3、ORACLE连接 4、默认连接 二、问题分析 1、默认dll配置 三、修改配置 1、下载匹配的client 2、替换相应目录 总结 背景 最近在项目中需要使用Oracle数据库,当前很多应用系统的数据都存储在MySQL或者Pos…...

21 Vue3中使用v-for遍历对象数组
概述 使用v-for遍历对象数组在真实的开发中也属于非常常见的用法,需要重点掌握。 因为目前流行的是前后端分离开发,在前后端分离开发中,最常需要处理的就是对象数组类型的数据了。 比如,将员工信息渲染到表格中。 这节课我们就…...
深入理解Java自定义异常与全局异常处理 @RestControllerAdvice
异常主要是包括编译时的异常和运行时的异常。编译时的异常可以通过捕获异常获取,运行时候的异常主要是通过代码规范,或者测试。 Spring Boot提供了两种异常处理方式来统一处理和维护异常信息。 第一种方式是使用RestControllerAdvice注解与ExceptionHand…...

h5页面跳转微信小程序(最简单的方法|URL Scheme)
文章目录 导文实现获取 URL Scheme加密 URL Scheme获取方式拼接参数 明文 URL Scheme获取方式 实际项目展示:频率限制注意事项开放范围示例代码包 导文 H5页面跳转微信小程序的需求是普遍存在的。由于微信小程序是一种只能在微信内部访问的应用程序,而H5…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...