Apache POI操作百万数据excel实战方案及JDK性能监控工具Jvisualvm实战

news2025/1/8 5:56:55

百万数据报表概述

文章目录

    • **百万数据报表概述**
    • **1、** **概述**
    • **2、 JDK性能监控工具介绍**
      • **2.1、 Jvisualvm概述**
      • **2.2、 Jvisualvm的位置**
      • **2.3、 Jvisualvm的使用**
    • **3、** **解决方案分析**
    • **4**、**百万数据报表导出**
      • **4.1** **需求分析**
      • **4.2** **解决方案**
        • **4.2.1** **思路分析**
        • **4.2.2** **原理分析**
      • **4.3** **代码实现**
        • 4.3.1、UserReportResult
        • 4.3.2、UserReportController
      • **4.4、对比测试**
    • **5**、**百万数据报表读取**
      • **5.1** **需求分析**
      • **5.2** **解决方案**
        • **5.2.1** **思路分析**
        • **5.2.2** **步骤分析**
        • **5.2.3** **原理分析**
      • **5.3** **代码实现**
        • **5.3.1** **自定义处理器**
        • **5.3.2** **自定义解析**
        • **5.3.3 PoiEntity**
        • **5.3.4 数据放resources下**
        • **5.3.5 UserReportController**
      • **5.4** **总结**

1、 概述

我们都知道Excel可以分为早期的Excel2003版本(使用POI的HSSF对象操作)和Excel2007版本(使用POI的XSSF

操作),两者对百万数据的支持如下:

  • Excel 2003:在POI中使用HSSF对象时,excel 2003最多只允许存储65536条数据,一般用来处理较少的数据 量。这时对于百万级别数据,Excel肯定容纳不了。

  • Excel 2007:当POI升级到XSSF对象时,它可以直接支持excel2007以上版本,因为它采用ooxml格式。这时 excel可以支持1048576条数据,单个sheet表就支持近百万条数据。但实际运行时还可能存在问题,原因是执 行POI报表所产生的行对象,单元格对象,字体对象,他们都不会销毁,这就导致OOM的风险。

2、 JDK性能监控工具介绍

没有性能监控工具一切推论都只能停留在理论阶段,我们可以使用Java的性能监控工具来监视程序的运行情况,包 括CUP,垃圾回收,内存的分配和使用情况,这让程序的运行阶段变得更加可控,也可以用来证明我们的推测。这里我们使用JDK提供的性能工具Jvisualvm来监控程序运行。

2.1、 Jvisualvm概述

VisualVM 是Netbeans的profifile子项目,已在JDK6.0 update 7 中自带,能够监控线程,内存情况,查看方法的

CPU时间和内存中的对 象,已被GC的对象,反向查看分配的堆栈

2.2、 Jvisualvm的位置

Jvisualvm位于JAVA_HOME/bin目录下,直接双击就可以打开该程序。如果只是监控本地的java进程,是不需要配

置参数的,直接打开就能够进行监控。首先我们需要在本地打开一个Java程序,例如我打开员工微服务进程,这时

在jvisualvm界面就可以看到与IDEA相关的Java进程了:
在这里插入图片描述

2.3、 Jvisualvm的使用

Jvisualvm使用起来比较简单,双击点击当前运行的进程即可进入到程序的监控界面
在这里插入图片描述

  • 概述:可以看到进程的启动参数。
  • 监视:左上:cpu利用率,gc状态的监控,右上:堆利用率,永久内存区的利用率,左下:类的监控,右下: 线程的监控 。
  • 线程:能够显示线程的名称和运行的状态,在调试多线程时必不可少,而且可以点进一个线程查看这个线程 的详细运行情况 。

3、 解决方案分析

对于百万数据量的Excel导入导出,只讨论基于Excel2007的解决方法。在ApachePoi 官方提供了对操作大数据量的

导入导出的工具和解决办法,操作Excel2007使用XSSF对象,可以分为三种模式:

  • 用户模式:用户模式有许多封装好的方法操作简单,但创建太多的对象,非常耗内存(之前使用的方法)
  • 事件模式:基于SAX方式解析XML,SAX全称Simple API for XML,它是一个接口,也是一个软件包。它是一 种XML解析的替代方法,不同于DOM解析XML文档时把所有内容一次性加载到内存中的方式,它逐行扫描文 档,一边扫描,一边解析。
  • SXSSF对象:是用来生成海量excel数据文件,主要原理是借助临时存储空间生成excel

在这里插入图片描述

这是一张Apache POI官方提供的图片,描述了基于用户模式,事件模式,以及使用SXSSF三种方式操作Excel的特

性以及CUP和内存占用情况。

4百万数据报表导出

4.1 需求分析

使用Apache POI完成百万数据量的Excel报表导出

4.2 解决方案

4.2.1 思路分析

基于XSSFWork导出Excel报表,是通过将所有单元格对象保存到内存中,当所有的Excel单元格全部创建完成之后 一次性写入到Excel并导出。当百万数据级别的Excel导出时,随着表格的不断创建,内存中对象越来越多,直至内 存溢出。Apache Poi提供了SXSSFWork对象,专门用于处理大数据量Excel报表导出。

4.2.2 原理分析

在实例化SXSSFWork这个对象时,可以指定在内存中所产生的POI导出相关对象的数量(默认100),一旦内存中 的对象的个数达到这个指定值时,就将内存中的这些对象的内容写入到磁盘中(XML的文件格式),就可以将这些 对象从内存中销毁,以后只要达到这个值,就会以类似的处理方式处理,直至Excel导出完成。

4.3 代码实现

在原有代码的基础上替换之前的XSSFWorkbook,使用SXSSFWorkbook完成创建过程即可。

4.3.1、UserReportResult

package com.example.payment.pojo;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

/**
 * @author :
 * @date :Created in 10:12 2022/12/22
 * @description :
 * @version: 1.0
 */
@Getter
@Setter
@NoArgsConstructor
@ToString
public class UserReportResult {

    private String userId;
    private String username;
    private String departmentName;
    private String mobile;
    private String timeOfEntry;
    private String companyId;
    private String sex;
    /**
     * 出生日期
     */
    private String dateOfBirth;
    /**
     * 最高学历
     */
    private String theHighestDegreeOfEducation;
    /**
     * 国家地区
     */
    private String nationalArea;
    /**
     * 护照号
     */
    private String passportNo;
    /**
     * 身份证号
     */
    private String idNumber;
    /**
     * 身份证照片-正面
     */
    private String idCardPhotoPositive;
    /**
     * 身份证照片-背面
     */
    private String idCardPhotoBack;
    /**
     * 籍贯
     */
    private String nativePlace;
    /**
     * 民族
     */
    private String nation;
    /**
     * 英文名
     */
    private String englishName;
    /**
     * 婚姻状况
     */
    private String maritalStatus;
    /**
     * 员工照片
     */
    private String staffPhoto;
    /**
     * 生日
     */
    private String birthday;
    /**
     * 属相
     */
    private String zodiac;
    /**
     * 年龄
     */
    private String age;
    /**
     * 星座
     */
    private String constellation;
    /**
     * 血型
     */
    private String bloodType;
    /**
     * 户籍所在地
     */
    private String domicile;
    /**
     * 政治面貌
     */
    private String politicalOutlook;
    /**
     * 入党时间
     */
    private String timeToJoinTheParty;
    /**
     * 存档机构
     */
    private String archivingOrganization;
    /**
     * 子女状态
     */
    private String stateOfChildren;
    /**
     * 子女有无商业保险
     */
    private String doChildrenHaveCommercialInsurance;
    /**
     * 有无违法违纪行为
     */
    private String isThereAnyViolationOfLawOrDiscipline;
    /**
     * 有无重大病史
     */
    private String areThereAnyMajorMedicalHistories;
    /**
     * QQ
     */
    private String qq;
    /**
     * 微信
     */
    private String wechat;
    /**
     * 居住证城市
     */
    private String residenceCardCity;
    /**
     * 居住证办理日期
     */
    private String dateOfResidencePermit;
    /**
     * 居住证截止日期
     */
    private String residencePermitDeadline;
    /**
     * 现居住地
     */
    private String placeOfResidence;
    /**
     * 通讯地址
     */
    private String postalAddress;
    /**
     * 联系手机
     */
    private String contactTheMobilePhone;
    /**
     * 个人邮箱
     */
    private String personalMailbox;
    /**
     * 紧急联系人
     */
    private String emergencyContact;
    /**
     * 紧急联系电话
     */
    private String emergencyContactNumber;
    /**
     * 社保电脑号
     */
    private String socialSecurityComputerNumber;
    /**
     * 公积金账号
     */
    private String providentFundAccount;
    /**
     * 银行卡号
     */
    private String bankCardNumber;
    /**
     * 开户行
     */
    private String openingBank;
    /**
     * 学历类型
     */
    private String educationalType;
    /**
     * 毕业学校
     */
    private String graduateSchool;
    /**
     * 入学时间
     */
    private String enrolmentTime;
    /**
     * 毕业时间
     */
    private String graduationTime;
    /**
     * 专业
     */
    private String major;
    /**
     * 毕业证书
     */
    private String graduationCertificate;
    /**
     * 学位证书
     */
    private String certificateOfAcademicDegree;
    /**
     * 上家公司
     */
    private String homeCompany;
    /**
     * 职称
     */
    private String title;
    /**
     * 简历
     */
    private String resume;
    /**
     * 有无竞业限制
     */
    private String isThereAnyCompetitionRestriction;
    /**
     * 前公司离职证明
     */
    private String proofOfDepartureOfFormerCompany;
    /**
     * 备注
     */
    private String remarks;

    /**
     * 离职时间
     */
    private String resignationTime;
    /**
     * 离职类型
     */
    private String typeOfTurnover;
    /**
     * 申请离职原因
     */
    private String reasonsForLeaving;
}

4.3.2、UserReportController

package com.example.payment.controller;

import com.example.payment.pojo.UserReportResult;
import com.example.payment.service.RiskCalculateService;
import lombok.extern.slf4j.Slf4j;
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.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * @author :
 * @date :Created in 10:00 2022/12/23
 * @description :
 * @version: 1.0
 */
@Controller
@RequestMapping("/userReport")
@Slf4j
public class UserReportController {


    @GetMapping("/download")
    public void download(HttpServletResponse response){
        log.info("[userReport-download]开始:{}");
        try {
            //1.模拟用户数据报表数据
            List<UserReportResult> list = new ArrayList<>();
            for (int i = 0; i < 100000; i++) {
                UserReportResult userReportResult = new UserReportResult();
                userReportResult.setEducationalType(i+"");
                userReportResult.setAge(i+"");
                userReportResult.setBirthday(i+"");
                userReportResult.setUserId(i+"");
                userReportResult.setUsername(i+"");
                userReportResult.setMobile(i+"");
                userReportResult.setTheHighestDegreeOfEducation(i+"");
                userReportResult.setNationalArea(i+"");
                userReportResult.setPassportNo(i+"");
                userReportResult.setNativePlace(i+"");
                userReportResult.setZodiac(i+"");
                userReportResult.setTimeOfEntry(i+"");
                userReportResult.setTypeOfTurnover(i+"");
                userReportResult.setReasonsForLeaving(i+"");
                userReportResult.setResignationTime(i+"");
                list.add(userReportResult);
            }
            //2.构造Excel
            //创建工作簿
            //SXSSFWorkbook : 百万数据报表
            //Workbook wb = new XSSFWorkbook();
            SXSSFWorkbook wb = new SXSSFWorkbook(100); //阈值,内存中的对象数量最大数量
            //构造sheet
            Sheet sheet = wb.createSheet();
            //创建行
            //标题
            String [] titles = "编号,姓名,手机,最高学历,国家地区,护照号,籍贯,生日,属相,入职时间,用户类型,描述,时间".split(",");
            //处理标题

            Row row = sheet.createRow(0);

            int titleIndex=0;
            for (String title : titles) {
                Cell cell = row.createCell(titleIndex++);
                cell.setCellValue(title);
            }

            int rowIndex = 1;
            Cell cell=null;
            for(int i=0;i<10;i++) {
                for (UserReportResult userReportResult : list) {
                    row = sheet.createRow(rowIndex++);
                    // 编号,
                    cell = row.createCell(0);
                    cell.setCellValue(userReportResult.getUserId());
                    // 姓名,
                    cell = row.createCell(1);
                    cell.setCellValue(userReportResult.getUsername());
                    // 手机,
                    cell = row.createCell(2);
                    cell.setCellValue(userReportResult.getMobile());
                    // 最高学历,
                    cell = row.createCell(3);
                    cell.setCellValue(userReportResult.getTheHighestDegreeOfEducation());
                    // 国家地区,
                    cell = row.createCell(4);
                    cell.setCellValue(userReportResult.getNationalArea());
                    // 护照号,
                    cell = row.createCell(5);
                    cell.setCellValue(userReportResult.getPassportNo());
                    // 籍贯,
                    cell = row.createCell(6);
                    cell.setCellValue(userReportResult.getNativePlace());
                    // 生日,
                    cell = row.createCell(7);
                    cell.setCellValue(userReportResult.getBirthday());
                    // 属相,
                    cell = row.createCell(8);
                    cell.setCellValue(userReportResult.getZodiac());
                    // 入职时间,
                    cell = row.createCell(9);
                    cell.setCellValue(userReportResult.getTimeOfEntry());
                    // 离职类型,
                    cell = row.createCell(10);
                    cell.setCellValue(userReportResult.getTypeOfTurnover());
                    // 离职原因,
                    cell = row.createCell(11);
                    cell.setCellValue(userReportResult.getReasonsForLeaving());
                    // 离职时间
                    cell = row.createCell(12);
                    cell.setCellValue(userReportResult.getResignationTime());
                }
            }
                String fileName = URLEncoder.encode("2022-12-22用户信息.xlsx", "UTF-8");
                response.setContentType("application/octet-stream");
                response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("ISO8859-1")));
                response.setHeader("filename", fileName);
                wb.write(response.getOutputStream());
        }catch (Exception e) {
            log.error("[userReport-download]error:{}", e.getMessage());
        }
    }

4.4、对比测试

(1)XSSFWorkbook生成百万数据报表

使用XSSFWorkbook生成Excel报表,时间较长,随着时间推移,内存占用原来越多,直至内存溢出

在这里插入图片描述

(2)SXSSFWorkbook生成百万数据报表

使用SXSSFWorkbook生成Excel报表,内存占用比较平缓
在这里插入图片描述

5百万数据报表读取

5.1 需求分析

使用POI基于事件模式解析案例提供的Excel文件

5.2 解决方案

5.2.1 思路分析

  • 用户模式:加载并读取Excel时,是通过一次性的将所有数据加载到内存中再去解析每个单元格内容。当Excel 数据量较大时,由于不同的运行环境可能会造成内存不足甚至OOM异常。
  • 事件模式:它逐行扫描文档,一边扫描一边解析。由于应用程序只是在读取数据时检查数据,因此不需要将 数据存储在内存中,这对于大型文档的解析是个巨大优势。

5.2.2 步骤分析

(1)设置POI的事件模式

  • 根据Excel获取文件流 ;
  • 根据文件流创建OPCPackage ;
  • 创建XSSFReader对象 ;

(2)Sax解析

  • 自定义Sheet处理器 ;
  • 创建Sax的XmlReader对象 ;
  • 设置Sheet的事件处理器 ;
  • 逐行读取 ;

5.2.3 原理分析

我们都知道对于Excel2007的实质是一种特殊的XML存储数据,那就可以使用基于SAX的方式解析XML完成Excel的 读取。SAX提供了一种从XML文档中读取数据的机制。它逐行扫描文档,一边扫描一边解析。由于应用程序只是在 读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势 。

在这里插入图片描述

5.3 代码实现

5.3.1 自定义处理器

重点关注endRow方法
package com.example.payment.utils;

import com.example.payment.pojo.PoiEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.usermodel.XSSFComment;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author :
 * @date :Created in 17:02 2022/12/22
 * @description :自定义Sheet基于Sax的解析处理器
 * @version: 1.0
 */
@Slf4j
public class SheetHandler implements XSSFSheetXMLHandler.SheetContentsHandler {

    //封装实体对象
    private PoiEntity entity;

    private AtomicInteger count = new AtomicInteger(0);

        /**
         * 解析行开始
         */
        @Override
        public void startRow(int rowNum) {
           if (rowNum > 0) {
             entity = new PoiEntity();
           }
        }
        /**
        * 解析每一个单元格
        */
        @Override
        public void cell(String cellReference, String formattedValue, XSSFComment comment) {
            if(entity != null) {
                switch (cellReference.substring(0, 1)) {
                    case "A":
                       entity.setId(formattedValue);
                       break;
                    case "B":
                       entity.setBreast(formattedValue);
                       break;
                    case "C":
                       entity.setAdipocytes(formattedValue);
                       break;
                    case "D":
                       entity.setNegative(formattedValue);
                       break;
                    case "E":
                       entity.setStaining(formattedValue);
                       break;
                    case "F":
                       entity.setSupportive(formattedValue);
                       break;
                    default:
                       break;
                }
            }
        }

        /**
         * 解析行结束
         */
         public void endRow(int rowNum) {
             //TODO 将数据存表等操作
             log.info("[解析行结束]第{}行,entity:{}", count.incrementAndGet(), entity);
         }

         /**
          * 处理头尾
          */
         public void headerFooter(String text, boolean isHeader, String tagName) {
         }

}

5.3.2 自定义解析

package com.example.payment.utils;

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.InputStream;

/**
 * @author :
 * @date :Created in 17:13 2022/12/22
 * @description :自定义Excel解析器
 * @version: 1.0
 */
public class ExcelParser {

    public void parse(InputStream is) throws Exception {
        //1.根据Excel获取OPCPackage对象
        OPCPackage pkg = OPCPackage.open(is);
        try {
            //2.创建XSSFReader对象
            XSSFReader reader = new XSSFReader(pkg);
            //3.获取SharedStringsTable对象
            SharedStringsTable sst = reader.getSharedStringsTable();
            //4.获取StylesTable对象
            StylesTable styles = reader.getStylesTable();
            //5.创建Sax的XmlReader对象
            XMLReader parser = XMLReaderFactory.createXMLReader();
            //6.设置处理器
            parser.setContentHandler(new XSSFSheetXMLHandler(styles, sst, new SheetHandler(), false));
            XSSFReader.SheetIterator sheets = (XSSFReader.SheetIterator)
            reader.getSheetsData();
            //7.逐行读取
            while (sheets.hasNext()) {
                InputStream sheetstream = sheets.next();
                InputSource sheetSource = new InputSource(sheetstream);
                try {
                  parser.parse(sheetSource);
                } finally {
                  sheetstream.close();
                }
            }
        } finally {
            pkg.close();
        }
    }

}

5.3.3 PoiEntity

package com.example.payment.pojo;


public class PoiEntity {
    private String id;
    private String breast;
    private String adipocytes;
    private String negative;
    private String staining;
    private String supportive;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getBreast() {
        return breast;
    }

    public void setBreast(String breast) {
        this.breast = breast;
    }

    public String getAdipocytes() {
        return adipocytes;
    }

    public void setAdipocytes(String adipocytes) {
        this.adipocytes = adipocytes;
    }

    public String getNegative() {
        return negative;
    }

    public void setNegative(String negative) {
        this.negative = negative;
    }

    public String getStaining() {
        return staining;
    }

    public void setStaining(String staining) {
        this.staining = staining;
    }

    public String getSupportive() {
        return supportive;
    }

    public void setSupportive(String supportive) {
        this.supportive = supportive;
    }

    @Override
    public String toString() {
        return "PoiEntity{" +
                "id='" + id + '\'' +
                ", breast='" + breast + '\'' +
                ", adipocytes='" + adipocytes + '\'' +
                ", negative='" + negative + '\'' +
                ", staining='" + staining + '\'' +
                ", supportive='" + supportive + '\'' +
                '}';
    }
}

5.3.4 数据放resources下

在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/13908ab340034e50998a90b6a61755b8.png

5.3.5 UserReportController

package com.example.payment.controller;

import com.example.payment.pojo.UserReportResult;
import com.example.payment.service.RiskCalculateService;
import lombok.extern.slf4j.Slf4j;
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.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * @author :
 * @date :Created in 10:00 2022/12/23
 * @description :
 * @version: 1.0
 */
@Controller
@RequestMapping("/userReport")
@Slf4j
public class UserReportController {


    @GetMapping("/read")
    public void download(HttpServletResponse response){
        log.info("[userReport-download]开始:{}");
        try {
            ExcelParser excelParser = new ExcelParser();
            InputStream is = this.getClass().getClassLoader().getResourceAsStream("demo.xlsx");
            excelParser.parse(is);
        }catch (Exception e) {
            log.error("[userReport-download]error:{}", e.getMessage());
        }
    }

5.4 总结

通过简单的分析以及运行两种模式进行比较,可以看到用户模式下使用更简单的代码实现了Excel读取,但是在读 取大文件时CPU和内存都不理想;而事件模式虽然代码写起来比较繁琐,但是在读取大文件时CPU和内存更加占 优。

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

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

相关文章

玩转门店管理新方法,促进营收利润加倍

门店管理的好坏是门店是否可以运营下去的重要因素&#xff0c;决定了门店的存亡与兴衰。以往很多门店管理者为了更简单方便&#xff0c;采用的是传统方式进行管理。即运用手工的方式记录和计算门店的各种信息。但是随着门店规模的扩大、商品种类的丰富、客户需求的增加以及员工…

普惠微光汇聚暖阳,招联携手奋斗者筑梦前行

撰稿 | 多客 来源 | 贝多财经 近年来&#xff0c;受疫情反复带来的经济下行压力&#xff0c;收入减少生活难以保障成了社会一大难题。值此艰难时刻&#xff0c;一大批爱心企业出资出力&#xff0c;纷纷用实际行动诠释企业的使命和担当。口罩、防护服、矿泉水、食品、药物、免费…

vue配置webpack生产环境.env.production、测试环境.env.development(配置不同环境的打包访问地址)

vue-cli区分办法 vue配置生产环境.env.production、测试环境.env.development vue配置webpack生产环境、测试环境 在使用webpack创建完vue2项目的时候&#xff0c;为了解决生产打包、测试打包对应的全局变量不一致的问题。 首先看一下package.json的改动&#xff1a; "…

MARL算法系列(1):IQL【原理+代码实现】

原文题目&#xff1a;Multiagent cooperation and competition with deep reinforcement learning 作者&#xff1a;Tampuu, Ardi and Matiisen, Tambet and Kodelja, Dorian等 发表时间&#xff1a;2017年 主要内容&#xff1a;相互独立的两个DQN智能体&#xff0c;竞争任务下…

2022年威胁隐私和安全的数个“罪魁祸首”

随着互联网技术的不断发展&#xff0c;我们对网络的信任也在不断增加&#xff0c;甚至将自己的私人数据委托给各种在线平台&#xff0c;如个人数字身份信息、银行账户、各种机密信息。网络一方面的确带来变革型的进步&#xff0c;但另一方面&#xff0c;频频曝光的数据泄露事件…

VueJs中setup的使用(下)

前言在Vue当中,父组件想要向子组件传值,是通过在父组件标签上通过自定义属性实现的,而在子组件中是通过props进行接收在Vue2.0里面,在子组件中的选项式API配置项选项中props进行接收就可以了的,在子组件中的模板中可以直接使用但在Vue3里面与Vue2.0存在一些差异,这个主要是针对…

excel文件管理:如何进行密码保护和破解? 下篇

在上篇文章中&#xff0c;我们提到了设置工作簿的打开权限密码、修改权限密码、保护工作簿的密码、允许编辑区域的密码&#xff0c;并且讲到了两种破解excel密码的方式。今天&#xff0c;我们书接上回&#xff0c;继续讲解excel中常见的密码保护和破解方式&#xff0c;一起来看…

浅谈屏幕适配

文章目录1. 概述2. 屏幕尺寸3. 屏幕分辨率4. 屏幕像素密度5. dp、sp、px6. mdpi、hdpi、xdpi..7. 屏幕分辨率限定符8. 最小宽度限定符8.1 获取设计图最小宽度(dp)8.2 生成对应的dimens.xml文件8.3 尺寸限定符8.4 其它9. 今日头条相关9.1 系统状态栏获取不对问题9.2 autosize1. …

Elasticsearch8.X入门实战(二)Elasticsearch集群架构

Elasticsearch集群由一个或多个节点(服务器)组成,这些节点一起保存Elasticsearch的所有数据,并提供跨所有节点的联合索引和搜索功能。集群由一个唯一的名称来标识,该名称默认为“elasticsearch”(可以在配置文件中修改)。当某个节点被设置为相同的集群名称时,该节点才能…

Docker容器的简单介绍与使用

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;曾经在某央企公司实习&#xff0c;目前入职某税务公司。本篇文章将记录和分享docker容器相关的知识点。 本篇文章记录的基础知识&#xff0c;适合在学Java的小白&#xff0c;也适合复习中&#x…

如何更好地进行 Android 组件化开发——路由原理篇

前言 组件化开发的会实现代码隔离&#xff0c;在开发时访问不到模块的代码&#xff0c;降低代码耦合度。那么如何跳转组件的页面、如何进行组件间的通信是个问题。这通常会使用到 ARouter、TheRouter、WMRouter 等路由框架。可能有不少人只知道怎么去调用&#xff0c;并不知道…

Pod内容详情梳理

本篇是笔者的一篇读书笔记&#xff0c;用于梳理pod的详情&#xff0c;方便理解和学习&#xff0c;也方便后续自己查询。一、Pod的概述Pod是k8s里面典型的CR&#xff0c;从它的元数据来看&#xff0c;具有所有CR的基本数据构成&#xff0c;分别是 version、kind&#xff0c;以及…

迅为RK3568开发板支持多屏同显/异显动态方案

iTOP-RK3568开发板采用四核Cortex-A55处理器&#xff0c;芯片内置VOP控制器&#xff0c;支持HDMI、LVDS、MIPI、EDP四种显示接口的多屏同显、异显和异触&#xff0c;可有效提高行业定制的拓展性。 三屏同显&#xff1a; 三屏异显&#xff1a; 双屏同显&#xff1a; 双屏异显&am…

Docker容器里进程的 pid 是如何申请出来的?

大家好&#xff0c;我是飞哥&#xff01;如果大家有过在容器中执行 ps 命令的经验&#xff0c;都会知道在容器中的进程的 pid 一般是比较小的。例如下面我的这个例子。# ps -ef PID USER TIME COMMAND1 root 0:00 ./demo-ie13 root 0:00 /bin/bash21 root …

编程小技巧9-如何生成没有水印的代码图片(IDEA carbon-now-sh插件使用教程)

陈老老老板&#x1f9b8;&#x1f468;‍&#x1f4bb;本文专栏&#xff1a;快速变成小技巧&#xff08;主要讲一些平时常用的、有助于提高开发素的内容&#xff09;&#x1f468;‍&#x1f4bb;本文简述&#xff1a;本文讲一下使用carbon-now-sh插件生成图片超详细教程。&…

STM32

一&#xff1a;生成独立的他.h和.c文件 勾选后&#xff0c;生成单独的.h和.c文件。不勾选的话都在main里面。 二&#xff1a;常用。 1&#xff1a;电平输出。 HAL_GPIO_WritePin(PIN_LED_1_GPIO_Port, PIN_LED_1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(PIN_LED_1_GPIO_Port, …

django 登录流程实现

一、简介&#xff1a; 1、用户输入正确的用户名、密码、验证码点击登录即可跳转到管理员页面。 2、用户输入错误的用户名或者密码或者验证码需要错误信息提示&#xff08;数据校验&#xff09; 二、实现步骤 1、新建一个项目&#xff08;创建项目过程和数据库略&#xff0c;…

签完三方后无法去实习,有什么可以弥补的吗?

作者&#xff1a;阿秀校招八股文学习网站&#xff1a;https://interviewguide.cn这是阿秀的第「228」篇原创你好&#xff0c;我是阿秀。2023届秋招已经步入尾声&#xff0c;很多小伙伴都已经找到工作&签约三方&#xff0c;慢慢结束了自己的秋招之旅&#xff0c;不过也有一些…

Local Attention和动态深度卷积间的关系

摘要 Local Vision Transformer 是分别在一个个小的局部窗口中进行注意力计算。 作者将局部注意力重新定义为通道级的局部连接层&#xff08;channel-wise locally-connected layer&#xff09;&#xff0c;并4个方面进行分析&#xff1a;两种网络的正则化方式&#xff0c;稀疏…

C语言实现九大排序算法(建议收藏!)

文章目录排序算法稳定性1. 插入排序原理排序过程代码实现性能分析2. 希尔排序原理排序过程关于增量取值代码实现性能分析3. 选择排序原理排序过程代码实现性能分析4. 堆排序原理排序过程代码实现性能分析5. 冒泡排序原理排序过程代码实现性能分析6. 快速排序原理Hoare法挖坑法前…