当前位置: 首页 > news >正文

【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

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

相关文章:

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

文章目录 前言正文一、项目简介二、核心代码2.1 pom.xml 依赖配置2.2 ExcelHeadMapFactory2.3 ExcelDataLinkedHashMap2.4 自定义注解 ExcelExportBean2.5 自定义注解 ExcelColumnTitle2.6 建造器接口 Builder2.7 表格工具类 ExcelUtils2.8 GsonUtil2.9 模版类 ExportDynamicCo…...

解决 Hive 外部表分隔符问题的实用指南

简介&#xff1a; 在使用 Hive 外部表时&#xff0c;分隔符设置不当可能导致数据导入和查询过程中的问题。本文将详细介绍如何解决在 Hive 外部表中正确设置分隔符的步骤。 问题描述&#xff1a; 在使用Hive外部表时&#xff0c;可能会遇到分隔符问题。这主要是因为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程序&#xff08;简例&#xff09; 03. ROS学习笔记(三)—好用的终端Terminator 04. ROS学习笔记(四)—使用 VScode 启动launch文件运行多个节点 05. ROS学习笔…...

【RTOS学习】源码分析(信号量和互斥量 事件组 任务通知)

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《RTOS学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f353;信号量和互斥量&#x1f345;创建&#x1f345;Take&#x1f345;Give &#x…...

1316:【例4.6】数的计数(Noip2001) 代码+解析

1316&#xff1a;【例4.6】数的计数(Noip2001) 【题目描述】 我们要求找出具有下列性质数的个数&#xff08;包括输入的自然数n &#xff09;。先输入一个自然数n(n≤1000)&#xff0c;然后对此自然数按照如下方法进行处理&#xff1a;不作任何处理&#xff1b;在它的左边加上一…...

征集倒计时 | 2023年卓越影响力榜单-第四届中国产业创新奖报名即将截止

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

vue的语法模板与数据绑定的说明

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

VueCron使用方法

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

SpringBlade export-user SQL 注入漏洞复现

0x01 产品简介 SpringBlade 是一个由商业级项目升级优化而来的 SpringCloud 分布式微服务架构、SpringBoot 单体式微服务架构并存的综合型项目。 0x02 漏洞概述 SpringBlade v3.2.0 及之前版本框架后台 export-user 路径存在安全漏洞,攻击者利用该漏洞可通过组件customSqlS…...

结构体的一些补充知识

1、结构体后面分号前面的名字是什么意思。 在C中&#xff0c;结构体的定义格式为&#xff1a; struct <结构体名> {// 成员变量和成员函数 };在这个定义中&#xff0c;<结构体名>就是结构体的名称&#xff0c;而这个名称位于结构体定义的末尾&#xff0c;分号之前…...

20V升26V 600mA升压型LED驱动芯片,PWM调光芯片-AH1160

AH1160是一个功能强大的升压型LED驱动芯片&#xff0c;专为需要精确控制LED亮度的PWM调光应用而设计。它可将20V输入电压升压至26V&#xff0c;同时提供稳定的600mA电流输出&#xff0c;适用于各种LED照明设备。 芯片特点&#xff1a; 1. 输入电压范围&#xff1a;AH1160可在…...

如何在Go中制作HTTP服务器

引言 许多开发人员至少会花一些时间创建服务器,以便在互联网上分发内容。HTTP (Hypertext Transfer Protocol,超文本传输协议)提供了大部分这些内容,无论是请求一张猫的图片还是请求加载你正在阅读的教程。Go标准库为创建HTTP服务器以提供web内容或向这些服务器发出HTTP请求…...

Linux笔记---系统信息

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux学习 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 命令 1. uname - 显示系统信息 2. hostname - 显示或设置系统主机名 3. top - 显示系统资源使用情况 4. df - 显示磁盘空间使用情…...

最新版android stuido加上namespace

每个 Android 模块都有一个命名空间&#xff0c;此命名空间用作其生成的 命名空间由模块的 build.gradle 文件中的 namespace 属性定义&#xff0c;如以下代码段所示。namespace 最初会设为您在创建项目时选择的软件包名称。 Kotlin Groovy android {namespace "com.ex…...

Wireshark基础及捕获技巧

第一章&#xff1a;Wireshark基础及捕获技巧 1.1 Wireshark基础知识回顾 1.2 高级捕获技巧&#xff1a;过滤器和捕获选项 1.3 Wireshark与其他抓包工具的比较 第二章&#xff1a;网络协议分析 2.1 网络协议分析&#xff1a;TCP、UDP、ICMP等 2.2 高级协议分析&#xff1a;HTTP…...

Windows下Navicat15.0连接Oracle11g报ORA-28547解决

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

21 Vue3中使用v-for遍历对象数组

概述 使用v-for遍历对象数组在真实的开发中也属于非常常见的用法&#xff0c;需要重点掌握。 因为目前流行的是前后端分离开发&#xff0c;在前后端分离开发中&#xff0c;最常需要处理的就是对象数组类型的数据了。 比如&#xff0c;将员工信息渲染到表格中。 这节课我们就…...

深入理解Java自定义异常与全局异常处理 @RestControllerAdvice

异常主要是包括编译时的异常和运行时的异常。编译时的异常可以通过捕获异常获取&#xff0c;运行时候的异常主要是通过代码规范&#xff0c;或者测试。 Spring Boot提供了两种异常处理方式来统一处理和维护异常信息。 第一种方式是使用RestControllerAdvice注解与ExceptionHand…...

h5页面跳转微信小程序(最简单的方法|URL Scheme)

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

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...