POI、Easy Excel操作Excel
文章目录
- 1.常用的场景
- 2.基本功能
- 3.Excel在Java中是一个对象
- 4. 简单的写(07版本(.xlsx)Excel)
- 大文件写HSSF
- 大文件写XSSF
- 大文件写SXSSF
- 5. Excel读
- 5.1 读取遇到类型转化问题该怎么解决
- 5.2 遇到Excel公式怎么办
- 6. Easy Excel
- 6.1简单的写
- 6.2 简单的读
1.常用的场景
-
- 将用户信息导出为Excel表格(导出数据)
-
- 将Excel表中的信息录入到网站数据库中(习题上传)大大减轻网站录入量。开发中经常会用到设计处理Excel,如导入Excel和导出Excel
-
- 目前操作Excel比较流行的就是Apach的POI和阿里巴巴的Easy Excel。
-
- POI官网:https://poi.apache.org/
-
- Easy Excel官网:https://github.com/alibaba/easyexcel
2.基本功能
- 1.POI的基本功能:(会比较麻烦,可能会出现OOM(Out Of Memory)异常)
其中:第一个HSSF和XSSF的区别(前者用03版本的Excel,后者用07年的Excel)- 1.1 内存问题:
POI 当数据为100w的时候,先将100w的数据先加载到内存当中(OOM),再写入文件
- 1.1 内存问题:
-
- Easy Excel:
- 2.1 简介,官方文档:(已经迁移到)https://easyexcel.opensource.alibaba.com/docs/current/
- 2.2 内存问题:
相对于POI来说,上图反映了POI会把所有内容加载到内存当中,而Easy Excel会一行一行通过磁盘返回。
3.Excel在Java中是一个对象
-
- 工作簿
-
- 工作表
-
- 行
-
- 列
4. 简单的写(07版本(.xlsx)Excel)
03版本代码中有标注,生成文件时候,需要改后缀为:(.xls)
package com.dapeng;import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.joda.time.DateTime;
import org.junit.Test;import java.io.FileNotFoundException;
import java.io.FileOutputStream;/*** @Description* @Author zhaopeng* @Date 2023/10/13 9:49*/
public class ExcelWriteTest {@Testpublic void testWrite() throws Exception {String PATH = "D:\\ExcelTest\\";// 1.创建一个工作簿(SXSSF优化版的07的工作簿,HSSF是03年的)// Workbook workbook = new HSSFWorkbook();03版本Workbook workbook = new SXSSFWorkbook();// 2. 创建一个工作表Sheet sheet = workbook.createSheet("我的工作表");// 3. 创建一行(0代表从第一行开始创建)Row row1 = sheet.createRow(0);// 4. 创建一列(0代表从第一列开始创建),Cell代表一个单元格Cell cell11 = row1.createCell(0);Cell cell12 = row1.createCell(1);// 5. 给单元格赋值cell11.setCellValue("测试数据1-1");cell12.setCellValue("Cell12数据");// 来个第二行Row row2 = sheet.createRow(1);Cell cell21 = row2.createCell(0);Cell cell22 = row2.createCell(1);// 来个时间String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");cell21.setCellValue(time);cell22.setCellValue("第二行第二个数据");// 生成一张表FileOutputStream fileOutputStream = new FileOutputStream(PATH + "test.xlsx");workbook.write(fileOutputStream);fileOutputStream.close();}
}
效果:
大文件写HSSF
- 优点:过程中写入缓存,不操作磁盘,最后一次性写入磁盘,速度快
- 缺点:最多只能处理65535行,否则会抛出异常:
java.lang.IlleaglArgumentException:Invalid row number(65535) outside allowable rang (0..65535)
- 代码截图:(没有自己写–自己没有03版本的excel)
- 当超过65536 的时候会报错
大文件写XSSF
- 优点:可以写较大的数据量,如20万条。
- 缺点:写数据时非常慢,非常耗内存,也会发生内存溢出,如100万条。
@Testpublic void testWrite07BigData() throws Exception {long startTime = System.currentTimeMillis();// 1.创建一个工作簿(SXSSF优化版的07的工作簿,HSSF是03年的)Workbook workbook = new XSSFWorkbook();// 2. 创建一个工作表Sheet sheet = workbook.createSheet("我的工作表");// 3.循环写入大数据for (int i = 0; i < 100000; i++) {// 创建行Row row = sheet.createRow(i);for (int j = 0; j < 10; j++) {// 创建列jCell cell = row.createCell(j);// 给列赋值cell.setCellValue(j);}}System.out.println("完事了");// 生成一张表FileOutputStream fileOutputStream = new FileOutputStream(PATH + "07BigData.xlsx");workbook.write(fileOutputStream);fileOutputStream.close();long end = System.currentTimeMillis();System.out.println("花费了:" + (double)(end - startTime)/1000 + "秒");}
大文件写SXSSF
- 优点:可以写非常大的数据量,如100万条甚至更多条,写数据快,占用更少的内存。
- Demo(没有多大变化,只用了SXSSFWorkbook类)
@Testpublic void testWrite07BigData() throws Exception {long startTime = System.currentTimeMillis();// 1.创建一个工作簿(SXSSF优化版的07的工作簿,HSSF是03年的)Workbook workbook = new SXSSFWorkbook();// 2. 创建一个工作表Sheet sheet = workbook.createSheet("我的工作表");// 3.循环写入大数据for (int i = 0; i < 1000000; i++) {// 创建行Row row = sheet.createRow(i);for (int j = 0; j < 10; j++) {// 创建列jCell cell = row.createCell(j);// 给列赋值cell.setCellValue(j);}}System.out.println("完事了");// 生成一张表FileOutputStream fileOutputStream = new FileOutputStream(PATH + "07BigData.xlsx");workbook.write(fileOutputStream);fileOutputStream.close();// 清除临时文件((SXSSFWorkbook)workbook).dispose();long end = System.currentTimeMillis();System.out.println("花费了:" + (double)(end - startTime)/1000 + "秒");}
5. Excel读
- Demo:
package com.dapeng;import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;import java.io.FileInputStream;/*** @Description* @Author zhaopeng* @Date 2023/10/13 10:43*/
public class ExcelReadTest {String PATH = "D:\\ExcelTest\\";@Testpublic void testRead() throws Exception{// 1. 获取文件流读取文件FileInputStream inputStream = new FileInputStream(PATH + "test.xlsx");// 2. 创建一个工作簿Workbook workbook = new XSSFWorkbook(inputStream);// 3. 得到表(通过下标);Sheet sheet = workbook.getSheetAt(0);// 4. 得到行(第一行)Row row = sheet.getRow(0);// 5. 获取第一个数据Cell cell = row.getCell(0);// 6.输出数据System.out.println(cell.getStringCellValue());inputStream.close();}
}
5.1 读取遇到类型转化问题该怎么解决
@Testpublic void testReadTeyp() throws Exception {// 1. 获取文件流读取文件FileInputStream inputStream = new FileInputStream(PATH + "test.xlsx");// 2. 创建一个工作簿Workbook workbook = new XSSFWorkbook(inputStream);// 3. 得到表(通过下标);Sheet sheet = workbook.getSheetAt(0);// 4. 获取第一行标题Row rowTitle = sheet.getRow(0);// 4.1 获取标题的数量if (rowTitle != null) {// 必须掌握,拿到所有的列int cells = rowTitle.getPhysicalNumberOfCells();for (int i = 0; i < cells; i++) {Cell cell = rowTitle.getCell(i);if (cell != null) {int cellType = cell.getCellType();String cellValue = cell.getStringCellValue();System.out.print(cellValue + " | ");}}}// 获取行的总数int rowCounts = sheet.getPhysicalNumberOfRows();for (int rowNum = 1; rowNum < rowCounts; rowNum++) {// 获取每一行Row row = sheet.getRow(rowNum);if (row != null) {// 读取列int columns = rowTitle.getPhysicalNumberOfCells();for (int cellColumn = 0; cellColumn < columns; cellColumn++) {System.out.print("[" + rowNum + "-" + cellColumn + "]");// 获取每一个数据Cell cell = row.getCell(cellColumn);// 匹配列数据类型if (cell != null) {int cellType = cell.getCellType();String cellValue = "";switch (cellType) {case HSSFCell.CELL_TYPE_STRING: // 字符串System.out.print("[String]");cellValue = cell.getStringCellValue();break;case HSSFCell.CELL_TYPE_BOOLEAN: // 布尔类型System.out.print("[BOOLEAN]");cellValue = String.valueOf(cell.getBooleanCellValue());break;case HSSFCell.CELL_TYPE_BLANK: // 空System.out.print("[BLANK]");break;case HSSFCell.CELL_TYPE_NUMERIC: // 数字(日期和数字)System.out.print("[NUMERIC]");if (HSSFDateUtil.isCellDateFormatted(cell)) { // 如果是日期类型System.out.print("[日期]");Date time = cell.getDateCellValue();// 使用工具类把日期进行转换cellValue = new DateTime(time).toString("yyyy-MM-dd HH:mm:ss");} else {// 如果不是日期格式,防止数字过长System.out.print("[转换为字符串输出]");cell.setCellType(HSSFCell.CELL_TYPE_STRING);cellValue = cell.toString();}break;case HSSFCell.CELL_TYPE_ERROR: // 错误System.out.print("[数据类型错误]");break;}System.out.println(cellValue);}}}}inputStream.close();}
5.2 遇到Excel公式怎么办
@Testpublic void readMath() throws Exception{FileInputStream inputStream = new FileInputStream(PATH + "test.xlsx");// 读取Workbook workbook = new XSSFWorkbook(inputStream);Sheet sheet = workbook.getSheetAt(0);// 这个单元格前提有公式比如=SUM(A2:A4);Row row = sheet.getRow(4);Cell cell = row.getCell(0);// 1.拿到该工作簿的公式XSSFFormulaEvaluator formulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) workbook);// 输出单元格内容,先获取类型int cellType = cell.getCellType();switch (cellType){case HSSFCell.CELL_TYPE_FORMULA: //公式// 先获取公式String formula = cell.getCellFormula();System.out.println(formula); // 输出公式// 计算得到值CellValue evaluate = formulaEvaluator.evaluate(cell);System.out.println(evaluate);// 输出计算好的值String value = evaluate.formatAsString();// 把值转化为String输出System.out.println(value);break;}}
6. Easy Excel
6.1简单的写
参考官方文档:https://easyexcel.opensource.alibaba.com/docs/current/quickstart/write
- 导入依赖
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.0-beta2</version>
</dependency>
- 数据来源:
private List<Entity> data() {List<Entity> list = new ArrayList<Entity>();for (int i = 0; i < 10; i++) {Entity data = new Entity();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}return list;}
- 一行代码导出Excel
// 根据List写入值@Testpublic void simpleWrite(){// 1. 当前的位置String PATH = "D:\\ExcelTest\\";String fileName= PATH + "esayExcel.xlsx";EasyExcel.write(fileName,Entity.class).sheet("easyExcel").doWrite(data());}
6.2 简单的读
参考:
- 先写一个类继承AnalysisEventListener并重写invoke方法,数据的处理逻辑全在这里。
package com.dapeng.DemoEntity;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;
import java.util.List;
import java.util.Map;/*** @Description* @Author zhaopeng* @Date 2023/10/13 15:31*/
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener extends AnalysisEventListener<DemoData> {/*** 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 5;List<DemoData> list = new ArrayList<>();private DemoDAO demoDAO;public DemoDataListener() {// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数demoDAO = new DemoDAO();}/*** 这个每一条数据解析都会来调用** @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}* @param context*/@Overridepublic void invoke(DemoData data, AnalysisContext context) {log.info("解析到一条数据:{}", JSON.toJSONString(data));System.out.println("解析到一条数据:{}" + JSON.toJSONString(data));list.add(data);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (list.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listlist.clear();}}/*** 所有数据解析完成了 都会来调用** @param context*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();log.info("所有数据解析完成!");}/*** 加上存储数据库*/private void saveData() {log.info("{}条数据,开始存储数据库!", list.size());demoDAO.save(list);log.info("存储数据库成功!");}
}
- 测试:
/*** 最简单的读* <p>* 1. 创建excel对应的实体对象 参照{@link DemoData}* <p>* 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}* <p>* 3. 直接读即可*/@Testpublic void simpleRead() {// 写法1:JDK8+ ,不用额外写一个DemoDataListener// since: 3.0.0-beta1String PATH = "D:\\ExcelTest\\";String fileName= PATH + "esayExcel.xlsx";// 这里默认每次会读取100条数据 然后返回过来 直接调用使用数据就行// 具体需要返回多少行可以在`PageReadListener`的构造函数设置EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();}
相关文章:

POI、Easy Excel操作Excel
文章目录 1.常用的场景2.基本功能3.Excel在Java中是一个对象4. 简单的写(07版本(.xlsx)Excel)大文件写HSSF大文件写XSSF大文件写SXSSF 5. Excel读5.1 读取遇到类型转化问题该怎么解决5.2 遇到Excel公式怎么办 6. Easy Excel6.1简单…...

网络安全(黑客)自学方向
每年报考网络安全专业的人数很多,但不少同学听说千万别学网络安全,害怕网络安全专业很难就业。下面就带大家深入了解一下网络安全专业毕业后可以干什么,包括网络安全专业的就业前景和方向等。 随着信息化时代的到来,网络安全行业…...
react写一个简单的3d滚轮picker组件
1. TreeDPicker.tsx文件 原理就不想赘述了, 想了解的话, 网址在: 使用vue写一个picker插件,使用3d滚轮的原理_vue3中支持3d picker选择器插件-CSDN博客 import React, { useEffect, useRef, Ref, useState } from "react"; import Animate from "../utils/an…...

Compose竖向列表LazyColumn
基础列表一 LazyColumn组件中用items加载数据,rememberLazyListState()结合rememberCoroutineScope()实现返回顶部。 /*** 基础列表一*/ Composable fun Items() {Box(modifier Modifier.fillMaxSize()) {val context LocalContext.currentval dataList arrayLi…...

6.自定义相机控制器
愿你出走半生,归来仍是少年! Cesium For Unity自带的Dynamic Camera,拥有优秀的动态展示效果,但是其对于场景的交互方式用起来不是很舒服。 通过模仿Cesium JS 的交互方式,实现在Unity中的交互: 通过鼠标左键拖拽实现场景平移通过…...

一文带你GO语言入门
什么是go语言? Go语言(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。Go语言的主要特点包括:- 简洁和简单 - 语法简单明快,易于学习和使用 特点 高效 编译速度快,执行效率高 并发支持 原生支持并发,利用goroutine实现高效的并发…...
前后端小项目链接
1.vue的创建 vue的项目创建 1.1 vue create vue_name 1.2 Babel Router(路由) CSS Pre-processors 路由可通过:npm i vue-router3.5.2 -S 下载 1.3less 1.4 In dedicated config files 1.5 启动命令:npm run serve 端口号在vue.config。js中配置 devS…...

编辑器功能:用一个快捷键来【锁定】或【解开】Inspector面板
一、需求 我有一个脚本,上面暴露了许多参数,我要在场景中拖物体给它进行配置。 如果不锁定Inspector面板的话,每次点击物体后,Inspector的内容就是刚点击的物体的内容,而不是挂载脚本的参数面板。 二、 解决 &…...

Vue 网络处理 - axios 异步请求的使用,请求响应拦截器(最佳实践)
目录 一、axiox 1.1、axios 简介 1.2、axios 基本使用 1.2.1、下载核心 js 文件. 1.2.2、发送 GET 异步请求 1.2.3、发送 POST 异步请求 1.2.4、发送 GET、POST 请求最佳实践 1.3、请求响应拦截器 1.3.1、拦截器解释 1.3.2、请求拦截器的使用 1.3.3、响应拦截器的使…...

关于W5500网卡使用过程的部分问题记录
某个项目中用到了W5500这种自带网络协议栈的网卡芯片,由于该项目开发时间很紧,就临时网上买了一些模块拼凑到了一套系统,经过验证果真这种拼积木的方法只能用在学生实验开发中,真不能拿来做工程应用,硬件太不稳定很容易…...

Unity DOTS World Entity ArchType Component EntityManager System概述
最近DOTS终于发布了正式的版本, 我们来分享以下DOTS里面地几个关键概念,方便大家上手学习掌握Unity DOTS开发。 Unity DOTS 中所有的Entities 都是被放到World世界中。每个Entity在它所在的World里面有唯一不同的ID号来区分。DOTS项目中可以同时有多个World。每个W…...

最详细STM32,cubeMX 点亮 led
这篇文章将详细介绍 如何在 stm32103 板子上点亮一个LED. 文章目录 前言一、开发环境搭建。二、LED 原理图解读三、什么是 GPIO四、cubeMX 配置工程五、解读 cubeMX 生成的代码六、延时函数七、控制引脚状态函数点亮 LED 八、GPIO 的工作模式九、为什么使用推挽输出驱动 LED总结…...

论文阅读:Image-to-Lidar Self-Supervised Distillation for Autonomous Driving Data
目录 摘要 Motivation 整体架构流程 技术细节 雷达和图像数据的同步 小结 论文地址: [2203.16258] Image-to-Lidar Self-Supervised Distillation for Autonomous Driving Data (arxiv.org) 论文代码:GitHub - valeoai/SLidR: Official PyTorch implementati…...
前端版本控制工具,常见的Git 和SVN
目录 前言GitGit简介Git的优势Git常用指令常见的Git服务 SVN (Subversion)SVN简介SVN的优势SVN常用指令SVN与Git的区别 👍 点赞,你的认可是我创作的动力! ⭐️ 收藏,你的青睐是我努力的方向! ✏️ 评论,你…...

C++ —— Tinyxml2在Vs2017下相关使用2(较文1更复杂,附源码)
相关链接 C —— Tinyxml2在Vs2017下相关使用1(附源码) tinyxml2简介 TinyXML2是一个简单,小巧,高效,CXML解析器,可以很容易地集成到其他程序中。TinyXML-2解析一个XML文档,并从中构建一个 可以…...

阿里内推强推的并发编程学习笔记,原理+实战+面试题,面面俱到!
并发编程 谈到并发编程,可能很多人都有过经验,甚至比我了解的更多。 那么并发与并行的区别又是什么? 并发编程是编程中的核心问题,实践中,当人们希望利用计算机处理一些现实世界问题,以及希望同时处理多…...
域名注册查询流程
域名注册查询怎么查域名是否被注册?域名注册查询如何查域名的过期时间和注册商?域名注册查询用什么工具?下面是关于域名注册查询流程介绍。 1、域名注册查询可以用什么工具? 这里可以使用聚查工具,聚查包括:whois 查询、建站历史查询、反链查询、P…...

【Linux学习笔记】代码编辑工具vim
1. vim工具基本模式的转换2. vim命令模式下的各种编辑命令2.1. 光标行定位2.2. 光标自由定位2.3. 复制粘贴2.4. 删除2.5. 文本的大小写替换2.6. 文本的替换2.7. 文本的前删后删2.8. 撤销操作 3. vim底行模式下的命令3.1. 设置行号与取消设置行号3.2. 分屏操作3.3. 在不退出vim的…...
Android Boring SSL
前期设置 SSLContext.getInstance(“TLS”)SSLContext.init()SSLContext.getSocketFactory()SSLSocketFactory.createSocket()NativeSsl.newInstance()BioWrapper 的创建ConscryptEngineSocket.startHandshake() TLS协商 state_start_connect(TLS)state_enter_early_data(TLS)s…...

中国人民大学与加拿大女王大学金融硕士项目:开启你的金融精英之路
在全球化的今天,金融行业的发展日新月异,对金融人才的需求也日益增长。为了满足这一需求,中国人民大学与加拿大女王大学联合推出了金融硕士项目,旨在培养具有国际视野、专业素养和创新能力的金融精英。 这一开创性的项目将两大世…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...