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

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

文章目录

  • 前言
  • 正文
    • 一、POM依赖
    • 二、核心Java文件
      • 2.1 自定义表头注解 ExcelColumnTitle
      • 2.2 自定义标题头的映射接口
      • 2.3 自定义有序map存储表内数据
      • 2.4 表头工厂
      • 2.5 表flag和表头映射枚举
      • 2.6 测试用的实体
        • 2.6.1 NameAndFactoryDemo
        • 2.6.2 StudentDemo
      • 2.7 启动类
      • 2.8 测试控制器
    • 三、测试
      • 测试1
      • 测试2
      • 测试3
      • 测试4

前言

日前,看到一个比较奇怪的导出功能。

需要根据不同的页面,以及指定不同的字段列表(任意顺序),然后导出对应的表格。

先假设一个场景:
假如你的系统有多个列表展示页,每页中可以依据筛选条件,调整展示的列的个数,顺序等。然后要求导出的时侯,导出一摸一样的格式。也就是“所见即所得”的表格。

那么基于以上场景,我们就来考虑下如何实现?
本文就是对以上场景功能的一个实现。目前仅支持单sheet,不支持数据聚合等。

正文

本文项目环境:
java 8,springboot2.2.0, easyexcel

一、POM依赖

<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></dependencies>

二、核心Java文件

此处粘贴全部的java文件
在这里插入图片描述

2.1 自定义表头注解 ExcelColumnTitle

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

2.2 自定义标题头的映射接口

此接口仅仅是用于规范实体,以及用于辅助实现导出功能。

package headbean;/*** excel头部映射接口,用于规范导出的实体类** @author feng*/
public interface ExcelHeadMapInterface {
}

2.3 自定义有序map存储表内数据

这个是表格导出时,字段数量,顺序的关键。

package headbean;import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;/*** 表格数据专用的map,带顺序,而且初始化的时候,依据指定的表头变量字段名确定导出数据的顺序** @author feng*/
public class ExcelDataLinkedHashMap<V> extends LinkedHashMap<String, V> {private static final long serialVersionUID = -8554095999151235982L;/*** 头部字段名缓存*/private final Set<String> headColumnNamesCache;/*** ExcelDataLinkedHashMap构造器** @param headColumnNames 表头字段变量名,例如:[name,studentNo,age,className]*/public ExcelDataLinkedHashMap(List<String> headColumnNames) {// 字段名去重headColumnNames = headColumnNames.stream().distinct().collect(Collectors.toList());// 构建字段名缓存this.headColumnNamesCache = new HashSet<>(headColumnNames);// 指定列数据排列顺序for (String headColumnName : headColumnNames) {this.put(headColumnName, null);}}@Overridepublic V put(String key, V value) {// 只保存字段名缓存中的key以及valueif (headColumnNamesCache.contains(key)) {return super.put(key, value);}return null;}
}

2.4 表头工厂

负责实现初始化表头字段名,以及后期使用时,从中获取表头信息。
核心功能是解析自定义的表头注解。

package factory;import enums.ExcelHeadBeanFlagEnum;
import headbean.ExcelColumnTitle;
import headbean.ExcelHeadMapInterface;import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;public class ExcelHeadMapFactory {/*** 全局表头名映射,ExcelHeadMapInterface实现类型为key,它内部变量的变量名和中文名映射为value*/private static final Map<Class<? extends ExcelHeadMapInterface>, Map<String, String>> HEAD_NAME_MAP = new HashMap<>();public static void addHeadClass(Class<? extends ExcelHeadMapInterface> headClass) {HEAD_NAME_MAP.put(headClass, mapToPrepareHead(headClass));}public static Map<String, String> getHeadMap(Class<? extends ExcelHeadMapInterface> headClass) {return HEAD_NAME_MAP.get(headClass);}public static Map<String, String> getHeadMapByFlag(String flag) {return getHeadMap(ExcelHeadBeanFlagEnum.getHeadClass(flag));}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.5 表flag和表头映射枚举

这个枚举,如果你的系统这类功能很多。可以设计为数据库的方式做映射。然后以查字典表的方式,来处理。当然使用枚举大概率是够用了。

package enums;import headbean.ExcelHeadMapInterface;
import headbean.NameAndFactoryDemo;
import headbean.StudentDemo;
import lombok.AllArgsConstructor;
import lombok.Getter;import java.util.Arrays;/*** 表头flag枚举,映射flag与对应的实体类型;主要是可以根据flag找到对应实体类型。** @author feng*/
@Getter
@AllArgsConstructor
public enum ExcelHeadBeanFlagEnum {NAME_AND_FACTORY_DEMO("NameAndFactoryDemo", NameAndFactoryDemo.class),STUDENT_DEMO("StudentDemo", StudentDemo.class);private final String flag;private final Class<? extends ExcelHeadMapInterface> headClass;public static Class<? extends ExcelHeadMapInterface> getHeadClass(String flag) {return Arrays.stream(values()).filter(bean -> bean.getFlag().equals(flag)).findFirst().orElseThrow(RuntimeException::new).getHeadClass();}
}

2.6 测试用的实体

2.6.1 NameAndFactoryDemo
package headbean;import lombok.Data;@Data
public class NameAndFactoryDemo implements ExcelHeadMapInterface {@ExcelColumnTitle("名字")private String name;@ExcelColumnTitle("工厂")private String factory;
}
2.6.2 StudentDemo
package headbean;import lombok.Data;@Data
public class StudentDemo implements ExcelHeadMapInterface {@ExcelColumnTitle("姓名")private String name;@ExcelColumnTitle("年龄")private Integer age;@ExcelColumnTitle("学号")private String studentNo;@ExcelColumnTitle("班级")private String className;
}

2.7 启动类

主要是项目启动后,注册表头数据到内存。

package org.feng;import factory.ExcelHeadMapFactory;
import headbean.ExcelHeadMapInterface;
import headbean.NameAndFactoryDemo;
import 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<? extends ExcelHeadMapInterface>> needRegisterExcelHeadClassList = new ArrayList<>();needRegisterExcelHeadClassList.add(NameAndFactoryDemo.class);needRegisterExcelHeadClassList.add(StudentDemo.class);needRegisterExcelHeadClassList.forEach(ExcelHeadMapFactory::addHeadClass);}
}

2.8 测试控制器

package org.feng;import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.WriteSheet;
import enums.ExcelHeadBeanFlagEnum;
import factory.ExcelHeadMapFactory;
import headbean.ExcelDataLinkedHashMap;
import headbean.ExcelHeadMapInterface;
import headbean.NameAndFactoryDemo;
import 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.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.function.BiFunction;@Controller
@RequestMapping("/excel")
public class ExcelDemoController {@GetMapping("/exportDy")public String exportDy(@RequestParam("flag")String flag,@RequestParam("table")List<String> table, HttpServletResponse response) throws IOException {String fileName = System.currentTimeMillis() + ".xlsx";Class<? extends ExcelHeadMapInterface> headClass = ExcelHeadBeanFlagEnum.getHeadClass(flag);Map<String, String> namedPrepareHeadMap = ExcelHeadMapFactory.getHeadMap(headClass);Map<String, String> head = new LinkedHashMap<>();for (String fieldName : table) {head.put(namedPrepareHeadMap.get(fieldName), fieldName);}List<Map<String, String>> excelDataList = new ArrayList<>();excelDataList.add(head);// 制造假数据for (BiFunction<Class<? extends ExcelHeadMapInterface>, List<Map<String, String>>, Boolean> biFunction : bizList) {Boolean applied = biFunction.apply(headClass, excelDataList);if(applied) {break;}}byte[] bytes = easyOut(excelDataList);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";}static final List<BiFunction<Class<? extends ExcelHeadMapInterface>, List<Map<String, String>>, Boolean>> bizList = new ArrayList<>();@PostConstructprivate void init() {bizList.add(this::genStudentDemoData);bizList.add(this::genNameAndFactoryDemoData);}private boolean genStudentDemoData(Class<? extends ExcelHeadMapInterface> headClass, List<Map<String, String>> excelDataList) {if(headClass == StudentDemo.class) {Map<String, String> headMap = excelDataList.get(0);for (int i = 0; i < 5; i++) {Collection<String> fieldNames = headMap.values();Map<String, String> data = new ExcelDataLinkedHashMap<>(new ArrayList<>(fieldNames));excelDataList.add(data);data.put("name", "张三"+(i+1));data.put("age", "年龄"+(i+1));data.put("studentNo", "学号"+(i+1));data.put("className", "班级"+(i+1));}return true;}return false;}private boolean genNameAndFactoryDemoData(Class<? extends ExcelHeadMapInterface> headClass, List<Map<String, String>> excelDataList) {if(headClass == NameAndFactoryDemo.class) {Map<String, String> headMap = excelDataList.get(0);for (int i = 0; i < 5; i++) {Collection<String> fieldNames = headMap.values();Map<String, String> data = new ExcelDataLinkedHashMap<>(new ArrayList<>(fieldNames));excelDataList.add(data);data.put("name", "张三"+(i+1));data.put("factory", "工厂"+(i+1));}return true;}return false;}/*** 导出数据(单sheet)* @param exportData key 是sheet名称,value是每个sheet里面的数据,支持自定义表头*/public static byte[] easyOut(List<Map<String, String>> exportData) {return easyOut(Collections.singletonMap("Sheet", exportData));}/*** 导出数据(多sheet)* @param exportData key 是sheet名称,value是每个sheet里面的数据,可以自定义*/public static byte[] easyOut(Map<String, List<Map<String, String>>> exportData) {// 导出数据ByteArrayOutputStream out = new ByteArrayOutputStream();com.alibaba.excel.ExcelWriter excelWriter = EasyExcel.write(out).build();int i=0;for (Map.Entry<String, List<Map<String, String>>> 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, String> cellData) {List<List<String>> head = new ArrayList<>();for (String key: cellData.keySet()) {head.add(Collections.singletonList(key));}return head;}private static List<List<String>> data(List<Map<String, String>> sheetData, boolean skipHead) {List<List<String>> 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;}
}

三、测试

测试1

http://localhost:8080/excel/exportDy?flag=StudentDemo&table=name,studentNo,age,className

获得的表格内容为:
在这里插入图片描述

测试2

http://localhost:8080/excel/exportDy?flag=StudentDemo&table=name,studentNo,age

获得的表格内容为:
在这里插入图片描述

测试3

http://localhost:8080/excel/exportDy?flag=NameAndFactoryDemo&table=factory,name
获得的表格内容为:
在这里插入图片描述

测试4

http://localhost:8080/excel/exportDy?flag=StudentDemo&table=className,name,studentNo
获得的表格内容为:
在这里插入图片描述

相关文章:

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

文章目录 前言正文一、POM依赖二、核心Java文件2.1 自定义表头注解 ExcelColumnTitle2.2 自定义标题头的映射接口2.3 自定义有序map存储表内数据2.4 表头工厂2.5 表flag和表头映射枚举2.6 测试用的实体2.6.1 NameAndFactoryDemo2.6.2 StudentDemo 2.7 启动类2.8 测试控制器 三、…...

代码随想录算法训练营第四十二天 _ 动态规划_01背包问题、416.分割等和子集。

学习目标&#xff1a; 动态规划五部曲&#xff1a; ① 确定dp[i]的含义 ② 求递推公式 ③ dp数组如何初始化 ④ 确定遍历顺序 ⑤ 打印递归数组 ---- 调试 引用自代码随想录&#xff01; 60天训练营打卡计划&#xff01; 学习内容&#xff1a; 二维数组处理01背包问题 听起来…...

市场上好用的aspera替代方案,你知道哪些

Aspera作为一个高速文件传输方案曾经非常受欢迎&#xff0c;但是其昂贵的价格却限制了许多用户的选择&#xff0c;因此市场上出现了众多Aspera替代方案&#xff0c;本文将会介绍市场上最好的Aspera替代方案。 最近几年&#xff0c;网络传输已成为现代商业运作中必不可少的一部…...

Stm32_串口的帧(不定长)数据接收

目录标题 前言1、串口中断接收固定帧头帧尾数据1.1、任务需求1.2、实现思路1.3、程序源码&#xff1a; 2、串口中断接收用定时器来判断帧结束3、串口中断接收数据空闲中断3.1、串口的空闲中断3.2、实现思路3.3、程序源码 4、串口的空闲中断DMA转运4.1、DMA简介4.2、DMA模式4.3、…...

L0、Linux常用命令

一、防火墙&#xff1a; 在 Linux 中&#xff0c;关闭防火墙可以使用不同的命令&#xff0c;这取决于你所使用的防火墙软件。在一些常见的 Linux 发行版中&#xff0c;防火墙可能是 iptables 或 firewalld两种&#xff1a; centos6使用iptables作为默认防火墙&#xff1b;cento…...

Golang实践录:读取toml配置

本文对 toml 文件进行解析。 下载 对于toml格式文件&#xff0c;golang 有很多库可以解释 yaml 文件&#xff0c;如toml、viper。由于 viper 可解析格式较多&#xff0c;本文采用该库。 toml语法规则 toml语法规则在官方中文文档上有说明&#xff0c;这里直接使用。 TOML 是…...

超大规模集成电路设计----基于阵列的可编程逻辑(七)

本文仅供学习&#xff0c;不作任何商业用途&#xff0c;严禁转载。本篇文章绝大部分资料来自中国科学院段成华教授PPT 超大规模集成电路设计----基于阵列的可编程逻辑&#xff08;七&#xff09; 7.1 引言7.1.1.回顾7.1.2. 数字逻辑系列Digital Logic Families7.1.3.从定制到半…...

深入探索FastAPI单元测试:使用TestClient轻松测试你的API

原文&#xff1a;深入探索FastAPI单元测试&#xff1a;使用TestClient轻松测试你的API-51CTO.COM 当使用FastAPI进行单元测试时&#xff0c;一个重要的工具是TestClient类。TestClient类允许我们模拟对FastAPI应用程序的HTTP请求&#xff0c;并测试应用程序的响应。这使我们能…...

基于ssm小型企业办公自动化系统论文

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对小型企业办公信息管理混乱&#xff0c;出错率高&#xff0c;信息安全…...

CasADi - 最优控制开源 Python/MATLAB 库

系列文章目录 文章目录 系列文章目录前言一、介绍1.1 CasADi 是什么&#xff1f;1.2 帮助与支持1.3 引用 CasADi1.4 阅读本文档 二、获取与安装三、符号框架3.1 符号 SX3.1.1 关于命名空间的说明3.1.2 C 用户注意事项 3.2 DM3.3 符号 MX3.4 SX 和 MX 混合使用3.5 稀疏类3.5.1 获…...

Java中使用String字符串的注意事项

引言 介绍字符串在Java中的重要性和普遍性&#xff0c;以及本文将讨论的注意事项。 1. 字符串是不可变的 解释Java中字符串是不可变的概念&#xff0c;即一旦创建&#xff0c;字符串对象的值就不能被修改。强调在对字符串进行操作时应当创建新的字符串对象而不是修改原有的对…...

离线数仓构建案例一

数据采集 日志数据&#xff08;文件&#xff09;到Kafka 自己写个程序模拟一些用户的行为数据&#xff0c;这些数据存在一个文件夹中。 接着使用flume监控采集这些文件&#xff0c;然后发送给kafka中待消费。 1、flume采集配置文件 监控文件将数据发给kafka的flume配置文件…...

nginx优雅如何优雅的接管【跨域配置】

跨域问题太常见了&#xff0c;这里不做详细赘述。文章主要想说一下&#xff0c;如何统一管理和更好的来管理 跨域配置 跨域的常见配置有两种 后台代码设置和网关设置 1、后台代码设置 以springboot为例代码如下&#xff08;水一下文章长度...&#xff09; Configuration pu…...

远离危险的购买手机的渠道

今年上半年从淘宝特价版上面的官方旗舰店买了一个oppo手机&#xff0c;第一次买我打算不要了&#xff0c;所以就退了回去&#xff0c;过了几天我又觉得还是买一个比较好&#xff0c;所以就又买了一个&#xff0c;型号我绝不说了700-1000z这个价位的手机带个高通骁龙芯片的&…...

外包干了2个多月,技术明显有退步了。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...

【Java项目管理工具】Maven

Maven 文章目录 Maven一、简介二、安装和配置三、GAVP四、IDEA Maven Java Web工程五、插件、命令、生命周期六、依赖配置七、构建配置八、依赖传递与依赖冲突九、Maven工程继承和聚合关系9.1 工程继承关系9.2 工程聚合关系 十、Maven私服10.1 Nexus下载安装10.2 Nexus上的各种…...

solidity案例详解(六)服务评价合约

有服务提供商和用户两类实体&#xff0c;其中服务提供商部署合约&#xff0c;默认诚信为true&#xff0c;用户负责使用智能合约接受服务及评价&#xff0c;服务提供商的评价信息存储在一个映射中&#xff0c;可以根据服务提 供商的地址来查找评价信息。用户评价信息&#xff0c…...

使用kubeadm搭建高可用的K8s集群

文章目录 1. 安装要求2. 准备环境3. 所有master节点部署keepalived3.1 安装相关包和keepalived3.2配置master节点3.3 启动和检查 4. 部署haproxy4.1 安装4.2 配置4.3 启动和检查 5. 所有节点安装Docker/kubeadm/kubelet5.1 安装Docker5.2 添加阿里云YUM软件源5.3 安装kubeadm&a…...

C#图像处理OpenCV开发指南(CVStar,07)——通用滤波(Filter2D)的实例代码

1 函数定义 void Filter2D (Mat src, Mat dst, int ddepth, InputArray kernel, Point anchor Point(-1,-1), double delta 0, int borderType BORDER_DEFAULT ) 1.1 原型 #include <opencv2/imgproc.hpp> Convolves an image wit…...

c++函数模板STL详解

函数模板 函数模板语法 所谓函数模板&#xff0c;实际上是建立一个通用函数&#xff0c;其函数类型和形参类型不具体指定&#xff0c;用一个虚拟的类型来代表。这个通用函数就称为函数模板。 凡是函数体相同的函数都可以用这个模板来代替&#xff0c;不必定义多个函数&#xf…...

从零搭建一个智能视频监控系统:3D定位、ONVIF控制与Python UI实战

从零搭建智能视频监控系统&#xff1a;3D定位、ONVIF控制与Python UI实战 在智能安防和物联网应用蓬勃发展的今天&#xff0c;具备3D定位功能的视频监控系统正成为行业新宠。本文将带您从零开始&#xff0c;基于树莓派或普通PC&#xff0c;结合支持ONVIF协议的球型摄像机&#…...

STM32驱动WS2812灯珠颜色错乱?可能是你的GRB顺序和位序搞反了!

STM32驱动WS2812灯珠颜色错乱&#xff1f;GRB顺序与位序的深度解析 当你第一次用STM32成功点亮WS2812灯珠时&#xff0c;那种成就感难以言表。但紧接着&#xff0c;你可能遇到了一个令人困惑的问题&#xff1a;明明在代码里设置了纯红色&#xff08;255, 0, 0&#xff09;&…...

告别UUID!用Apache Commons Lang3的RandomStringUtils生成更灵活的随机字符串(Java实战)

告别UUID&#xff01;用Apache Commons Lang3的RandomStringUtils生成更灵活的随机字符串&#xff08;Java实战&#xff09; 在Java开发中&#xff0c;生成随机字符串的需求无处不在——从用户邀请码、临时密码到订单编号&#xff0c;我们经常需要快速生成一串既随机又可读的字…...

【更新至2025年】2001-2025年上市公司年报文本数据(txt格式)

【更新至2025年】2001-2025年上市公司年报文本数据&#xff08;txt格式&#xff09; 1、时间&#xff1a;2001-2025年 2、来源&#xff1a;巨潮资讯网 3、范围&#xff1a;A股上市公司 4、样本量&#xff1a;共7.2W份 5、说明&#xff1a;上市公司年报文本数据可以挖掘文本…...

护眼钢化膜是智商税?圆偏振光+AR降反射实测,观复盾用硬核技术给出答案

护眼钢化膜是智商税&#xff1f;圆偏振光AR降反射实测&#xff0c;观复盾用硬核技术给出答案“花上百块买的护眼钢化膜&#xff0c;贴上后屏幕又黄又暗&#xff0c;眼睛反而更累了。”这样的抱怨在数码社区里比比皆是。与此同时&#xff0c;也有用户表示换了圆偏振光膜后&#…...

【BUUCTF】【WEB】ReadlezPHP

考点&#xff1a;打开题目&#xff0c;发现页面有点阴森&#xff1a;右键没有任何反应&#xff0c;那就右上角三个点&#xff1a;更多工具->开发者工具OK没有任何线索&#xff0c;那就用bp看看。拉倒最下面&#xff0c;发现右下角一个文件./time.php?source这可能是一个线索…...

智能服装开发实战:基于NeoPixel与Arduino的动态光效设计与实现

1. 项目概述&#xff1a;打造一件会“流动”的智能光效裙几年前&#xff0c;当我第一次看到Phil Burgess的“Ooze Master 3000”代码时&#xff0c;就被那个模拟粘稠液体缓慢滴落的灯光动画迷住了。它不像普通的彩虹轮转那么直白&#xff0c;而是有一种有机的、近乎生物感的动态…...

NotebookLM+遥感影像分析实战:水稻倒伏预警模型搭建(含Landsat-8元数据自动标注技巧)

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;NotebookLM农业科学研究 NotebookLM 是 Google 推出的基于 AI 的研究协作者工具&#xff0c;专为知识密集型工作设计。在农业科学研究中&#xff0c;它能高效整合多源异构文献&#xff08;如 FAO 报告、PubMed…...

基于DS18B20与WipperSnapper的无代码物联网温度监测方案

1. 项目概述&#xff1a;当经典传感器遇上无代码物联网 在物联网和智能硬件的世界里&#xff0c;温度监测是一个永恒的基础需求。无论是想监控家里的温室环境、记录鱼缸水温&#xff0c;还是追踪服务器机柜的热量变化&#xff0c;你都需要一个可靠、精确且易于集成的温度传感器…...

双足机器人步态规划算法与动平衡控制【附仿真】

✨ 长期致力于双足机器人、步态规划、动平衡控制、运动发散分量、模型预测控制、二次优化、可视化仿真研究工作&#xff0c;擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流&#xff0c;点击《获取方式》 &#xff08;1&#xff09…...