【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…...
智能优化算法应用:基于非洲秃鹫算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于非洲秃鹫算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于非洲秃鹫算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.非洲秃鹫算法4.实验参数设定5.算法结果6.…...
持续集成交付CICD:Jenkins使用GitLab共享库实现前端项目镜像构建
目录 一、实验 1. GitLab修改项目文件与Harbor环境确认 2.Jenkins使用GitLab共享库实现前端项目镜像构建 3.优化CI流水线封装Harbor账户密码 4.Jenkins再次使用GitLab共享库实现前端项目镜像构建 一、实验 1. GitLab修改项目文件与Harbor环境确认 (1…...
SQL server 数据库 SQL语句高级用法
1、表的高级查询 use student select * from stuinfo1 -- 使用 in 的子查询 select * from stuinfo where stu_age in ( select stu_age from stuinfo where cla_id 12345 ) select * from stuinfo where stu_age in ( 19 , 20 , 21 , 25 , 23 , 1…...
wavlink 路由器 多处前台RCE漏洞复现
0x01 产品简介 WAVLINK是中国睿因科技(WAVLINK)公司开发的一款路由器。 0x02 漏洞概述 WAVLINK路由器mesh.cgi、nightled.cgi、live-api.cgi等接口处存在命令执行漏洞,攻击者可通过该漏洞获取服务器权限。包含型号WN530HG4、WN531G3、WN572HG3、WN535G3、WN575A4等。 0x…...
互联网中的商品超卖问题及其解决方案:Java中Redis结合UUID的应用
前言 在设计商品下单和库存扣减,你一定遇到过这样的问题,库存扣减为0了,可是消费者还能下单,并将订单信息保存到了数据库里,针对商品超卖问题,作此篇以解决。 随着互联网商业的飞速发展,商品超…...
mysql:查看线程缓存中的线程数量
使用命令show global status like Threads_cached;可以查看线程缓存中的线程数量。 例如,查询线程缓存中的线程数量如下: 然后启动应用程序,使用连接,查询如下: 由查询结果可以看到,线程缓存中的线程数量…...
线性表,也是Java中数组的知识点!
线性表定义: 由n (n≥0)个数据特性相同的元素构成的有限序列称为线性表,(n0)的时候被称为空表。 线性表的顺序表示 线性表的顺序存储又被称为顺序表 优点 无需为表示表中元素之间的逻辑关系而增加额外的存储空间可以随意读取任意位置的元素 缺点 插入…...
java使用面向对象实现图书管理系统
꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …...
2023 英特尔On技术创新大会直播 |我感受到的“芯”魅力
文章目录 每日一句正能量前言AI时代,云与PC结合为用户带来更好体验全新处理器,首次引入针对人工智能加速的NPU大模型时代,软硬结合带来更好训练成果后记 每日一句正能量 成长是一条必走的路路上我们伤痛在所难免。 前言 在2023年的英特尔On技…...
Atium Designer 23 全新功能-丝印制备,解决DFM问题
进行PCB设计时需要养成良好的设计习惯,才能保证后期的生产效果。例如整板上需要保证丝印跟阻焊的间距规则避免产生丝印重叠造成的PCB制造设计(DFM)问题。丝印重叠阻焊的影响有如下: 1)PCB板后期打样,一般是…...
怎样做平台网站/seo长沙
环境描述:已经存在一个MySQL的实例,端口号为3306,配置文件/etc/my.cnf,数据目录/data/mysql,现在需要重新添加一个端口号为3307端口的MySql的实例。1、关闭原有的默认端口3306的mysql[rootwww.cndba.cn /]# service mysql stop2、拷贝或创建数…...
网站建设外包被骗/百度推广怎么开户
jQuery实现倒计时效果-杨秀徐 本实例效果:剩余368天22小时39分57秒结束 代码简单易懂,适用各种倒计时; http://www.cnblogs.com/sntetwt/category/287335.html 12345678910111213141516171819202122232425262728293031323334353637383940414…...
做兼职的翻译网站吗/广告推销
本期教程我们将和小伙伴们一起研究如何使用计算机视觉和图像处理技术来检测汽车在行驶中时汽车是否在改变车道!大家一定听说过使用OpenCV 的haar级联文件可以检测到面部、眼睛等,但是如果目标是汽车,公共汽车呢? 1.数据集本教程将…...
日本真人做爰无遮挡视频免费网站/关键词优化排名哪家好
我认为这是一套适合初学者由浅到深的文章,所以强烈推荐给大家,作者从基础讲到最近比较火的漏洞,可能有些人看来是浅了些,但是的确很适合想干点啥但又不知道怎么办的菜鸟们 。 第一节,伸展运动。这节操我们要准备道具&a…...
网站建设 环讯传媒/优化网站排名方法教程
w7 64位/32位电脑系统支持多大内存?计算机上不同的操作电脑系统对内存的支持是有限度的,且因为主板、CPU的存在,这样的限制只会更小,但还在用户可以接受的范围内。想知道什么原因限制了内存极限吗?请看下文详细介绍。w…...
网上做任务网站/买卖网站
随着人脸识别技术的逐渐成熟及普及,在各个领域行业的场景落地应用,如刷脸支付、刷脸门禁、刷脸解锁…逐渐在改变着人们的生活工作,推动行业转型升级。 以办公场所为例,人脸识别产品在办公场景应用的范围越来越广泛,为…...