Servlet获取Excel中数据的两种方式

2023-11-17

Servlet解析Excel文件的两种方式

简单分享一下Servlet通过解析Excel文件得到其中数据的两种方式

第一种:前端获取

思路:通过layui的第三方插件 layui.excel 解析excel文件,得到数据,再通过Ajax传递给后端,后端只需要接受参数并封装到实体类中即可。以下是具体步骤:

1、准备环境

搭建Web项目,导入相关jar包,下载插件等;具体略

2、编写JSP文件

<%
    String path = request.getContextPath();
%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page contentType="text/html;charset=UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    ......
    <%--引入layui静态资源文件--%>
    <link rel="stylesheet" href="<%=path%>/layui/css/layui.css" type="text/css">
</head>
<body>
    
<div class="layui-upload">
	<button type="button" class="layui-btn" id="uploadExcelOne">上传Excel</button>
</div>
    
<%--引入静态资源文件--%>
<script src="<%=path%>/layui/layui.js" type="text/javascript"></script>
<script src="<%=path%>/layui/jquery.js" type="text/javascript" ></script>

<script>
    
    // 前端处理方式
    layui.config({
        base: '<%=path%>/layui/layui_exts/',
    }).use(['jquery','layer','upload','excel'], function () {
        $ = layui.jquery;
        var excel = layui.excel;
        var upload = layui.upload;
        var layer = layui.layer;

        upload.render({
            elem: '#uploadExcelOne',
            // 不自动上传
            auto: false, 
            accept: 'file', 
            // 打开文件选中框时只显示Excel格式的文件
            acceptMime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel', 
            // 规定上传的格式
            exts: 'xls|excel|xlsx',
            choose: function (obj) {
                var files = obj.pushFile();
                var fileArray = Object.values(files);
                // 用完就清理掉,避免多次选中相同文件时出现问题
                for (var index in files) {
                    if (files.hasOwnProperty(index)) {
                        delete files[index]
                    }
                }
                uploadExcel(fileArray);
            }
        });
		// 上传文件的具体方法
        function uploadExcel(files) {
            try {
                excel.importExcel(files, {
                    // 读取数据的同时梳理数据 可参考官方文档
                    fields: {
                        'id': 'A',
                        'name': 'B',
                        'age': 'C',
                        'height': 'D',
                        'birthday': 'E'
                    }
                }, function (data) {
                    $.each(data, function (index, obj) {
                        $.each(obj.Sheet1, function (index, object){
                            var id = object.id;
                            var name = object.name;
                            var age = object.age;
                            var height = object.height;
                            // Excel文件中时间比较特殊,需做如下处理
                            var birthday = LAY_EXCEL.dateCodeFormat(object.birthday, 'YYYY/MM/DD');

                            if(id === "id") {
                                console.log("读取了表头");
                            } else {
                                $.ajax({
                                    url: "<%=path%>/byb/test?action=updateExcelOne",
                                    dataType: "json",
                                    type: 'get',
                                    contentType: "application/json;charset=utf-8",
                                    data: {
                                        id: id,
                                        name: name,
                                        age: age,
                                        height: height,
                                        birthday: birthday,
                                    },
                                    success: function (result) {
                                        if (result.status === 200) {
                                            layer.msg('上传成功');
                                        } else {
                                            layer.msg('上传失败');
                                        }
                                    },
                                    error: function () {
                                        layer.msg('请联系管理员!!!');
                                    }
                                });
                            }
                        })
                    });
                })
            } catch (e) {
                layer.alert("未知错误,请稍后再试...");
            }
        }
    });

</script>
</body>
</html>

前端处理完成后就可以让后台接收了。

3、Servlet接收

package upload;

@WebServlet("/byb/test")
@MultipartConfig
public class FileUploadTest extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ParseException {
		// 获取请求参数
        String action = request.getParameter("action");
        action = action == null ? "" : action;
        // 定义返回map
        Map<String, Object> resultMap = new HashMap<>();

        switch (action) {

            case "updateExcelOne":
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
                // 获取参数并封装到实体类 这里可以根据Excel的字段创建一个对应的实体类
                Person person = new Person();
                person.setId(Integer.parseInt(request.getParameter("id")));
                person.setName(request.getParameter("name"));
                person.setAge(Integer.parseInt(request.getParameter("age")));
                person.setHeight(Double.parseDouble(request.getParameter("height")));
                person.setBirthday(sdf.parse(request.getParameter("birthday")));
                try {
                    // 没有顺序
                    System.out.println(person);
                    // 得到实体类之后就可以实现具体业务了 略...
                    resultMap.put("status", 200);
                } catch (Exception e) {
                    e.printStackTrace();
                    resultMap.put("status", 201);
                }
                response.getWriter().println(JSONArray.toJSONString(resultMap));
                response.getWriter().flush();
                response.getWriter().close();
                break;
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            processRequest(req, resp);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            processRequest(req, resp);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

4、运行测试

前端效果图

5、总结

缺点:

​ 1.Excel中的数据顺序被打乱,例如Excel中数据的顺序是1-10,传到后台顺序就完全乱了

​ 2.一条数据发送一个Ajax请求,那如果Excel中有上万条数据,是不是就会影响到性能呢?

​ 3.前端解析暂不支持IE11及以下版本,其他浏览器支持

第二种:后端获取

思路:将整个Excel文件提交给后端,后端通过相关工具类解析文件并获取到相关数据;以下是具体步骤:

1、准备环境

在上面的环境中添加即可

2、编写JSP文件

<div class="layui-upload">
  <button type="button" class="layui-btn" id="uploadExcelTwo">上传Excel后端取值</button>
</div>

<script>
// 在原先的JSP文件中添加
layui.use(["layer","upload"], function () {
    $ = layui.jquery;
    var upload = layui.upload;
    upload.render({
        elem: '#uploadExcelTwo',
        url: '<%=path%>/byb/test?action=updateExcelTwo',
        //选择文件后是否自动上传
        auto: true,
        // 指定普通文件
        accept: 'file',
        // 弹出文件显示框时只展示Excel类型的文件
        acceptMime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel',
        // 规定上传的格式
        exts: 'xls|excel|xlsx',
        // 禁止多文件上传
        multiple: false,
        // 是否开启拖拽文件上传 默认为true
        drag: true,
        done: function (result) {
            if (result.status === 200) {
                layer.alert("已成功获取到Excel数据", {icon: 6});
            } else if (result.status === 202) {
                layer.alert("Excel文件内容为空", {icon: 5});
            } else {
                layer.alert("Excel数据错误,请修改并重新导入", {icon: 5});
            }
        },
        error: function () {
            layer.alert("未知错误,请联系管理员", {icon: 5});
        }
    });
});
</script>

3、实体类

根据Excel中的字段编写一个对应的实体类:比如Excel文件如下(Excel第一行是有表头的):

id name age height(double类型) birthday(日期类型)
1 张三1 18 10.10 2020/10/10
2 张三2 19 11.10 2020/10/11

则实体类:

@Date
public class Person {
    private Integer id;
    private String name;
    private Integer age;
    private Double height;
    private Date birthday;
}

4、编写Excel解析工具类

package upload;

public class UploadExcelUtil {

    // 总行数
    private int totalRows = 0;

    // 总列数
    private int totalCells = 0;

    // 错误信息
    private String errorMsg;

    // 构造方法
    public UploadExcelUtil() {
    }

    public int getTotalRows() {
        return totalRows;
    }

    public int getTotalCells() {
        return totalCells;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    /**
     * 根据流以及文件名得到Excel文件里的所有数据 封装到实体类中并返回集合
     */
    public List<Person> getExcelInfo(InputStream inputStream, String fileName) throws FileNotFoundException {
        List<Person> list = null;
        try {
            // 验证文件名是否合格
            if (!validateExcel(fileName)) {
                return null;
            }
            // 根据文件名判断文件是2003版本还是2007版本
            boolean isExcel2003 = true;
            if (isExcel2007(fileName)) {
                isExcel2003 = false;
            }
            list = createExcel(inputStream, isExcel2003);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 根据excel里面的内容读取信息
     * @param is 输入流
     * @param isExcel2003 excel是2003还是2007版本
     */
    public List<Person> createExcel(InputStream is, boolean isExcel2003) {
        List<Person> list = null;
        try {
            Workbook wb;
            if (isExcel2003) {
                // 当excel是2003时,创建excel2003
                wb = new HSSFWorkbook(is);
            } else {
                // 当excel是2007时,创建excel2007
                wb = new XSSFWorkbook(is);
            }
            // 读取Excel里面客户的信息
            list = readExcelValue(wb);
        } catch (IOException | ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 读取Excel里面的信息
     */
    private List<Person> readExcelValue(Workbook wb) throws ParseException {
        List<Person> list = new ArrayList<>();
        // 得到第一个shell
        Sheet sheet = wb.getSheetAt(0);
        // 得到Excel的行数
        this.totalRows = sheet.getPhysicalNumberOfRows();
        // 得到Excel的列数(前提是有行数)
        if (totalRows > 1 && sheet.getRow(0) != null) {
            this.totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
        }

        // 循环Excel行数 r=1表示从第二行开始读 第一行是表头
        for (int r = 1; r < totalRows; r++) {
            Row row = sheet.getRow(r);
            if (row == null) {
                // 如果该行为空则结束本次循环开始读下一行
                continue;
            }
            // 一行数据封装为一个新对象
            Person person = new Person();
            // 循环Excel的列
            for (int c = 0; c < totalCells; c++) {
                Cell cell = row.getCell(c);
                if (null != cell) {

                    switch (c) {
                        case 0:
                            // 第一列是id
                            cell.setCellType(Cell.CELL_TYPE_STRING);
                            String id = String.valueOf(cell.getStringCellValue());
                            person.setId(Integer.parseInt(id));
                            break;

                        case 1:
                            // 第2列是名字
                            cell.setCellType(Cell.CELL_TYPE_STRING);
                            String name = String.valueOf(cell.getStringCellValue());
                            person.setName(name);
                            break;

                        case 2 :
                            // 第3列是年龄
                            cell.setCellType(Cell.CELL_TYPE_STRING);
                            String age = String.valueOf(cell.getStringCellValue());
                            person.setAge(Integer.parseInt(age));
                            break;

                        case 3 :
                            // 第4列是身高 double类型数据
                            cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                            person.setHeight(cell.getNumericCellValue());
                            break;

                        case 4 :
                            // 第5列是生日 date类型数据
                            if (cell.getCellType() == 0) {
                                if (HSSFDateUtil.isCellDateFormatted(cell)){
                                    Date date = cell.getDateCellValue();
                                    person.setBirthday(date);
                                } else {
                                    // 如果格式不正确就设置为空
                                    person.setBirthday(null);
                                }
                            }
                            break;

                        default :
                            break;
                    }
                }
            }
            list.add(person);
        }
        return list;
    }

    /**
     * 验证EXCEL文件
     */
    public boolean validateExcel(String filePath) {
        if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))) {
            errorMsg = "文件名不是excel格式";
            return false;
        }
        return true;
    }
    // 是否是2003的excel,返回true是2003
    public static boolean isExcel2003(String filePath) {
        return filePath.matches("^.+\\.(?i)(xls)$");
    }
    // 是否是2007的excel,返回true是2007
    public static boolean isExcel2007(String filePath) {
        return filePath.matches("^.+\\.(?i)(xlsx)$");
    }
}

5、Servlet接收

在上面的Servlet类中添加如下:

case "updateExcelTwo":
    // 获取上传的文件
    Collection<Part> parts01 = request.getParts();
    String fileName01 = null;
    try {
        for (Part part : parts01) {
            if(part.getHeader("Content-Disposition").contains("filename")) {
                // 上传文件的头部信息
                String fileHeader = part.getHeader("Content-Disposition");
                // 获取到上传文件的文件名
                fileName01 = fileHeader.substring(fileHeader.indexOf("filename=\"") + 10, fileHeader.lastIndexOf("\""));
                // 获取文件的输入流
                InputStream in = part.getInputStream();
                // 处理Excel的工具
                UploadExcelUtil uploadExcel = new UploadExcelUtil();
                // 使用工具类处理后得到数据集合
                List<Person> list = uploadExcel.getExcelInfo(in, fileName01);
                if (list.size() == 0) {
                    // Excel没有读取到数据
                    resultMap.put("status", 202);
                    break;
                } else {
                    for (Person person : list) {
                        // 得到每一个实体类就可以实现具体业务了 例如批量更新数据 具体略..
                        System.out.println(person);
                    }
                    resultMap.put("status", 200);
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
        resultMap.put("status", 201);
    }
    // 转换为json返回前台
    response.getWriter().println(JSONArray.toJSONString(resultMap));
    response.getWriter().flush();
    response.getWriter().close();
	break;

6、运行测试

后端效果图

7、总结

根据效果图可看到数据顺序没有被打乱,而且这种后台处理数据的方式明显会更加高效;个人建议使用第二种方式。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Servlet获取Excel中数据的两种方式 的相关文章

随机推荐

  • 安装CPU版本的pytorch和torchvision(Win10)

    前言 在使用以下方法之前 我是用了网上说的搭建清华镜像进行下载 虽然pytorch下载成功了 但是在下载torchvision的时候就一直成功不了 在网络的大千世界中 我终于悟到先本地下载再安装的方法 第一步 找好对应的版本 第二步 下载本
  • 基于Canal与Flink实现数据实时增量同步(一)

    点击上方蓝色字体 关注我 canal是阿里巴巴旗下的一款开源项目 纯Java开发 基于数据库增量日志解析 提供增量数据订阅 消费 目前主要支持了MySQL 也支持mariaDB 准备 配置MySQL的binlog 常见的binlog命令 是
  • Java多线程分批导入数据

    package com rk iam sys service author wdy version 1 0 date 2022 4 27 14 50 import com alibaba fastjson JSON import com a
  • NLP学习笔记-聊天机器人项目准备(三)

    走进聊天机器人 1 目前企业中的常见的聊天机器人 QA BOT 问答机器人 回答问题 有明确目标 能够返回结果 代表 智能客服 比如 提问和回答 TASK BOT 任务机器人 通过机器人帮助人去完成事情 代表 siri 比如 设置明天早上9
  • 使用词云报错‘TransposedFont‘ object has no attribute ‘getbbox‘

    网上根本找不到这句报错 搞了很久 终于搞完了 1 卸载numpy库 pip uninstall numpy 2 卸载pillow库 pip uninstall pillow 3 卸载词云库 pip uninstall wordcloud 再
  • Linux宝塔面板反向代理设置教程

    此方法最简单快捷 没有复杂步骤 不容易出错 即最简单 零代码 零部署的方法 实现准备 一台服务器 安装宝塔面板 OpenAI官方的API KEY ChatGPT网站系统源码 ChatGPT网站系统源码 大家可以看看另一篇文章介绍 最新版本系
  • 项目中如何修改element-ui的默认样式

    element ui 修改默认样式 一 第一种 修改element ui默认的样式 如果要组件内全局修改 首先在浏览器里F12找到element默认的UI类名 找到要修改的默认类名以后 在文件中修改代码 重写属性 但是如果已经在全局内修改了
  • Nginx反向代理技巧

    跨域 作为一个前端开发者来说不可避免的问题就是跨域 那什么是跨域呢 跨域 指的是浏览器不能执行其他网站的脚本 它是由浏览器的同源策略造成的 是浏览器对javascript施加的安全限制 浏览器的同源策略是指协议 域名 端口都要相同 其中有一
  • 与大多数台式机和移动广告软件说再见

    Some time ago I wrote an article where I described read it here an easy way to get rid of advertisements on your smart T
  • 解决go-cqhttp登录失败:密码错误或账号被冻结

    目录 前言 解决方法一 下载最新go cqhttp 使用方法 解决方法二 总结 推荐阅读 http t csdn cn nQfIY 前言 解决go cqhttp登录失败 密码错误或账号被冻结 解决方法一 下载最新go cqhttp 1 0
  • esp32 CMT130-V1.0 PS 240*240屏幕使用方法实验

    1 安装好Arduino 1 8 13 注意尽量不要大于1 8的版本 2 安装esp32驱动代码并且配置 3 esp32选择波特率 921600 4 选择频率 80MHZ 5 具体连线总结 6 需要在Arduino库管理中心下载TFT eS
  • HTTP协议(超文本传输协议)

    目录 1 HTTP协议介绍 2 HTTP协议格式 3 代码实现 1 HTTP协议介绍 HTTP协议是一个简单的请求响应协议 HTTP协议是一个明文字符串传输协议 便于调试 HTTP协议在传输层上基于TCP协议实现数据传输 本质上HTTP服务
  • BUUCTF[强网杯 2019]随便注 的三种解法

    文章目录 尝试注入 解题思路1 解题思路2 解题思路3 知识点总结 打开后题目是这样的 尝试注入 1 测试 1 or 1 1 初步判定存在SQL注入 1 or 1 1 再测试字段数 到3时报错 说明字段数为2 1 order by 1 接着
  • 测试开发1

    基本概念 一 测试开发基本概念 1 什么是软件测试 2 软件测试和软件开发的区别 3 你为什么选择软件测试 4 什么是需求 二 测试开发基础 1 需求是软件测试的依据 2 用户名和密码登陆测试用例 2 1 功能角度 2 2 非功能需求维度
  • 同学,DBDiff了解一下

    DBDiff是一款自动化的数据库schema和数据对比工具 它可以比较两个数据库 支持本地 远程库 并自动生成差异报告 数据库Schema代表数据库中的数据结构 包括表 视图 索引 序列 存储过程等 在设计数据库Schema时需要考虑各种数
  • Hyperledger fabric: 使用dev模式调试链码(chaincode)

    fabric的链码开发是比较痛苦的 主要是调试起来特别繁琐 在不使用dev模式的情况下 写好chaincode之后不能在本地测试 必须将代码部署到docker 然后再install instantiate 这样peer节点会在新的容器中启动
  • RabbitMQ:hello结构

    1 在Linux环境上面装入rabbitMQ doker compose yml version 3 1 services rabbitmq image daocloud io library rabbitmq management res
  • Youtube扒视频+ffmpeg批量将 png图像转换为avi、MP4以及将avi、MP4转换为单帧图像

    Youtube扒视频 ffmpeg批量将 png图像转换为avi MP4以及将avi MP4转换为单帧图像 最近有科研需求 需要去youtube上扒视频来制作数据集 遇到了如何将avi及mp4转换为png 以及 将png图像转换为视频的操作
  • 螺旋打印矩阵 -- C语言

    需求 给定一个包含 m x n 个元素的矩阵 m 行 n 列 请按照顺时针螺旋顺序 返回矩阵中的所有元素 示例 1 输入 1 2 3 4 5 6 7 8 9 输出 1 2 3 6 9 8 7 4 5 示例 2 输入 1 2 3 4 5 6
  • Servlet获取Excel中数据的两种方式

    Servlet解析Excel文件的两种方式 简单分享一下Servlet通过解析Excel文件得到其中数据的两种方式 第一种 前端获取 思路 通过layui的第三方插件 layui excel 解析excel文件 得到数据 再通过Ajax传递