SpringBoot使用EasyExcel批量导出500万数据

SpringBoot使用EasyExcel批量导出500万数据

  • 说明
  • excel版本比较
  • EasyExcel介绍
  • 项目目录
  • mysql对应表建表语句
  • pom.xml
  • application.yml配置类
  • 启动类代码
  • OrderInfo 实体类
  • OrderInfoExcel excel模版标题类(EasyExcel需要使用这个)
  • TestController控制层
  • 接口层TestService
  • TestServiceImpl实现层
  • TestDao数据接口层
  • dao层对应mapper.xml自定义sql语句
  • 测试结果如下

说明

记录下学习SpringBoot使用EasyExcel批量导出百万数据。留着以后备用。
本地环境mysql安装的5.7版本,项目使用jdk1.8版本,项目使用的mysql驱动版本为8.0版本。
这一篇博客内容代码基于我的这篇博客:
SpringBoot使用mybatis批量新增500万数据到mysql数据库Demo,在自己这篇博客的代码上做改动写批量导出功能。

excel版本比较

03版excel:HSSFWorkbook为2003之前的版本,扩展名为.xls。每个sheet页最多65536行,最大列数是256列。当应用场景数据小于65536行数据时,可以使用03版excel来导出,导出性能很高。

07版excel:XSSFWorkbook为2007之后的版本,扩展名为.xlsx。每个sheet页最多1048576行,超过这个行数,导出的时候后端程序就会抛异常。

当数据量超过65536行进行大数据量导出时可以用07版excel,当用POI进行百万数据导出时,会很占用内存,很有可能导致程序出现OOM(内存溢出),而且为了让XSSFWorkbook效率提升,用了Workbook第三个实现类SXSSFWorkbook。SXSSFWorkbook用来处理大数据量以及超大数据量的导出,只是 SXSSFWorkbook只支持.xlsx格式,不支持.xls格式。

EasyExcel介绍

EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
它能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。

easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便。

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

项目目录

在这里插入图片描述

mysql对应表建表语句

CREATE TABLE `order_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `period` int(11) NOT NULL COMMENT '账期月份',
  `amount` decimal(20,2) NOT NULL COMMENT '金额',
  `user_name` varchar(20) NOT NULL COMMENT '下单人',
  `phone` varchar(11) NOT NULL COMMENT '手机号',
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `creator` varchar(20) NOT NULL COMMENT '创建人',
  `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `modifier` varchar(20) NOT NULL COMMENT '修改人',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_period` (`period`),
  KEY `idx_modified` (`modified`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='订单信息表';

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>batching</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>batching</name>
    <description>batching</description>
    <properties>
        <java.version>1.8</java.version>
        <!--下列版本都是2022/04/16最新版本,都是父项目的基本依赖,用来子项目继承父项目依赖-->
        <pagehelper-starter.version>1.4.2</pagehelper-starter.version>
        <mybatis.version>3.5.9</mybatis.version>
        <mysql-connector.version>8.0.28</mysql-connector.version>
        <druid.version>1.2.9</druid.version>
        <lombok.version>1.18.22</lombok.version>
        <easyexcel.version>3.2.1</easyexcel.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--MyBatis分页插件1.4.2版本才支持spring-boot2.6.6-->
        <!--pagehelper分页官网:https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter/-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>${pagehelper-starter.version}</version>
        </dependency>
        <!-- MyBatis就是用来创建数据库连接进行增删改查等操作,提供了原生JDBC,Connection,Statement,ResultSet这些底层-->
        <!-- MyBatis官网:https://mybatis.org/mybatis-3/zh/dependency-info.html-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <!--Mysql数据库驱动-->
        <!--Mysql驱动官网:https://mvnrepository.com/artifact/mysql/mysql-connector-java/-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-connector.version}</version>
        </dependency>
        <!--集成druid连接池-->
        <!--druid版本官网:https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--lombok-->
        <!--lombok官网:https://mvnrepository.com/artifact/org.projectlombok/lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
        <!--集成阿里巴巴EasyExcel用于大批量数据导出-->
        <!--官网地址:https://easyexcel.opensource.alibaba.com/-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>${easyexcel.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml配置类

server:
  port: 8080

mybatis:
  mapper-locations:
    - classpath:mapper/*.xml #找到mybatis位置,自定义sql语句
  #当查询语句中resultType="java.util.HashMap"时,如果返回的字段值为null时,设置如下参数为true,让它返回
  configuration:
    call-setters-on-nulls: true

#打印sql语句
logging:
  level:
    com.example.batching.dao: debug

spring:
  datasource:
    #mysql批量新增需要在url后面添加rewriteBatchedStatements=true才能生效
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
    driverClassName: com.mysql.cj.jdbc.Driver #mysql8.0驱动,mysql5.7驱动是com.mysql.jdbc.Driver
    username: 你自己的数据库用户名
    password: 你自己的数据库密码
    druid:
      initial-size: 3 #连接池初始大小
      min-idle: 5 #最小空闲连接数
      max-active: 20 #最大空闲连接数
      web-stat-filter:
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" #不统计这些请求数据
      stat-view-servlet: #访问监控网页的用户名和密码
        #默认为true,内置监控页面首页/druid/index.html
        enabled: true
        login-username: druid
        login-password: druid


启动类代码

package com.example.batching;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BatchingApplication {

    public static void main(String[] args) {
        SpringApplication.run(BatchingApplication.class, args);
    }

}

OrderInfo 实体类

package com.example.batching.entity;

import lombok.Data;

import java.math.BigDecimal;

@Data
public class OrderInfo {
    private int id;
    private int period;//账期月份
    private BigDecimal amount;//金额
    private String userName;//下单人
    private String phone;//手机号
    private String created;//创建时间
    private String creator;//创建人
    private String modified;//修改时间
    private String modifier;//修改人
    private int pageNum;//页数
    private int pageSize;//每页所返回行数
}

OrderInfoExcel excel模版标题类(EasyExcel需要使用这个)

package com.example.batching.excelmode;

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;

import java.math.BigDecimal;

public class OrderInfoExcel {
    @ExcelProperty(value="id")
    private int id;
    @ExcelProperty(value="账期月份")
    private int period;//账期月份
    @ExcelProperty(value="金额")
    private BigDecimal amount;//金额
    @ExcelProperty(value="下单人")
    private String userName;//下单人
    @ExcelProperty(value="手机号")
    private String phone;//手机号
    @ExcelProperty(value="创建时间")
    private String created;//创建时间
    @ExcelProperty(value="创建人")
    private String creator;//创建人
    @ExcelProperty(value="修改时间")
    private String modified;//修改时间
    @ExcelProperty(value="修改人")
    private String modifier;//修改人
    @ExcelIgnore
    private int pageNum;//页数
    @ExcelIgnore
    private int pageSize;//每页所返回行数
}

TestController控制层

批量导出方法看batchExport方法。

package com.example.batching.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.example.batching.entity.OrderInfo;
import com.example.batching.excelmode.OrderInfoExcel;
import com.example.batching.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping(value = "/order")
public class TestController {

    @Autowired
    private TestService testService;

    //批量新增数据处理
    @PostMapping(value = "/batchSave")
    public String batchSave() {
        //随机生成电话号码
        String[] start = {"130", "131", "132", "133", "134", "150", "151", "155", "158", "166", "180", "181", "184", "185", "188"};
        List<OrderInfo> orderInfoList=new ArrayList<>();
        //生成500万数据批量新增到mysql数据库里面
        for(int i=1;i<=5000000;i++){
            OrderInfo orderInfo=new OrderInfo();
            orderInfo.setPeriod(202206);
            orderInfo.setAmount(new BigDecimal(i));
            orderInfo.setUserName("用户"+i);
            orderInfo.setPhone(start[(int) (Math.random() * start.length)]+(10000000+(int)(Math.random()*(99999999-10000000+1))));
            orderInfo.setCreator("用户"+i);
            orderInfo.setModifier("用户"+i);
            orderInfoList.add(orderInfo);
            //每一万条数据进行批量新增
            if(i%10000==0){
                testService.batchSave(orderInfoList);
                //新增完成后清空list集合防止内存溢出
                orderInfoList.clear();
                System.out.println("当前已新增完数据:"+i+"行");
            }
        }
        return "成功";
    }

    //批量导出数据到excel
    @GetMapping(value = "/batchExport")
    public void batchExport(HttpServletResponse response) {

        try{
            OutputStream outputStream =response.getOutputStream();
            //查询出总数据量大小,这里为500万
            int count=testService.batchExportCount();
            System.out.println("count="+count);
            //根据总数得到总页数
            int totalPage=(count-1)/100000+1;//总页数,每页10万行数据
            System.out.println("totalPage="+totalPage);
            //xlsx每个sheet页最大数据行为1048576,超过这个数值就会报错,所以这里将500万数据分5个导出到5个sheet页
            //根据总数得到每页sheet应该分几个sheet,每个sheet导入100万数据,500万就是5个sheet
            int totalSheet=(count-1)/1000000+1;//总sheet页数,每个sheet100万行数据
            System.out.println("totalSheet="+totalSheet);
            //设置初始页数
            OrderInfo orderInfo=new OrderInfo();
            orderInfo.setPageNum(0);//初始页,从0开始
            orderInfo.setPageSize(100000);//每页返回数据
            //文件名
            String fileName="批量测试导出.xlsx";
            //使用EasyExcel进行导出
            ExcelWriter excelWriter = EasyExcel.write(outputStream, OrderInfoExcel.class).build();
            //这里最终会写到5个sheet里面
            for (int i = 0; i < totalSheet; i++) {
                //writerSheet第一个参数表示往几个sheet开始写数据,从0开始表示第一个
                WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();
                //分页去数据库查询数据
                for(int j = orderInfo.getPageNum(); j < totalPage; j++){
                    //页数,对应后端数据库来说是索引
                    int pageNum=j*100000;
                    //每页要查询的行数
                    int pageSize=orderInfo.getPageSize();
                    //根据分页参数去查询每页数据
                    List<OrderInfo> data = testService.batchExport(pageNum,pageSize);
                    excelWriter.write(data, writeSheet);
                    System.out.println("已导出数据:"+(pageNum+100000));
                    if((pageNum+100000)%1000000==0){
                        //记录当前页数j并加1,并跳出这个for循环,往下一个sheet页写入数据
                        orderInfo.setPageNum(j+1);
                        break;
                    }
                }
            }
            //下载
            response.reset();
            response.setContentType("application/octet-stream; charset=utf-8");//以流的形式对文件进行下载
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));//对文件名编码,防止文件名乱码
            excelWriter.finish();
            outputStream.flush();
            outputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

接口层TestService

package com.example.batching.service;

import com.example.batching.entity.OrderInfo;

import java.util.List;

public interface TestService {
    void batchSave(List<OrderInfo> orderInfoList);

    int batchExportCount();

    List<OrderInfo> batchExport(int pageNum, int pageSize);
}

TestServiceImpl实现层

package com.example.batching.service.impl;

import com.example.batching.dao.TestDao;
import com.example.batching.entity.OrderInfo;
import com.example.batching.service.TestService;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Service
public class TestServiceImpl implements TestService {

    @Resource
    private TestDao testDao;

    @Resource
    private SqlSessionFactory sqlSessionFactory;

    @Override
    public void batchSave(List<OrderInfo> orderInfoList) {
        //批量新增处理,需要在jdbc连接那里添加rewriteBatchedStatements=true属性,批量新增才能生效
        // ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。自动提交不关闭的前提下,默认设置是这个
        // ExecutorType.REUSE: 这个执行器类型会复用预处理语句。
        // ExecutorType.BATCH: 这个执行器会批量执行所有更新语句,如果 SELECT 在它们中间执行还会标定它们是 必须的,来保证一个简单并易于理解的行为。
        //如果自动提交设置为true,将无法控制提交的条数,改为最后统一提交
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        try {
            TestDao testMapper = sqlSession.getMapper(TestDao.class);
            orderInfoList.stream().forEach(orderInfo -> testMapper.batchSave(orderInfo));
            //提交数据
            sqlSession.commit();
        } catch (Exception e) {
            sqlSession.rollback();
        } finally {
            sqlSession.close();
        }
    }

    @Override
    public int batchExportCount() {
        return testDao.batchExportCount();
    }

    @Override
    public List<OrderInfo> batchExport(int pageNum, int pageSize) {
        return testDao.batchExport(pageNum, pageSize);
    }
}

TestDao数据接口层

package com.example.batching.dao;

import com.example.batching.entity.OrderInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface TestDao {
    void batchSave(OrderInfo orderInfo);

    int batchExportCount();

    List<OrderInfo> batchExport(@Param("pageNum") int pageNum, @Param("pageSize") int pageSize);
}

dao层对应mapper.xml自定义sql语句

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace必须指向Dao接口 -->
<mapper namespace="com.example.batching.dao.TestDao">

    <insert id="batchSave" parameterType="com.example.batching.entity.OrderInfo">
        INSERT INTO order_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="period != null">
                period,
            </if>
            <if test="amount != null">
                amount,
            </if>
            <if test="userName != null">
                user_name,
            </if>
            <if test="phone != null">
                phone,
            </if>
            <if test="creator != null">
                creator,
            </if>
            <if test="modifier != null">
                modifier,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="period != null">
                #{period},
            </if>
            <if test="amount != null">
                #{amount},
            </if>
            <if test="userName != null">
                #{userName},
            </if>
            <if test="phone != null">
                #{phone},
            </if>
            <if test="creator != null">
                #{creator},
            </if>
            <if test="modifier != null">
                #{modifier},
            </if>
        </trim>
    </insert>

    <select id="batchExportCount" resultType="java.lang.Integer">
        select count(id) num from order_info
    </select>

    <select id="batchExport" parameterType="java.lang.Integer" resultType="com.example.batching.entity.OrderInfo">
        select id,period,amount,user_name userName,phone,created,creator,modified,modifier
        from order_info
        order by id
        limit #{pageNum},#{pageSize}
    </select>
</mapper>

测试结果如下

浏览器调用接口返回如下:
在这里插入图片描述
后台控制台打印如下:
在这里插入图片描述
越往后进行深翻页,查询耗时越长
在这里插入图片描述
从22时33分01秒到22时36分52秒耗时接近4分钟才将所有数据进行导出。
所以这里的性能瓶颈在sql优化那一块,怎么才能深翻页的时候提高sql性能,让500万
数据更快导出。

excel文件结果如下:
id自增从1到5000000,每个sheet页100万数据。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

十五、docker学习-docker核心docker数据卷

什么是数据卷 当我们在使用docker容器的时候&#xff0c;会产生一系列的数据文件&#xff0c;这些数据文件在我们删除docker容器时是会消失的&#xff0c;但是其中产生的部分内容我们是希望能够把它给保存起来另作用途的&#xff0c;Docker将应用与运行环境打包成容器发布&…

创建启动前端vue与后端python/flask,前后端分离,相互传递参数

创建启动vue 确保你已经安装了Node.js和npm 安装vue npm install -g vue/cli创建vue项目&#xff1a; vue create my-project cd my-project启动vue npm run serve如果安装vue报错&#xff1a;管理员权限模式打开powershell Windows PowerShell 版权所有&#xff08;C&#…

斐波那契数列

目录 斐波那契数列 斐波那契数列和黄金分割率的关联 解析表达式 练习 斐波那契数列 一个人将一对兔子放到一个封闭的围墙内&#xff0c;并假设每对兔子每个月都繁殖出一对兔子&#xff0c;且新生兔子从第二个月开始有繁殖能力&#xff0c;那么一年以后这个封闭的围墙内有多…

kotlin Flow系列之 - 冷流SafeFlow源码解析之 - Safe在那里?

本文涉及源码基于kotlinx-coroutines-core-jvm:1.7.1 kotlin 协成系列文章: 你真的了解kotlin中协程的suspendCoroutine原理吗? Kotlin Channel系列&#xff08;一&#xff09;之读懂Channel每一行源码 kotlin Flow系列之-冷流SafeFlow源码解析之 - Safe在那里&#xff1f; ko…

vue el-table的每行操作el-button添加单独的loading效果实现

vue el-table的每行操作el-button添加单独的loading效果实现 效果图&#xff1a;实现代码&#xff1a;结语 效果图&#xff1a; 实现代码&#xff1a; <tamplate><el-table :data"list" ><el-table-column fixed"right" label"操作&q…

服务负载均衡Ribbon

服务负载均衡Ribbon Ribbon 介绍Ribbon 案例Ribbon 负载均衡策略Ribbon 负载均衡算法设置自定义负载均衡算法 Ribbon 介绍 Ribbon 是一个的客服端负载均衡工具&#xff0c;它是基于 Netflix Ribbon 实现的。它不像 Spring Cloud 服务注册中心、配置中心、API 网关那样独立部署…

启动网站调试提示 HTTP 错误 403.14 – Forbidden Web 服务器被配置为不列出此目录的内容。

启动网站调试提示 HTTP 错误 403.14 – Forbidden Web 服务器被配置为不列出此目录的内容。 解决方案第一种.在网站的配置文件里添加第二种.ISS管理界面修改 解决方案 第一种.在网站的配置文件里添加 <system.webServer><directoryBrowse enabled"true" /&…

STM32+PWM+输入捕获测频

外部时钟&#xff0c;主频64M 定时器1 通道1发出PWM波 频率1K 定时器2 通道1输入捕获&#xff0c;上升沿触发 串口 /* USER CODE BEGIN 0 */ uint32_t time_up_num0;//上升沿计数 float time_frequency;//频率 /* USER CODE END 0 */ 初始换打开定时器 /* USER CODE BEGIN 2 …

跑深度学习nvidia驱动忽然实效的详细解决方法

由于经常跑深度学习&#xff0c;所以对于显卡驱动什么的都还是整的比较明白的不含糊&#xff0c;所以都能跑的起来。但是今天跑pytorch框架时&#xff08;用到cuda&#xff09;忽然给我报了个错&#xff1a; RuntimeError: No CUDA GPUs are available这给我整不会了&#xff…

解决uni-app微信小程序底部输入框,键盘弹起时页面整体上移问题

存在问题 做了一个记录页面&#xff08;类似单方聊天页&#xff09;&#xff0c;输入框在底部&#xff1b;当弹出键盘时&#xff0c;页面整体上移&#xff0c;页面头信息会消失不见 需要实现效果&#xff1a; 比如一个记录页面&#xff0c;需要在键盘弹出时&#xff1a; 底…

【SQL】群辉 NAS 安装 Mysql 远程访问连接

群辉安装MySQL具有高效、安全、可靠、灵活等优势&#xff0c;可以为用户提供一个优秀的数据管理和分析环境。同时具有良好的硬件性能和稳定性&#xff0c;可以保障MySQL数据库的高效运行和数据安全. cpolar 是一款内网穿透工具,通过简单的设置,我们即可实现远程访问群辉中mysq…

微信为什么使用 SQLite 保存聊天记录?

概要 SQLite 是一个被大家低估的数据库&#xff0c;但有些人认为它是一个不适合生产环境使用的玩具数据库。事实上&#xff0c;SQLite 是一个非常可靠的数据库&#xff0c;它可以处理 TB 级的数据&#xff0c;但它没有网络层。接下来&#xff0c;本文将与大家共同探讨 SQLite 在…

Element+Vue+OpenLayers的项目实战

WebGIS ElementVueOpenLayers的项目实战 使用npm配置开发环境Vue的安装npm安装vue-cli脚手架构建工具安装桥接工具运行项目 使用npm配置开发环境 开发是项目级别的&#xff0c;则需要使用npm来配置开发环境&#xff1b; 使用npm配置开发环境主要包括Vue、Element和OpenLayers的…

Linux·图解Linux网络包接收过程

因为要对百万、千万、甚至是过亿的用户提供各种网络服务&#xff0c;所以在一线互联网企业里面试和晋升后端开发同学的其中一个重点要求就是要能支撑高并发&#xff0c;要理解性能开销&#xff0c;会进行性能优化。而很多时候&#xff0c;如果你对Linux底层的理解不深的话&…

ContOS7 Oracle11g 安装配置

挂载镜像和配置本地yum源 mount /dev/cdrom /mnt cat <<EOF>/etc/yum.repos.d/local.repo [local] namelocal baseurlfile:///mnt gpgcheck0 enabled1 EOFSelinux配置 #selinux修改后需要重启主机生效&#xff1a; sed -i s/SELINUXenforcing/SELINUXdisabled/g /et…

python dataframe 时间格式处理

1&#xff0c;20230101 这种处理成 2023-01-01 这种 df1[apply_date] df1[apply_date].astype(str) df1[apply_dt] pd.to_datetime(df1[apply_date]).dt.strftime(%Y-%m-%d) 2、时间&#xff0c;截取年月日 如 &#xff1a;2023-01-01 12:01:01 &#xff0c;只取年月日 df[…

java中地址问题

//第一个大mapMap<String, Object> map new HashMap<>();HashMap<String, String> map2 new HashMap<>();map2.put("358","999");//给小map赋值并将其添加到map中map.put("666",map2);//获取小map并且修改对应的键值对…

基于springboot+vue框架的电影订票系统_wqc3k

随着网络科技的不断发展以及人们经济水平的逐步提高&#xff0c;计算机如今已成为人们生活中不可缺少的一部分&#xff0c;为电影订票方便管理&#xff0c;基于java技术设计与实现了一款简洁、轻便的管理系统。本系统解决了电影订票事务中的主要问题&#xff0c;包括个人中心、…

uniapp小程序订单页面UI

前言 之前用模板写了订单页面&#xff0c;由于需求改了导致这个页面做更新麻烦&#xff0c;弄了一下午&#xff0c;索性全部删除了自己写了&#xff0c;上面的tabs用的是b-ui框架写的&#xff0c;其他的都是原生写法。 &#x1f64f;如果这篇文章对你有帮助还请收藏点赞关注&…

Android Studio 和 Android Gradle 插件的已知问题

Android Studio 的已知问题 渲染 Compose 预览时出错 从 Android Studio Chipmunk 开始&#xff0c;如果您在问题面板中看到 java.lang.NoSuchFieldError: view_tree_saved_state_registry_owner 或 java.lang.ClassNotFoundException: androidx.savedstate.R$id&#xff0c;…