草庐IT

初次邂逅 EasyExcel

god23bin 2023-04-16 原文

前言

由于工作原因,有这种需求,就是把数据库中的数据导出成 Excel 表格,同时,也得支持人家用 Excel 表格导入数据到数据库。当前项目也是在用 EasyExcel,所以我不得不学啦!

以前学习的过程中,有听过 EasyExcel 这么一个东西,不过从来没用过,所以,正好借此机会学习,看看如何使用它来实现需求。

在学习 EasyExcel 的这段时间里,也了解到工作中这种导入导出的需求还是挺常见的,所以决定记录下来。

官方文档:https://easyexcel.opensource.alibaba.com/docs/current/

需求

用户点击导入按钮,就能够上传 Excel 文件,将 Excel 文件的数据导入到系统中。

用户勾选目标数据 id,点击导出按钮,就能将系统中的数据以 Excel 文件的格式下载到本地。

分析

导入,从用户的视角来看,就是导入 Excel 文件;从开发者的视角,或者说系统的视角来看,就是读取用户的 Excel 文件的数据到系统中(实际上是读取到计算机的内存中),最后将读取到的数据存储到数据库,EasyExcel 在导入的过程中进行了读操作

导出,同理,用户的视角就是导出,开发者的视角就是把系统的数据写入到用户的计算机上,即写操作

简而言之,涉及 IO 操作的,视角不同,说法不同(初学IO时就没搞清楚,为我后续的学习留下了大坑T_T!)。

当然我们也可以把导入说成写操作,毕竟数据是最终是存储在系统的数据库中的,即写到了系统的数据库里了。自己别搞混了就行。

准备

本 Demo 使用 Spring Boot 构建,配合 MyBaits Plus,以游戏数据导入和导出作为需求;一些工具依赖如下:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.10</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.72</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

依赖

今天 EasyExcel 主菜,需要加其依赖才能食用~

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.7</version>
</dependency>

配置

server:
  port: 4790

spring:
  application:
    name: easyexcel-demo
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/easy_excel_demo?useUnicode=true&autoReconnect=true&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull&characterEncoding=utf8
    username: root
    password: 123456

游戏实体类

咱们的游戏类就这些属性:id、游戏名称、价格、uuid,发售日期、创建时间、修改时间

/**
 * @author god23bin
 * @version 1.0
 * @description 游戏
 * @date 2022/10/21 16:51:02
 */
@Data
@TableName("t_game")
public class Game {

    @TableId(type = IdType.AUTO)
    private Long id;

    private String name;

    private Double price;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" ,timezone = "GMT+8")
    private Date releaseDate;

    @TableField(fill = FieldFill.INSERT)
    private String uuid;

    @TableField(fill = FieldFill.INSERT)
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" ,timezone = "GMT+8")
    private Date gmtCreate;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" ,timezone = "GMT+8")
    private Date gmtModified;
}

模型

啥是模型?别慌,先假设需要导入的 Excel 表格长这样:

那么这个就是所谓的模型啦,不管是还是,都需要相对应的对象,所以一般会编写一个读对象的类和写对象的类,当然,如果读写的表头字段都是一模一样,直接一个类就可以了,导入导出都用这个类。

读对象

读对象-GameImportExcelModel

/**
 * @author god23bin
 * @version 1.0
 * @description Game 导入的 Excel 数据模型(读对象)
 * @date 2022/10/21 17:18:50
 */
@Data
public class GameImportExcelModel {

    private String name;

    private Double price;

    private Date releaseDate;
}

写对象

写对象-GameExportExcelModel

/**
 * @author god23bin
 * @version 1.0
 * @description Game 导出的 Excel 数据模型(写对象)
 * @date 2022/10/21 17:18:50
 */
@Data
public class GameExportExcelModel {

    @ExcelProperty("游戏ID")
    private Long id;

    @ExcelProperty("游戏名")
    private String name;

    @ExcelProperty("价格")
    private Double price;

    @ExcelProperty("发售日期")
    private Date releaseDate;
}

实现

导入功能

用户点击导入按钮,就能够上传 Excel 文件,将 Excel 文件的数据导入到系统中。

前端实现一个上传文件的按钮,后端就接收这个文件,读取这个文件的数据,存储到数据库中。

开胃菜-后端

搭个整体的代码框架先!

持久层

GameMapper

@Mapper
public interface GameMapper extends BaseMapper<Game> {
}
业务层

GameService

/**
 * @author god23bin
 * @version 1.0
 * @description
 * @date 2022/11/8 14:36:43
 */
public interface GameService {

    /**
     * 导入Excel数据到数据库
     * @date 2022/11/8 14:38
     * @param file Excel文件
     * @return boolean
     **/
    boolean importExcel(MultipartFile file);
    
}

GameServiceImpl

/**
 * @author god23bin
 * @version 1.0
 * @description
 * @date 2022/11/8 14:40:08
 */
@Slf4j
@Service
public class GameServiceImpl extends ServiceImpl<GameMapper, Game> implements GameService {

    @Resource
    private GameMapper gameMapper;

    /**
     * 导入Excel数据到数据库
     *
     * @param file Excel文件
     * @return boolean
     * @date 2022/11/8 14:38
     **/
    @Override
    public boolean importExcel(MultipartFile file) {
        // 这里就需要用到「读监听器」了,需要我们自己实现
        return null;
    }

}
控制层

GameController

/**
 * @author god23bin
 * @version 1.0
 * @description
 * @date 2022/11/8 14:31:50
 */
@RestController
public class GameController {

    @Resource
    private GameService gameService;

    @PostMapping("/excel/import/game")
    public ResponseEntity<String> importExcel(@RequestPart("file") MultipartFile file) {
        gameService.importExcel(file);
        return new ResponseEntity<>("OK", HttpStatus.OK);
    }
}

正餐-读数据需要用到的监听器

对于读取,有一个监听器需要我们实现,根据文档的说明,这个监听器是不可以让 Spring 来管理的。

有个很重要的点 DemoDataListener 不能被 spring管理,要每次读取 excel都要 new,然后里面用到 spring 可以构造方法传进去

所以我们也不需要加上 @Component 注解把这个类作为组件让 Spring 扫描。直接一个普通的类就行

具体代码如下,需要知道的是:

  • 需要继承 AnalysisEventListener 类,参数化的类型(泛型)为 GameImportExcelModel(读对象)

GameImportExcelListener

/**
 * @author god23bin
 * @version 1.0
 * @description
 * @date 2022/10/24 08:45:15
 */
@Slf4j
public class GameImportExcelListener extends AnalysisEventListener<GameImportExcelModel> {

    /**
     * 每隔100条存储到数据库,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;

    /**
     * 缓存的数据
     */
    private List<Game> cachedDataList = new ArrayList<>(BATCH_COUNT);

    /**
     * 每解析一行数据就会执行这个方法
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(GameImportExcelModel data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        Game game = new Game();
        BeanUtil.copyProperties(data, game);
        cachedDataList.add(game);
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList.clear();
        }
    }

    private void saveData() {
        // 这里写存储到数据库的逻辑代码
    }

    /**
     * 解析完之后会执行这个方法,如果有其他事情需要做,可以在这里加上代码来完成
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }
}

但是!如果我们想要使用 Spring IOC 管理对象,比如 Dao、Mapper 这些对象,现在当前类是用不了 @Autowired 注解将这些对象注入的,那我们怎么获取它们?

方法就是:在该类中写一个构造方法,将这些被 Spring 管理的对象作为参数传入进来!

比如我这里需要用到 GameMapper 对象,那么就将它作构造方法的参数传进来。

@Slf4j
public class GameImportExcelListener extends AnalysisEventListener<GameImportExcelModel> {

    // 省略其他代码
    
    private GameMapper gameMapper;
    
    public GameImportExcelListener(GameMapper gameMapper) {
        this.gameMapper = gameMapper;
    }

    @Override
    public void invoke(GameImportExcelModel data, AnalysisContext context) {
        // ...
    }

    private void saveData() {
        // ...
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // ...
    }
}
完整的监听器代码

GameImportExcelListener

package cn.god23bin.demo.excel.listener;

import cn.god23bin.demo.entity.Game;
import cn.god23bin.demo.excel.bean.GameImportExcelModel;
import cn.god23bin.demo.mapper.GameMapper;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zwb
 * @version 1.0
 * @description
 * @date 2022/10/24 08:45:15
 */
@Slf4j
public class GameImportExcelListener extends AnalysisEventListener<GameImportExcelModel> {

    /**
     * 每隔100条存储到数据库,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;

    /**
     * 缓存的数据
     */
    private List<Game> cachedDataList = new ArrayList<>(BATCH_COUNT);

    private GameMapper gameMapper;

    public GameImportExcelListener(GameMapper gameMapper) {
        this.gameMapper = gameMapper;
    }

    /**
     * 每解析一行数据就会执行这个方法
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(GameImportExcelModel data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        Game game = new Game();
        BeanUtil.copyProperties(data, game);
        cachedDataList.add(game);
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList.clear();
        }
    }

    private void saveData() {
        // 这里写存储到数据库的逻辑代码
        for (Game game : cachedDataList) {
            gameMapper.insert(game);
        }
    }

    /**
     * 解析完之后会执行这个方法,如果有其他事情需要做,可以在这里加上代码来完成
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }
}

完善业务层

  1. 使用 EasyExcel.read() 方法构建一个 Excel reader builder,第一个参数是文件输入流,第二个参数是读对象,指定它这个class去读,第三个参数就是读监听器
  2. 接着链式调用 sheet() 方法和 doRead() 方法,完成整个 Excel 的读取操作。
@Slf4j
@Service
public class GameServiceImpl extends ServiceImpl<GameMapper, Game> implements GameService {

    @Resource
    private GameMapper gameMapper;

    /**
     * 导入Excel数据到数据库
     *
     * @param file Excel文件
     * @return boolean
     * @date 2022/11/8 14:38
     **/
    @Override
    public boolean importExcel(MultipartFile file) {
        try {
            // 使用 EasyExcel.read() 方法构建一个 Excel reader builder,第一个参数是文件输入流,第二个参数是读对象,指定它这个class去读,第三个参数就是读监听器
            EasyExcel.read(file.getInputStream(), GameImportExcelModel.class, new GameImportExcelListener(gameMapper))
                    .sheet()
                    .doRead();
        } catch (IOException e) {
            log.error("Error importing: {}", e.getMessage());
            return false;
        }
        return true;
    }

}

测试

使用 Postman 测试,请求后端的导入 Excel 的接口,在 Postman 中选好 Post 请求并且输入请求路径。

点击 Headers 设置请求头:

  • Key 中输入 Content-Type,属性的值输入 multipart/form-data

点击 Body 设置请求体:

  • 选择 form-data 格式,Key 中输入 file,便可以选择文件进行上传了

测试结果:

可以看到Excel中的数据成功存储到数据库中了,这就完成了导入的功能!

导出功能

用户勾选目标数据 id,点击导出按钮,就能将系统中的数据以 Excel 文件的格式下载到本地。

细节:需要导出的文件名称为这种格式:游戏列表-2022-11-11-12-30-00.xlsx

在这个导出文件的场景下,就需要后端返回前端文件数据,后端有两种方式可以返回,让前端进行下载。

  1. 后端返回文件所在的 URL,前端直接根据 URL 进行下载。
  2. 后端以二进制流的形式返回文件流,前端再接受这个流下载到本地。

由于我们的数据是在数据库中的,并不是直接存储 Excel 文件的,所以我们以二进制流的形式返回文件流给前端,让前端下载。

看看 EasyExcel 的 write 方法签名,里面有好多个重载的 write 方法,我们看看这个就行:

public static ExcelWriterBuilder write(OutputStream outputStream, Class head)

参数说明:

  • 第一个参数是文件输出流
  • 第二个参数是指定我们要参照哪个模型类去写这个 Excel,head 意思就是该类的属性将作为 Excel 的表头。

代码

主要逻辑
// 假设这里是从数据库获取的集合
List<Game> data = ...;
// 文件格式
String fileName = new String("");
String format = "yyyy-MM-dd-HH-mm-ss";
fileName = fileName + DateUtil.format(new Date(), format);
// 将数据写到输出流返回给前端
EasyExcel.write(ExcelUtil.getResponseOutputStream(fileName, response), GameExportExcelModel.class)
    .sheet("工作簿")
    .doWrite(dataList);
Excel 工具类
/**
 * @author god23bin
 * @version 1.0
 * @description Excel 工具类
 * @date 2022/11/18 17:55:48
 */
public class ExcelUtil {

    /**
     * 获取响应输出流
     * @date 2022/11/18 18:10
     * @param fileName 文件名
     * @param response 响应
     * @return java.io.OutputStream
     **/
    public static OutputStream getResponseOutputStream(String fileName, HttpServletResponse response) {
        try {
            // 给文件名编码,则前端接收后进行解码
            fileName = URLEncoder.encode(fileName, "UTF-8");
            // 指定客户端接收的响应内容类型为Excel以及字符编码为UTF-8
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf8");
            // 让浏览器提供打开、保存的对话框,以附件的形式下载,同时设置文件名格式
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
            // 禁止缓存
            response.setHeader("Cache-Control", "no-store");
            response.addHeader("Cache-Control", "max-age=0");
            return response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

控制层

用 Set 集合去重,防止多次查询同一数据。

    @PostMapping("/excel/export/game")
    public ResponseEntity<String> exportExcel(@RequestBody Set<String> uuidList, HttpServletResponse response) {
        gameService.exportExcel(new ArrayList<>(uuidList), response);
        return new ResponseEntity<>("OK", HttpStatus.OK);
    }

业务层

主要逻辑是去数据库查询出需要导出的数据,然后转成对应的导出模型对象,最后使用 EasyExcel 的 write() 方法将数据写到输出流。

    /**
     * 导出数据库记录到Excel
     *
     * @param uuidList uuid集合
     * @param response 响应
     * @return boolean
     * @date 2022/11/11 14:23
     **/
    @Override
    public boolean exportExcel(List<String> uuidList, HttpServletResponse response) {
        // 根据uuid找到需要导出的记录集合
        LambdaQueryWrapper<Game> achievementWrapper = new LambdaQueryWrapper<>();
        achievementWrapper.in(Game::getUuid, uuidList);
        achievementWrapper.orderByDesc(Game::getGmtCreate);
        List<Game> games = this.baseMapper.selectList(achievementWrapper);
        // 将查询到的数据转换成对应Excel的导出模型对象
        List<GameExportExcelModel> dataList = games.stream().map(game -> {
            GameExportExcelModel gameExportExcelModel = new GameExportExcelModel();
            BeanUtil.copyProperties(game, gameExportExcelModel);
            return gameExportExcelModel;
        }).collect(Collectors.toList());
        // 文件格式
        String fileName = new String("");
        String format = "yyyy-MM-dd-HH-mm-ss";
        fileName = fileName + DateUtil.format(new Date(), format);
        // 将数据写到输出流返回给前端
        EasyExcel.write(ExcelUtil.getResponseOutputStream(fileName, response), GameExportExcelModel.class)
                .sheet("工作簿")
                .doWrite(dataList);
        return true;
    }

测试

以请求体的方式传递一个需要导出的游戏的 uuid 数组

点击 Send 按钮旁边的三角符号,点击 Send and Download,这样就可以下载了,最后下载的 Excel 打开后如下:

额,翻车,格式有点点问题,问题不大,这时候就需要一个自定义的拦截器帮我们处理单元格。

自定义拦截器

拿来主义,写法基本是这样:

EasyExcel导出自动适应列宽 Excel样式

public class CustomCellWriteHandler extends AbstractColumnWidthStyleStrategy {

    private static final int MAX_COLUMN_WIDTH = 255;

    private Map<Integer, Map<Integer, Integer>> cache = new HashMap<>(16);

    public CustomCellWriteHandler() {
    }
    /**
     * Sets the column width when head create
     *
     * @param writeSheetHolder
     * @param cellDataList
     * @param cell
     * @param head
     * @param relativeRowIndex
     * @param isHead
     */
    @Override
    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
        if (needSetWidth) {
            Map<Integer, Integer> maxColumnWidthMap = cache.get(writeSheetHolder.getSheetNo());
            if (maxColumnWidthMap == null) {
                maxColumnWidthMap = new HashMap<>(16);
                cache.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
            }

            Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
            if (columnWidth >= 0) {
                if (columnWidth > 255) {
                    columnWidth = 255;
                }
                Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
                if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
                    maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
                    writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), 7250);
                }
            }
        }
    }

    private Integer dataLength(List<CellData> cellDataList, Cell cell, Boolean isHead) {
        if (isHead) {
            return cell.getStringCellValue().getBytes().length;
        } else {
            CellData cellData = (CellData) cellDataList.get(0);
            CellDataTypeEnum type = cellData.getType();
            if (type == null) {
                return -1;
            } else {
                switch (type) {
                    case STRING:
                        return cellData.getStringValue().getBytes().length;
                    case BOOLEAN:
                        return cellData.getBooleanValue().toString().getBytes().length;
                    case NUMBER:
                        return cellData.getNumberValue().toString().getBytes().length;
                    default:
                        return -1;
                }
            }
        }
    }
}

但是为什么这样写,好吧,目前不了解T_T,有待研究。

接着注册这个拦截器,让它知道该如何处理,修改业务层的代码:

EasyExcel.write(ExcelUtil.getResponseOutputStream(fileName, response), GameExportExcelModel.class)
                .sheet("工作簿")
                .registerWriteHandler(new CustomCellWriteHandler())
                .doWrite(dataList);

最后导出效果:

总结

某张 Excel 表需要你导入到系统中,这里系统指的就是你所做的项目,更准确来说将 Excel 的数据插入到你系统中的数据库里。那么就可以使用 EasyExcel。

常见的需求就是对 Excel 数据的导入导出,我们需要做的就是根据 Excel 表进行建模,创建对应的读对象和写对象。

对于导入,就需要读对象配合读监听器来实现。

对于导出,就直接通过 write 方法,以二进制流的方式将数据写到响应体中。

最后的最后

由本人水平所限,难免有错误以及不足之处, 屏幕前的靓仔靓女们 如有发现,恳请指出!

最后,谢谢你看到这里,谢谢你认真对待我的努力,希望这篇博客对你有所帮助!

你轻轻地点了个赞,那将在我的心里世界增添一颗明亮而耀眼的星!

有关初次邂逅 EasyExcel的更多相关文章

  1. 搭建hadoop集群初次格式化namenode时不小心格式化了多次,主节点namenode或者从节点datanode进程不能启动,怎么办? - 2

    我们在搭建完hadoop集群时,初次启动HDFS集群,需要对主节点进行格式化操作,其本质是清理和做一些准备工作,因为此时的HDFS在物理上还是存在的。而且主节点格式化操作只能进行一次。那我们在格式化时,不小心格式化多次,就会导致主从节点之间互相不识别。然后导致启动hadoop集群时,主节点的namenode进程可能不会启动或者从节点的datanode可能不会启动。这里给出一种解决方法:我们在配置hadoop的配置文件core-site.xml时,其中有一组参数hadoop.tmp.dir,它的值指定的是配置hadoop的临时目录我们把tmp目录删除,再重新格式化即可。先进入/export/se

  2. Java EasyExcel带格式多线程导出百万数据 - 2

    JavaEasyExcel带格式多线程导出百万数据1.背景说明2.方案概述(1)大数据量导出问题主要是以下三个地方:(2)将写入导出Excel等功能单独分开成一个微服务:(3)注意:(4)方案设计:标注说明(5)maven依赖:3.详细设计4.缓存5.可行性验证6.代码以下为结合实际情况作的方案设计,导出阈值以及单sheet页条数都可以根据实际情况调整大佬可直接跳过新手教程,直接查看文末代码————————————————————————————————1.背景说明    针对明细报表,用户会选择针对当前明细数据进行导出,便于本地或者线下进行处理或者计算等需求。不过一般在这种大数据量的导出任务

  3. git安装、初次配置及密钥生成 - 2

    1.git下载①可以从官网下载github进行安装,网址:Git-Downloads;②git官网时常无法登录,可以从百度网盘下载安装包安装,版本:Git-2.38.1-64-bit,网址:链接:https://pan.baidu.com/s/18PDKQSfIa1SSyTAfQLNLMQ 提取码:rtdm 2.git安装git安装引导界面可根据需要改变安装目录,其他安装选项,无特殊需求,一直点击next即可完成安装。3.git配置git安装完成后,在文件资源管理器空白处,右键-GitBashHere,即可在当前路径打开git命令行,如图所示为桌面处打开的git bash。在git bash中

  4. Rock 5 RK3588 SBC初次摸索 - 2

    RADXARock5(基于RK3588)的初次摸索硬件平台简述系统安装选择几个系统的介绍系统的安装方式配件方面硬件平台简述RK3588是瑞芯微发布的一款8核(4核大+4核小)ARM架构处理器,许多家都有这个芯片的开发板。这里使用ROCK5的原因,是前期用过radxa家的rockpi4p和rockpi3,对同一家产品熟悉一点。还有就是比较便宜,可以板载NVMe硬盘,hdmiin也引出了(谁不想一张板子啥都能干呢~~),下面两张是开发板的正反面实物图(来自于Radxa官网Wiki)下图是Radxa关于RK3588的功能定义(来自于官方DataSheet),Rock5同样遵循该定义制作。具体的细节参

  5. EasyExcel导出合并单元格 - 2

    功能展示功能类似这样:开题序言当时网上的资料大部分都是上下行相同的数据合并,唯独没有左右列的单元格合并。因此找资料花了一点时间,但功夫不负有心人,终于看到有两个和我要的功能差不多类似的文章。需要自取:EasyExcel模板导出(行和列自动合并)_Lzfnemo2009的博客-CSDN博客_easyexcel模板导出EasyExcel导出自定义合并单元格策略个人理解写这篇文章只是为了自己以后参考。 以下进入正文:1、导出的实体类,也就是表头@DatapublicclassCityCapacityPo{@ExcelProperty(value="时间",index=0)privateStringt

  6. 【二十四】springboot使用EasyExcel和线程池实现多线程导入Excel数据 - 2

      springboot篇章整体栏目: 【一】springboot整合swagger(超详细【二】springboot整合swagger(自定义)(超详细)【三】springboot整合token(超详细)【四】springboot整合mybatis-plus(超详细)(上)【五】springboot整合mybatis-plus(超详细)(下)【六】springboot整合自定义全局异常处理【七】springboot整合redis(超详细)【八】springboot整合AOP实现日志操作(超详细)【九】springboot整合定时任务(超详细)【十】springboot整合redis实现启动服

  7. 【ADS学习笔记(二)——ADS初次仿真】 - 2

    一、设计电路图创建好原理图后,在元件库面板选择Lumped-Components元件库,里面含有各种集成元件,R、L、C等,点击元件图标在画布内放置元件。点击工具栏可添加导线,点击可添加接地点,点击可添加端口。设计电路图如图所示(无源滤波器)。二、更改元件值更改元件值有多种办法,例如在元件下方显示的原件值中直接更改。或者左键双击元件,在参数窗口更改。该窗口可更改元件的一系列参数,可根据需要修改。点击EquationEditor可对该元件的某个值用等式表示,ADS会自动计算该值。在该窗口也可更改元件类型,点击SwapComponent可选择更改为其他元件。当需要更改多个元件的类型时,例如将所有电

  8. EasyExcel导入 - 2

    方式一:Controller层@PostMapping("/import")publicResultString>importDemo(HttpServletRequestrequest,@RequestParam("file")MultipartFilefile){log.info("import.request:{}",file.getOriginalFilename());if(file.getOriginalFilename()==null||!file.getOriginalFilename().endsWith("xlsx")){thrownewException("只支持.xls

  9. 谷粒学院——Day06【整合阿里云OSS、EasyExcel技术实现Excel导入分类】 - 2

    ❤作者主页:欢迎来到我的技术博客😎❀个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~*🍊如果文章对您有帮助,记得关注、点赞、收藏、评论⭐️⭐️⭐️📣您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉阿里云存储OSS一、对象存储OSS1.开通“对象存储OSS”服务阿里云:https://www.aliyun.com/申请阿里云账号实名认证开通“对象存储OSS”服务进入管理控制台2.创建Bucket选择:标准存储、公共读、不开通。 3.上传默认头像 4.创建RAM子用户二、使用SDK 1.创建Mavaen项目aliyun-oss2.pomcom.aliyun.os

  10. EasyExcel导入和导出数据 - 2

    pomcom.alibabaeasyexcel3.1.1#实体类```java/***@author:lzp*@create:2022-08-0115:06*@Description:员工表excel增强*//***@author:lzp*@create:2022-07-0315:57*@Description:excel*/@DatapublicclassEmpExcelVo{/***员工编号*/@ExcelProperty(value="编号",index=0)privateIntegerid;/***员工姓名*/@ExcelProperty(value="姓名",index=1)priv

随机推荐