SpringBoot 使用EasyExcel 导出Excel报表(单元格合并)

news2024/11/24 2:59:01

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、导入依赖
  • 二、代码
      • 1. 导出简单的Excel
      • 2. 代码控制导出报表的格式
  • 总结


前言

SpringBoot 使用Alibaba提供的EasyExcel导出Excel报表。

本文中涉及的业务逻辑有:

  1. 前端发起请求,后端封装Excel信息,直接在浏览器完成下载业务;
  2. 在后端,通过代码,控制导出的Excel样式。(主要包括:横向、纵向合并单元格

本文中后端导出Excel的数据,只包括导出列表数据,具体指:将一个List< List< String>>类型的数据导出到Excel中。(可将数据导出到不同的sheet中)

也就是说导出的数据没有固定的对象格式。如果需要导出List< Object> 的列表,需要封装导出对象,并对属性配置@ExcelProperty等信息,此文目前将不涉及这部分的内容。

最终效果展示:
在这里插入图片描述


一、导入依赖

导入相关依赖

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

二、代码

1. 导出简单的Excel

// 导出的Excel 文件名称
String fileName = "xxx.xlsx";
try {
    response.setContentType("application/vnd.ms-excel");
    response.setHeader("Content-Type", "application/vnd.ms-excel");
    fileName = URLEncoder.encode(fileName, "UTF-8");
    response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
    response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
    response.addHeader("Cache-Control", "no-cache");

    // 创建ExcelWriter对象
    ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();

    // 写入第一个sheet的数据
    WriteSheet sheet1 = EasyExcel.writerSheet(0, "Sheet1")
            .registerWriteHandler(mergePrevCol1)
            .build();
    // 设置Excel表头(表头横向展示)
    sheet1.setHead(Arrays.asList(Arrays.asList(""),Arrays.asList("1#加热炉"),Arrays.asList("1"),Arrays.asList("2"),Arrays.asList("3#加热炉"),Arrays.asList("1"),Arrays.asList("2")));
    // 写入数据
    excelWriter.write(heatFurnace1And3MZLValueList, sheet1);

    // 关闭ExcelWriter
    excelWriter.finish();
} catch (UnsupportedEncodingException e) {
    throw new RuntimeException(e);
} catch (IOException e) {
    throw new RuntimeException(e);
}

以上就能完成简单的导出Excel报表的功能

请注意Controller对应接口的返回值,一般设置为void

    @PostMapping(value = "/export")
    @ApiOperation(value = "导出报表")
    public void export(@RequestBody RecordExportBO bean, HttpServletResponse response) {
    	// 这里的RecordExportBO 为封装接收前端数据的对象
        iService.export(bean,response);
}

2. 代码控制导出报表的格式

这里主要包括控制表头的格式以及合并单元格

A. 合并行的工具类

package cisdi.info.imc.device.model.common.util;

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;

/**
 * 合并Excel的行(内容相同的行才合并)
 */
public class ExcelFillCellMergeStrategyUtil implements CellWriteHandler {
    private int[] mergeColumnIndex; //数组存放这一行需要合并那几列  [0,1,2] 在这mergeRowIndex行中合并 0 、1、2列
    private int mergeRowIndex;  // 存放需要向上合并的列
    private Integer noMergeRowIndex;// 不要合并的列

    public ExcelFillCellMergeStrategyUtil() {
    }

    public ExcelFillCellMergeStrategyUtil(int mergeRowIndex, int[] mergeColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
    }

    public ExcelFillCellMergeStrategyUtil(int mergeRowIndex, int[] mergeColumnIndex, Integer noMergeRowIndex) {
        this.mergeColumnIndex = mergeColumnIndex;
        this.mergeRowIndex = mergeRowIndex;
        this.noMergeRowIndex = noMergeRowIndex;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
        int curRowIndex = cell.getRowIndex();
        int curColIndex = cell.getColumnIndex();
        if (curRowIndex > mergeRowIndex) {
            for (int i = 0; i < mergeColumnIndex.length; i++) {
                if (curColIndex == mergeColumnIndex[i]) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }
    }

    /**
     * 当前单元格向上合并
     * .
     * @param writeSheetHolder writeSheetHolder
     * @param cell             当前单元格
     * @param curRowIndex      当前行
     * @param curColIndex      当前列
     */
    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        Row  preRow = cell.getSheet().getRow(curRowIndex - 1);
        if (preRow == null) {
            // 当获取不到上一行数据时,使用缓存sheet中数据
            preRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex - 1);
        }
        Cell preCell = preRow.getCell(curColIndex);
        Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();
        //不需要合并的列直接跳出
        if ( (noMergeRowIndex != null) &&   noMergeRowIndex == (curRowIndex - 1)  ){
            return;
        }
        // 将当前单元格数据与上一个单元格数据比较
        Boolean dataBool = preData.equals(curData);

        //此处需要注意:所以获取每一行第一列数据和上一行第一列数据进行比较,如果相等合并
        boolean equals = cell.getRow().getCell(0).getStringCellValue().equals(cell.getSheet().getRow(curRowIndex - 1).getCell(0).getStringCellValue());
        if (dataBool && equals) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
                    sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastRow(curRowIndex);
                    sheet.addMergedRegion(cellRangeAddr);
                    isMerged = true;
                }
            }
            // 若上一个单元格未被合并,则新增合并单元
            if (!isMerged) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
                sheet.addMergedRegion(cellRangeAddress);
            }
        }
    }

}

B. 合并列的工具类

package cisdi.info.imc.device.model.common.util;

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
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.util.CellRangeAddress;

import java.util.HashMap;
import java.util.Map;
import java.util.List;

/**
 * 合并Excel的列
 */
public class ExcelFillCellMergePrevColUtil implements CellWriteHandler {
    private static final String KEY ="%s-%s";
    //所有的合并信息都存在了这个map里面
    Map<String, Integer> mergeInfo = new HashMap<>();

    public ExcelFillCellMergePrevColUtil() {
    }
    public ExcelFillCellMergePrevColUtil(Map<String, Integer> mergeInfo) {
        this.mergeInfo = mergeInfo;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
        //当前行
        int curRowIndex = cell.getRowIndex();
        //当前列
        int curColIndex = cell.getColumnIndex();

        Integer num = mergeInfo.get(String.format(KEY, curRowIndex, curColIndex));
        if(null != num){
            // 合并最后一行 ,列
            mergeWithPrevCol(writeSheetHolder, cell, curRowIndex, curColIndex,num);
        }
    }

    public void mergeWithPrevCol(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex, int num) {
        Sheet sheet = writeSheetHolder.getSheet();
        CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex, curRowIndex, curColIndex, curColIndex + num);
        sheet.addMergedRegion(cellRangeAddress);
    }

    //num从第几列开始增加多少列
    // curRowIndex 在第几行进行行合并
    // curColIndex 在第几列进行合并
    // num 合并多少格
    // 比如我上图中中心需要在第三行 从0列开始合并三列 所以我可以传入 (3,0,2)
    public void add (int curRowIndex,  int curColIndex , int num){
        mergeInfo.put(String.format(KEY, curRowIndex, curColIndex),num);
    }

}

C. 控制表头格式

/**
* 设置导出报表的表格格式
* @return
*/
public CellStyleStrategyUtil horizontalCellStyleStrategyBuilder() {
   WriteCellStyle headWriteCellStyle = new WriteCellStyle();
   //设置头字体
   WriteFont headWriteFont = new WriteFont();
   headWriteFont.setFontHeightInPoints((short) 15);
   headWriteFont.setBold(true);
   headWriteCellStyle.setWriteFont(headWriteFont);
   //设置头居中
   headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
   //内容策略
   WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
   //设置 水平居中
   contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
   //垂直居中
   contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

   return new CellStyleStrategyUtil(headWriteCellStyle, contentWriteCellStyle,Boolean.TRUE);
    }

D. 具体用法

直接结合具体例子,通过例子中关键代码的注解进行介绍:

// 导出的Excel 文件名称
String fileName = "xxx.xlsx";
try {
    response.setContentType("application/vnd.ms-excel");
    response.setHeader("Content-Type", "application/vnd.ms-excel");
    fileName = URLEncoder.encode(fileName, "UTF-8");
    response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
    response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
    response.addHeader("Cache-Control", "no-cache");

    // 创建ExcelWriter对象
    ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();

    // 创建第一个sheet的列合并工具类对象
    ExcelFillCellMergePrevColUtil mergePrevCol1 = new ExcelFillCellMergePrevColUtil();
    // 第一个参数:合并哪一行;第二个参数:合并的起始列;第三个参数:往右合并的列数;
    // 指一条代表合并第0行的第1,2,3列。
    mergePrevCol1.add(0,1,2);
    // 这一行代表合并第0行的4,5,6列
    mergePrevCol1.add(0,4,2);

    // 写入第一个sheet的数据
    WriteSheet sheet1 = EasyExcel.writerSheet(0, "Sheet1")
            // 字体表格样式工具类,下方展示
            .registerWriteHandler(horizontalCellStyleStrategyBuilder())
            // 合并行。第一个参数:从第几行开始合并、第二个参数:合并哪几列、第三个参数:到哪一行为止。
            // 这一行的意思是:从第0行开始合并第0列,到第2行为止。也就是合并了第0行和第1行的第0列。(注意这里必须合并列的内容相同才能够合并)
            .registerWriteHandler(new ExcelFillCellMergeStrategyUtil(0,new int[]{0}, 2))
            // 合并列。
            .registerWriteHandler(mergePrevCol1)
            .build();
    // 设置Excel表头
    // Collections.singletonList("") 这样设置表头的第0列才能与第1行的第0列合并。使用Arrays.asList("")是不行的。
    sheet1.setHead(Arrays.asList(Collections.singletonList(""),Arrays.asList("1#加热炉"),Arrays.asList("1"),Arrays.asList("2"),Arrays.asList("3#加热炉"),Arrays.asList("1"),Arrays.asList("2")));
    // 写入数据
    // list1的类型为List<List<String>>
    excelWriter.write(list1, sheet1);

    // 创建第二个sheet的列合并工具类对象
    ExcelFillCellMergePrevColUtil mergePrevCol2 = new ExcelFillCellMergePrevColUtil();
    mergePrevCol2.add(0,1,3);
    mergePrevCol2.add(0,5,3);

    // 写入第二个sheet的数据
    WriteSheet sheet2 = EasyExcel.writerSheet(1, "Sheet2")
            .registerWriteHandler(horizontalCellStyleStrategyBuilder()) // 字体表格样式工具类,下方展示
            .registerWriteHandler(new ExcelFillCellMergeStrategyUtil(0,new int[]{0}, 2))
            .registerWriteHandler(mergePrevCol2)
            .build();
    sheet2.setHead(Arrays.asList(Collections.singletonList(""),Arrays.asList("2#加热炉"),Arrays.asList("1"),Arrays.asList("2"),Arrays.asList("3"),Arrays.asList("4#加热炉"),Arrays.asList("1"),Arrays.asList("2"),Arrays.asList("3")));
     // list2的类型为List<List<String>>
    excelWriter.write(list2, sheet2);

    // 关闭ExcelWriter
    excelWriter.finish();
} catch (UnsupportedEncodingException e) {
    throw new RuntimeException(e);
} catch (IOException e) {
    throw new RuntimeException(e);
}

效果图
在这里插入图片描述
在这里插入图片描述


总结

阿巴阿巴…

文章内容就到这里结尾了,整个过程鄙人亲力亲为。如果你的需求相同,又还是无法达到想要的效果,抑或是出现了什么问题,欢迎找笔者沟通!!!

此外,本篇文章中单元格合并的工具类等代码,并非我自己亲自完成,如有侵权,请及时联系笔者。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1194961.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C/C++内存管理——“C++”

各位CSDN的uu们你们好呀&#xff0c;好久没有更新小雅兰的C专栏啦&#xff0c;下面&#xff0c;小雅兰继续开始更新C专栏的内容&#xff01;&#xff01;&#xff01;今天&#xff0c;小雅兰的内容是C和C的内存管理&#xff0c;下面&#xff0c;让我们进入C的世界吧&#xff01…

【Nginx40】Nginx学习:动静分离与日志分割

Nginx学习&#xff1a;动静分离与日志分割 放轻松放轻松&#xff0c;最后两篇文章学习的内容是比较轻松的。首先&#xff0c;我们来看看 Nginx 动静分离的概念&#xff0c;然后再看看怎么为 Nginx 做日志分割。内容都很简单&#xff0c;完全不需要有任何的压力。 动静分离 动静…

FPGA高端项目:图像缩放+GTX+UDP架构,高速接口以太网视频传输,提供2套工程源码加QT上位机源码和技术支持

目录 1、前言免责声明本项目特点 2、相关方案推荐我这里已有的 GT 高速接口解决方案我这里已有的以太网方案我这里已有的图像处理方案 3、设计思路框架设计框图视频源选择IT6802解码芯片配置及采集动态彩条跨时钟FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择 …

SSL证书申请安全审核失败?

随着HTTPS普及&#xff0c;申请安装使用SSL证书成为了我们的必备项。但这个SSL证书申请过程中&#xff0c;遇到问题也是不少。今天我们来浅了解一下SSL证书为什么会出现安全审核失败&#xff1f; SSL证书申请会出现安全审核失败的情况可能是以下原因&#xff1a; 域名验证不通…

docker-compose安装es以及ik分词同义词插件

目录 1 前言 2 集成利器Docker 2.1 Docker环境安装 2.1.1 环境检查 2.1.2 在线安装 2.1.3 离线安装 2.2 Docker-Compose的安装 2.2.1 概念简介 2.2.2 安装步骤 2.2.2.1 二进制文件安装 2.2.2.2 离线安装 2.2.2.3 yum安装 3 一键安装ES及Kibana 3.1 yml文件的编写…

多组学整合,快速定位关键代谢通路,解析分子机制

生物学是一种复杂的学科&#xff0c;往往单一组学无法探究想要了解的生物学问题&#xff0c;这时就要运用到多组学联合分析。近年来&#xff0c;多组学研究的不断发展和持续火热&#xff0c;越来越多的研究者开始将微生物组学和代谢组学联合起来。16s全长扩增子测序可提供细菌构…

JAVA集合学习和源码分析

一、结构 List和Set继承了Collection接口&#xff0c;Collection继承了Iterable Object类是所有类的根类&#xff0c;包括集合类&#xff0c;集合类中的元素通常是对象&#xff0c;继承了Object类中的一些基本方法&#xff0c;例如toString()、equals()、hashCode()。 Collect…

Mysql数据备份 —Navicat

一 Navicat 对于表的备份 根据自己的需求来选择 可以直接备份数据表 操作简单明了 二 Navicat 对于库的备份 对于数据库 直接通过转储SQL文件 保存结构和数据 需要新创建数据库 字符集和编码格式要对应 否则容易乱码 运行刚才生成的文件即可

【Git】GUI图形化界面的使用SSH协议IDEA集成Git

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Git的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一. GUI图形化界面的使用 1.使用Gui​ 2.常…

Linux - 基础IO(Linux 当中的文件,文件系统调用接口,文件描述符)- 上篇

前言 首先&#xff0c;关于文件我们最先要理解的是&#xff0c;文件不仅仅存储的是数据&#xff0c;一个文件包括 内容 数据。内容好理解&#xff0c;就是我们先要这文件存储哪一些数据&#xff0c;这些数据就是文件的内容。 但是&#xff0c;在计算机当中&#xff0c;有两种…

【Maven教程】(十):使用 Hudson 进行持续集成—— 从Hudson的安装到任务创建 ~

Maven 使用 Hudson 进行持续集成 1️⃣ 持续集成的作用、过程和优势2️⃣ Hudson 简介与安装3️⃣ 准备 Subversion 仓库4️⃣ Hudson 的基本系统设置5️⃣ 创建 Hudson 任务5.1 Hudson 任务的基本配置5.2 Hudson 任务的源码仓库配置5.3 Hudson 任务的构建触发配置5.4 Hudson …

Linux:权限篇 (彻底理清权限逻辑!)

shell命令以及运行原理&#xff1a; Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&#xff0c;也就是所谓的shell&#xff0c;来…

Ubuntu18.04.6安装qt5.7.1(超级详细教程)

目录 1、下载对应Linux版本的qt 2、安装完qt&#xff0c;可能也要安装下对应的编译工具 1、下载对应Linux版本的qt &#xff08;1&#xff09;准备安装的是qt5.7.1&#xff1a;qt-opensource-linux-x64-5.7.1.run &#xff08;2&#xff09;在虚拟机进入存放qt安装包的目录…

jQuery HTML/CSS 参考文档

jQuery HTML/CSS 参考文档 文章目录 应用样式 示例属性方法示例 jQuery HTML/CSS 参考文档 应用样式 addClass( classes ) 方法可用于将定义好的样式表应用于所有匹配的元素上。可以通过空格分隔指定多个类。 示例 以下是一个简单示例&#xff0c;设置了para标签 <p&g…

CVE-2023-25194 Kafka JNDI 注入分析

Apache Kafka Clients Jndi Injection 漏洞描述 Apache Kafka 是一个分布式数据流处理平台&#xff0c;可以实时发布、订阅、存储和处理数据流。Kafka Connect 是一种用于在 kafka 和其他系统之间可扩展、可靠的流式传输数据的工具。攻击者可以利用基于 SASL JAAS 配置和 SASL …

django|报错SQLite 3.8.3 or later is required的解决方案

迁移原同事写的程序&#xff0c;到新服务器上边。运行报错。解决方案有三种 降低django版本升级sqlite3&#xff0c;不低于3.8.3版本修改django源码 方案一、降低django版本 卸载高版本django pip uninstall django安装低版本&#xff0c;如 pip install django2.1.7注意&…

ARM 基础学习记录 / 异常与GIC介绍

GIC概念 念课本&#xff08;以下内容都是针对"通用中断控制器&#xff08;GIC&#xff09;"而言&#xff0c;直接摘录的&#xff0c;有的地方可能不符人类的理解方式&#xff09;&#xff1a; 通用中断控制器&#xff08;GIC&#xff09;架构提供了严格的规范&…

【C语言 | 预处理】C语言预处理详解(三)——内存对齐、手把手教你计算结构体大小

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

Elasticsearch:Lucene 中引入标量量化

作者&#xff1a;BENJAMIN TRENT 我们如何将标量量化引入 Lucene。 Lucene 中的自动字节量化 虽然 HNSW 是一种强大而灵活的存储和搜索向量的方法&#xff0c;但它确实需要大量内存才能快速运行。 例如&#xff0c;查询 768 维的 1MM float32 向量大约需要 1,000,000*4*(7681…

Spring Boot 集成 ElasticSearch

1 加入依赖 首先创建一个项目&#xff0c;在项目中加入 ES 相关依赖&#xff0c;具体依赖如下所示&#xff1a; <dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.1.0</version&g…