Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载

news2024/12/30 4:01:09

在这里插入图片描述

文章目录

  • 一、业务背景
  • 二、实现思路
  • 二、准备工作
    • 1.准备data模板.xlsx
    • 2.引入poi相关依赖,用于操作excel
    • 3.针对WorkBook+ZIP压缩输入/输出流,相关方法知识点要有所了解
  • 三、完整的项目代码
  • 四、可能遇到的问题
    • 错误场景1:java.io.IOException: Stream closed
    • 错误场景2:调用接口没有另存为弹窗,但是F12查看接口结果返回一堆乱码

一、业务背景

业务需求:从数据库查询多个list集合信息封装excel,每个excel都有2个sheet页,填充不同的信息,最后将所有excel打包成zip文件,以流的形式返回给客户端,供客户端另存为窗口下载。

  1. 只发出一次请求
  2. 每个excel表中到数据记录不能超过2条
  3. excel文件或者zip包不会上传服务器,而是查询后直接封装excel,然后把多个excel封装成zip包直接返回

之前看过其他人的方案大概有2种:

方案1:打包成zip包后上传到服务器某个路径下,然后在读取该路径的zip文件,以流的形式返回给客户端。
方案2:不上传服务器,而是查询后直接封装excel,然后把多个excel封装成zip包直接返回。(本人采用的就是第二种方案)

最终的效果,如图

在这里插入图片描述

二、实现思路

  1. 设置HttpServletResponse的参数,比如header、contentType
  2. 新建一个Workbook对象并置为空,同时初始化相关对象,比如List、File等
  3. 从数据库查询多条list
  4. 以其中为主的一个list计算分页数量
  5. 循环遍历list开始
  6. 初始化新的Workbook对象,并设置相应的Title
  7. 将list拆分成多个段,分别写到的Workbook对象中
  8. 将Workbook对象填充到List<XSSFWorkbook>中
  9. 重复步骤6至步骤8直至写完所有数据
  10. 最后统一封装zip压缩包并导出,调用downFileByStream方法
  11. 初始化ZipOutputStream对象
  12. 循环遍历List<XSSFWorkbook>将每一个wb写入ZipOutputStream对象中,并将内存流写入Zip文件,即:将每一个excel封装到zip包中
  13. 关闭ZipOutputStream

二、准备工作

1.准备data模板.xlsx

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

2.引入poi相关依赖,用于操作excel

pom.xml

<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
</dependency>

3.针对WorkBook+ZIP压缩输入/输出流,相关方法知识点要有所了解

Apache POI包中的HSSFWorkbook、XSSFWorkbook、SXSSFWorkbook的区别如下:

在这里插入图片描述

ZipOutputStream类的常用方法如下表所示:

方法返回值说明
putNextEntry(ZipEntry e)void开始写一个新的ZipEntry,并将流内的位置移至此entry所指数据的开头
write(byte[] b, int off, int len)void将字节数组写入当前ZIP条目数据
finish()void完成写入ZIP输出流的内容,无须关闭它所配合的OutputStream
setComment(String comment)void可设置此ZIP文件的注释文字

ZipInputStream类的常用方法如下表所示:

方法返回值说明
read(byte[] b, int off, int len)int读取目标b数组内off偏移量的位置,长度是len字节
available()int判断是否已读完目前entry所指定的数据。已读完返回0,否则返回1
closeEntry()void关闭当前ZIP条目并定位流以读取下一个条目
skip(long n)long跳过当前ZIP条目中指定的字节数
getNextEntry()ZipEntry读取下一个ZipEntry,并将流内的位置移至该entry所指数据的开头
createZipEntry(String name)ZipEntry以指定的name参数新建一个ZipEntry对象

Workbook类提供的方法

方法返回值说明
getNumberOfSheets()int获得工作薄(Workbook)中工作表(Sheet)的个数
getSheets()Sheet[]返回工作薄(Workbook)中工作表(Sheet)对象数组
getVersion()String返回正在使用的API的版本号,好像是没什么太大的作用。
getName()String获取Sheet的名称
getColumns()int获取Sheet表中所包含的总列数
getColumn(int column)Cell[]获取某一列的所有单元格,返回的是单元格对象数组
getRows()int获取Sheet表中所包含的总行数
getRow(int row)Cell[]获取某一行的所有单元格,返回的是单元格对象数组
getCell(int column, int row)Cell获取指定单元格的对象引用,需要注意的是它的两个参数,第一个是列数,第二个是行数,这与通常的行、列组合有些不同。
write()写入Exel工作表
close()关闭Excel工作薄对象
getPhysicalNumberOfCells()int获取该行的总列数
getSheetAt(int index)Sheet根据索引index获取对应的sheet页
getBodyStyle(Workbook wb)CellStyle设置excel中比如第一行Title样式
setCellStyle(CellStyle var1)void跟getBodyStyle()方法搭配设置样式
setCellValue(String var1)void设置值
getStringCellValue()String获取对应列的值

三、完整的项目代码

ExportUtil工具类

package com.excel.utils;

import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 导出【用户、组、隶属关系】工具
 * @Author 211145187
 * @Date 2023/4/13 16:29
 **/
public class ExportUtil {
    private static Logger logger = LoggerFactory.getLogger(ExportUtil.class);

    /**
     * 自定义获取分页总页数的方法
     * @param count 查询集合数量
     * @param pageSize 配置文件中设置的单文件存储最大条数
     * @return 总页数
     */
    public static Integer getPageCount(Integer count, Integer pageSize){
        Integer pageCount = 0;
        if(count.equals(0)){
            return pageCount;
        }
        pageCount = count/pageSize;
        if(count % pageSize != 0){
            pageCount++;
        }

        return pageCount;
    }

    /**
     * 自定义List分页工具
     * @param list 待分页的list数据
     * @param pageNum 页码
     * @param pageSize 页容量
     * @param pageCount 总页数
     * @return 分页后的list数据
     */
    public static <T> List<T> getPageList(List<T> list, Integer pageNum, Integer pageSize, Integer pageCount){

        /**开始索引*/
        int beginIndex = 0;
        /**结束索引*/
        int endIndex = 0;

        Integer compare = pageNum.compareTo(pageCount);
        if(!compare.equals(0)){
            beginIndex = (pageNum - 1) * pageSize;
            endIndex = beginIndex + pageSize;
        }else{
            beginIndex = (pageNum - 1) * pageSize;
            endIndex = list.size();
        }
        List pageList = list.subList(beginIndex, endIndex);

        return pageList;
    }

    /**
     * HSSFWorkbook转file
     * @param wb wb
     * @param name 文件名称
     * @return File
     */
    public static File xssfWorkbookToFile(Workbook wb, String name) {
        File toFile = new File(name);
        try {
            OutputStream os = new FileOutputStream(toFile);
            wb.write(os);
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return toFile;
    }


    /**
     * 直接下载zip包
     * @param response response
     * @param excels wb集合
     */
    public static void downFileByStream(HttpServletResponse response, List<XSSFWorkbook> excels){
        try {
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            ZipOutputStream zipOutputStream = new ZipOutputStream(toClient);
            for(int i=0; i<excels.size(); i++){
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                // 将Workbook写入内存流
                excels.get(i).write(baos);
                ZipEntry zipEntry = new ZipEntry("data" + i + ".xlsx");
                zipOutputStream.putNextEntry(zipEntry);
                // 将内存流写入Zip文件
                zipOutputStream.write(baos.toByteArray());
            }
            zipOutputStream.closeEntry();
            zipOutputStream.flush();
            zipOutputStream.close();
        }catch (Exception e){
            logger.error("downFileByStream==========fail:{}", e.getMessage());
        }
    }
}

application.properties

server.port=8001
#导出excel配置,单文件存储最大数量
export.num=2

OperateExcelController

package com.excel.controller;

import com.excel.bean.Score;
import com.excel.bean.Teacher;
import com.excel.utils.ExportUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
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.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 测试3.17版本操作Excel
 * @Author 211145187
 * @Date 2022/2/22 19:43
 **/
@RequestMapping("/excel")
@Controller
public class OperateExcelController {
	private static Logger logger = LoggerFactory.getLogger(OperateExcelController.class);
    @Value("${export.num:10000}")
    private Integer exportLimitNum;

    //构建教师集合数据
    public List<Teacher> buildTeacherList1() {
        List<Teacher> teacherList = new ArrayList<>();
        Teacher teacher1 = new Teacher();
        teacher1.setName("周杰伦");
        teacher1.setClasses("三年二班");
        teacher1.setCollege("魔法学院");
        teacher1.setAlias("Jay Chou");
        teacherList.add(teacher1);
        Teacher teacher2 = new Teacher();
        teacher2.setName("陈奕迅");
        teacher2.setClasses("三年二班");
        teacher2.setCollege("魔法学院");
        teacher2.setAlias("Eason");
        teacherList.add(teacher2);
        Teacher teacher3 = new Teacher();
        teacher3.setName("林俊杰");
        teacher3.setClasses("三年二班");
        teacher3.setCollege("魔法学院");
        teacher3.setAlias("Eason");
        teacherList.add(teacher3);
        Teacher teacher4 = new Teacher();
        teacher4.setName("张杰");
        teacher4.setClasses("三年二班");
        teacher4.setCollege("魔法学院");
        teacher4.setAlias("Eason");
        teacherList.add(teacher4);
        return teacherList;
    }
    //构建分数集合数据
    public List<Score> buildScoreList1() {
        List<Score> scoreList = new ArrayList<>();
        Score score1 = new Score();
        score1.setName("流川枫");
        score1.setClasses("三年二班");
        score1.setWriteScore("6");
        score1.setComputerScore("4");
        scoreList.add(score1);
        Score score2 = new Score();
        score2.setName("樱木花道");
        score2.setClasses("三年二班");
        score2.setWriteScore("6");
        score2.setComputerScore("4");
        scoreList.add(score2);
        Score score3 = new Score();
        score3.setName("大猩猩");
        score3.setClasses("三年二班");
        score3.setWriteScore("6");
        score3.setComputerScore("4");
        scoreList.add(score3);
        Score score4 = new Score();
        score4.setName("三井");
        score4.setClasses("三年二班");
        score4.setWriteScore("6");
        score4.setComputerScore("4");
        scoreList.add(score4);
        return scoreList;
    }

    //方法5:java导出多个Excel为zip包
    @RequestMapping("/exportMultipleExcelToZip")
    public void exportMultipleExcelToZip(HttpServletResponse response) throws IOException {
        response.setHeader("Content-disposition", "attachment; filename=" + "test.zip");
        response.setContentType("application/zip; charset=utf-8");

        //创建HSSFWorkbook对象(excel的文档对象)
        XSSFWorkbook wb = null;
        List<Teacher> teacherList = new ArrayList<>();
        //构建sheet页集合
        List<Score> scoreList = new ArrayList<>();
        File templateFile = new File("C:\\Users\\211145187\\Desktop\\data模板.xlsx");

        //.....省略部分代码
        List<Teacher> buildTeacherList = buildTeacherList1();
        List<Score> buildScoreList = buildScoreList1();

        Integer pageLimitSize = exportLimitNum;
        //计算list的分页数量
        Integer pageCount = ExportUtil.getPageCount(buildTeacherList.size(), pageLimitSize);
        List<XSSFWorkbook> excels = new ArrayList<>();
        try {
            for(Integer pageNum = 1; pageNum < pageCount + 1; pageNum++) {
                //注意:每次循环遍历前都需要初始化新的wb对象
                //注意情况1:如果是初始化wb空对象然后手动添加title,下方三行代码不会报错
//                wb = new XSSFWorkbook();
//                buildScoreSheetTitle(wb);
//                buildTeacherSheetTitle(wb);

                //注意情况2:如果是初始化wb对象,并且以流的形式初始化,那么io流必须放在里面才行,如果放在for循环外面会报“Stream Closed”错误
                InputStream io = new FileInputStream(templateFile);
                wb = new XSSFWorkbook(io);
                teacherList = ExportUtil.getPageList(buildTeacherList, pageNum, pageLimitSize, pageCount);
                scoreList = ExportUtil.getPageList(buildScoreList, pageNum, pageLimitSize, pageCount);
                buildScoreSheetParams(wb, scoreList);
                buildTeacherSheetParams(wb, teacherList);
                excels.add(wb);
            }
            //最后统一封装zip压缩包并导出
            ExportUtil.downFileByStream(response, excels);
        } catch (Exception e) {
            logger.error("IOException:", e);
        }
    }

    /**
     * 填充教师页信息
     * @param wb wb
     * @param bodyData bodyData
     */
    private void buildTeacherSheetParams(Workbook wb, List<Teacher> bodyData){
        int teacherColumnCount = wb.getSheetAt(1).getRow(0).getPhysicalNumberOfCells();
        Sheet sheet = wb.getSheetAt(1);
        // build data
        for(int j=0; j<bodyData.size(); j++){
            Teacher itm = bodyData.get(j);
            Row rowData = sheet.createRow(j+1);
            for(int k=0;k<teacherColumnCount; k++){
                Cell cell = rowData.createCell(k);
                cell.setCellValue(getValueByTeacher(k, itm));
            }
        }
    }
    private String getValueByTeacher(int columnIndex,Teacher itm){
        String cellValue;
        switch (columnIndex){
            case 0:cellValue = itm.getName(); break;
            case 1:cellValue = itm.getClasses()+""; break;
            case 2:cellValue = itm.getCollege(); break;
            case 3:cellValue = itm.getAlias(); break;
            default:cellValue=""; break;
        }
        return cellValue;
    }
    /**
     * 填充分数页信息
     * @param wb wb
     * @param bodyData bodyData
     */
    private void buildScoreSheetParams(Workbook wb, List<Score> bodyData){
        int scoreColumnCount = wb.getSheetAt(0).getRow(0).getPhysicalNumberOfCells();
        Sheet sheet = wb.getSheetAt(0);
        // build data
        for(int j=0; j<bodyData.size(); j++){
            Score itm = bodyData.get(j);
            Row rowData = sheet.createRow(j+1);
            for(int k=0;k<scoreColumnCount; k++){
                Cell cell = rowData.createCell(k);
                cell.setCellValue(getValueByScore(k, itm));
            }
        }
    }
    private String getValueByScore(int columnIndex,Score itm){
        String cellValue;
        switch (columnIndex){
            case 0:cellValue = itm.getName(); break;
            case 1:cellValue = itm.getClasses()+""; break;
            case 2:cellValue = itm.getWriteScore(); break;
            case 3:cellValue = itm.getComputerScore(); break;
            default:cellValue=""; break;
        }
        return cellValue;
    }

    /**
     * 构建分数表excel的标头
     * @Author 211145187
     * @Date 2022/2/22 20:20
     * @Param wb wb
     **/
    private void buildScoreSheetTitle(XSSFWorkbook wb) {
        //建立新的sheet对象(excel的表单)
        XSSFSheet sheet=wb.createSheet("成绩表");
        XSSFRow row=sheet.createRow(0);
        //创建单元格并设置单元格内容
        XSSFCell cell0 = row.createCell(0);
        cell0.setCellValue("姓名");
        cell0.setCellStyle(getHeadStyle(wb));
        XSSFCell cell1 = row.createCell(1);
        cell1.setCellValue("班级");
        cell1.setCellStyle(getHeadStyle(wb));
        XSSFCell cell2 = row.createCell(2);
        cell2.setCellValue("笔试成绩");
        cell2.setCellStyle(getHeadStyle(wb));
        XSSFCell cell3 = row.createCell(3);
        cell3.setCellValue("机试成绩");
        cell3.setCellStyle(getHeadStyle(wb));
    }
    /**
     * 构建教师表excel的标头
     * @Author 211145187
     * @Date 2022/2/22 20:20
     * @Param wb wb
     **/
    private void buildTeacherSheetTitle(XSSFWorkbook wb) {
        //建立新的sheet对象(excel的表单)
        XSSFSheet sheet=wb.createSheet("教师表");
        XSSFRow row=sheet.createRow(0);
        //创建单元格并设置单元格内容
        XSSFCell cell0 = row.createCell(0);
        cell0.setCellValue("姓名");
        cell0.setCellStyle(getHeadStyle(wb));
        XSSFCell cell1 = row.createCell(1);
        cell1.setCellValue("班级");
        cell1.setCellStyle(getHeadStyle(wb));
        XSSFCell cell2 = row.createCell(2);
        cell2.setCellValue("所属学院");
        cell2.setCellStyle(getHeadStyle(wb));
        XSSFCell cell3 = row.createCell(3);
        cell3.setCellValue("别名");
        cell3.setCellStyle(getHeadStyle(wb));
    }

    /**
     * 设置样式
     * @Author 211145187
     * @Date 2022/2/22 20:15
     * @Param wb wb
     * @Return CellStyle
     **/
    private CellStyle getHeadStyle(Workbook wb) {
        CellStyle cellStyle = wb.createCellStyle();
        //用于设置前景颜色
        cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
        /**
         * setFillPattern用于设置单元格填充样式
         * 注意:
         *      1)setFillPattern必须设置否则光设置setFillForegroundColor无效
         *      2)3.10.1版本支持short类型参数,而3.17版本支持FillPatternType类型参数
         */
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        return cellStyle;
    }
}

四、可能遇到的问题

错误场景1:java.io.IOException: Stream closed

原因分析:

我这里导致流关闭会有2种场景触发:
场景1:工具类方法downFileByStream()中的for循环执行write()方法。
场景2:wb = new XSSFWorkbook(io);通过IO流初始化wb对象时。

解决方案:

针对场景1中的解决方案就是:Workbook的write()方法最终会关闭它写入的输出流。如果只是一次性全部输出那就不会碰到这种问题,但是现在的场景是工具类方法downFileByStream()中的for循环执行write()方法,所以解决方案就是用一个ByteArrayOutputStream去接收存储当前Workbook的内容,这样哪怕Workbook关闭了,但是内容已经提前存入了ByteArrayOutputStream中,只要读取了就可以继续使用。因此才有这样的如下写法:

/**
     * 直接下载zip包
     * @param response response
     * @param excels wb集合
     */
    public static void downFileByStream(HttpServletResponse response, List<XSSFWorkbook> excels){
        try {
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            ZipOutputStream zipOutputStream = new ZipOutputStream(toClient);
            for(int i=0; i<excels.size(); i++){
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                // 将Workbook写入内存流
                excels.get(i).write(baos);
                ZipEntry zipEntry = new ZipEntry("data" + i + ".xlsx");
                zipOutputStream.putNextEntry(zipEntry);
                // 将内存流写入Zip文件
                zipOutputStream.write(baos.toByteArray());
            }
            zipOutputStream.closeEntry();
            zipOutputStream.flush();
            zipOutputStream.close();
        }catch (Exception e){
            logger.error("downFileByStream==========fail:{}", e.getMessage());
        }
    }

针对场景2中的解决方案就是:把IO流初始化提到for循环里面,如实有了如下写法:

for(Integer pageNum = 1; pageNum < pageCount + 1; pageNum++) {
                //注意:每次循环遍历前都需要初始化新的wb对象
                //注意情况1:如果是初始化wb空对象然后手动添加title,下方三行代码不会报错
//                wb = new XSSFWorkbook();
//                buildScoreSheetTitle(wb);
//                buildTeacherSheetTitle(wb);

                //注意情况2:如果是初始化wb对象,并且以流的形式初始化,那么io流必须放在里面才行,如果放在for循环外面会报“Stream Closed”错误
                InputStream io = new FileInputStream(templateFile);
                wb = new XSSFWorkbook(io);
                ...
            }

错误场景2:调用接口没有另存为弹窗,但是F12查看接口结果返回一堆乱码

错误原因分析:可能是返回结果HttpServletResponse设置的setContentType格式不对。

正确的应该设置为如下,一定要设置为application/zip:

response.setHeader("Content-disposition", "attachment; filename=" + "test.zip");
response.setContentType("application/zip; charset=utf-8");

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

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

相关文章

【RabbitMQ】SpringBoot整合RabbitMQ实现延迟队列、TTL、DLX死信队列

目录 一、TTL 1、什么是TTL 2、设置TTL的两种方式 3、控制台设置TTL 4、SpringBoot实现两种方式设置TTL 1.给消息设置过期时间 2.给队列设置过期时间 二、DLX死信队列 1、什么是死信交换机与死信队列 2、消息何时会成为死信 3、队列如何绑定死信交换机与死信队列 4…

vscode“检测到 #include 错误,请更新 includepath。”的问题解决办法

目录 一.报错更新includepath​编辑 二.原因 三.解决方法 一.报错更新includepath 如图 二.原因 1.没有安装gcc 2.没有配置好环境 winR打开cmd,输入gcc -v,如果安装了gcc,会返回版本 三.解决方法 1.安装MinGW 2.添加MinGW环境变量 将bin文件夹的位置添加到系统环境变量中…

三分钟搭建个人博客技术栈Nuxt3+vite+mysql+koa2

最近也是想入一下Nuxt3的坑&#xff0c;然后就写了一个博客系统&#xff0c;目前已开源github&#xff0c;欢迎大家star&#xff01;&#xff01;&#xff01; 效果预览 网址&#xff1a;http://180.76.121.2:3000/ github地址 https://github.com/ztzzhi/ztzzhi-nuxt3-vite…

MySQL事物(基础篇)

MySQL事务事物的基本概念事物的ACID属性事务的使用事务隔离级别MVCC&ReadViewMySQL是否还存在幻读事物的基本概念 Transaction作为关系型数据库的核心组成&#xff0c;在数据安全方面有着非常重要的作用&#xff0c;本文会一步步解析事务的核心特性&#xff0c;以获得对事…

多云数据存储,理想与现实之间还差着什么?

去年底&#xff0c;“数据二十条”正式颁布&#xff0c;数据要素全面提速已是指日可待。 无疑&#xff0c;数据作为数字经济的基础&#xff0c;其价值的释放依赖于数据的流动、共享和应用。数据要素只有充分地流动和应用起来&#xff0c;才能够实现价值的最大化。 换而言之&a…

VPN、IPSEC、AH、ESP、IKE、DSVPN

目录 1.什么是数据认证&#xff0c;有什么作用&#xff0c;有哪些实现的技术手段? 2.什么是身份认证&#xff0c;有什么作用&#xff0c;有哪些实现的技术手段? 3.什么VPN技术? 4. VPN技术有哪些分类? 5. IPSEC技术能够提供哪些安全服务? 6. IPSEC的技术架构是什么?…

idea中使用git工具

目录一、IDEA中配置git二、git操作将项目设置成git仓库一、IDEA中配置git 打开idea&#xff0c;点击File–>Settings 点击版本控制&#xff0c;然后点击git 将你的git.exe安装目录填到下面位置 点击test可以看到显示了版本&#xff0c;说明配置成功 二、git操作 将项目设置…

geoserver更换默认的端口、修改默认密码

geoserver默认的端口是8080,有的时候会与其他的项目相冲突,我们的目标是将端口修改为8888,如何更改呢?geoserver正常安装的默认用户名密码为admin/geoserver,如何做一个修改呢将默认密码修改为其他的。 修改端口 分两种情况: (一)如果安装的时候,指定了端口,修改s…

elasticsearch基础教程

elasticsearch安装 有些软件对于安装路径有一定的要求&#xff0c;例如&#xff1a;路径中不能有空格&#xff0c;不能有中文&#xff0c;不能有特殊符号&#xff0c;等等。 为了避免不必要的麻烦&#xff0c;也懒得一一辨别踩坑&#xff0c;我们人为作出「统一的约定」&…

2023_深入学习HTML5

H5 基于html5和 css3和一部分JS API 结合的开发平台(环境) 语义化标签 header : 表示头部&#xff0c;块级元素 footer &#xff1a; 表示底部&#xff0c;块级元素 section &#xff1a;区块 nav &#xff1a; 表示导航链接 aside &#xff1a; 表示侧边栏 output &am…

Flume系列:Flume组件架构

目录 Apache Hadoop生态-目录汇总-持续更新 一&#xff1a;Flume 概述 二&#xff1a;Flume 基础架构 2.1&#xff1a;Agent 2.2&#xff1a;Source 2.3&#xff1a;Sink 2.4&#xff1a;Channel 1) Memory Channel 2) File Channel 3) Kafka Channel 2.5&#xff1a…

AI 绘画 API 超详细使用教程 - 附微信小程序接入代码

写在前面 【AI绘画/AI图像生成】已成为现下炙手可热的话题&#xff0c;AI 大模型训练的成本高昂&#xff0c;算法研究时间周期较长&#xff0c;对于大多数人来说&#xff0c;自研一套算法模型还是非常困难的&#xff0c;因此 AI 绘画 API 就应运而生&#xff0c;直接调用 AI 绘…

MRI图像配准技术及其未来

前言 早在20世纪40年代数字革命开始之前&#xff0c;图像配准就已经成为一个具有重要现实意义的过程。这技术首次应用于彩印&#xff0c;即将几种单色图案叠加在一起形成多色图案。为了生成最终所需的多色印刷品&#xff0c;各个层相对于另一个层的对齐必须是精确的。若个别层…

linux PAM模块简介

PAM模块简介1. 介绍1.1 概念1.2 验证过程简述2. 配置文件介绍2.1 PAM的模块类型2.2 PAM的控制标记2.3 PAM的模块路径3. 验证机制3.1 login的验证机制流程3.2 pam相关文件4. 示例4.1 ssh远程登录控制4.2 禁止账号间使用su命令切换4.3 限制root从tty1,tty2&#xff0c;tty5登录1.…

墨菲安全入选网络安全全景图,将持续深耕软件供应链安全垂直领域

2023年4月7日&#xff0c;中国网络安全领域的专业媒体安全牛正式发布第十版网络安全行业全景图&#xff0c;展现了我国网络安全行业的应用发展与变革创新&#xff0c;所有申请企业通过多个维度审核考量。墨菲安全作为一家专注于软件供应链安全领域的创新企业&#xff0c;以开发…

数据层的解决方案(NOSQL)

1.Redis 1.Redis是一款key-value存储结构的内存结构的内存级NoSQL数据库 支持多种数据存储 支持持久化 支持集群 2.服务器的启动命令&#xff1a; redis-server.exe redis.windows.conf 3.客户端启动命令 redis-cli.exe 4.SpringBoot整合Redis 1.导入相应的依赖 <…

ESP32学习笔记09-ADC多通道采集 dma方式传输

9. ADC多通道采集 dma方式传输 9.1 DIG SAR ADC 控制器 9.1.1特点 高性能。时钟更快,因此采样速率实现了大幅提升。支持多通道扫描模式。每个 SAR ADC 的测量规则可见样式表。扫描模式可配置为 单通道模式双通道模式交替模式。扫描可由软件或 I2S 总线发起。支持 DMA,扫描完…

Win10 安装配置 Hadoop 及 Spark

以下内容只针对 Win10 系统 1. 环境安装 (1) 安装Java并配置环境变量 https://www.oracle.com/java/technologies/downloads/#java8-windows (2) 安装Scala https://www.scala-lang.org/ 或 https://github.com/lampepfl/dotty/releases/tag/3.2.2 配置环境变量&#xff0…

谷歌研究科学家:ChatGPT秘密武器的演进与局限

来源&#xff5c;TalkRL OneFlow编译 翻译&#xff5c;徐佳渝、贾川 同样是基于GPT预训练模型&#xff0c;为什么ChatGPT的效果要远远超出GPT-3等前几代模型&#xff1f;答案已经揭晓&#xff0c;成就ChatGPT的秘密武器在于RLHF&#xff0c;也就是人类反馈的强化学习。 在预训…

SpringMVC的入门案例

三层架构和mvc 三层架构&#xff1a; 我们的开发架构一般都是基于两种形式&#xff0c;一种是C/S 架构&#xff0c;也就是客户端/服务器&#xff0c;另一种是 B/S 架构&#xff0c;也就是测览器服务器。在 avaEE开发中&#xff0c;几乎全都是基于 B/S 架构的开发。那么在 B/S…