springboot+thymeleaf+layui的实现示例

 更新时间:2023年12月12日 09:16:04   作者:左边的天堂  
本文主要介绍了springboot+thymeleaf+layui的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、背景

公司运营的同事有个任务,提供一个数据文件给我,然后从数据库中找出对应的加密串再导出来给他。这个活不算是很难,但时不时就会有需求。

同事给我的文件有时是给excel表格,每一行有4列,逗号隔开,合并成一列数据,这类文件需要把所有数据复制到文本编辑器进行处理,把逗号替换成空格,再使用列块编辑模式复制2、3、4列替换原来的excel数据。有时是给.DAT的文件,这类文件需要手动修改后缀为csv,修改后就跟普通的excel表格一样打开,去掉第一列。最后添加一行表头,再对第一列进行筛选去重。

去重后准备导入到数据库的临时表,在此之前需要手动清空临时表的历史数据。导入后再执行一段sql语句,然后把查询结果导出为excel文件给到同事。

这样的工作重复重复再重复,确实挺无趣的,何不鼓捣一个工具给同事自己去处理?

二、步骤

2.1 项目搭建

项目结构如下图:

创建项目,使用springboot 2.5.14poi 4.1.2mybatis,前端使用 thymeleaf + layui-v2.6.8 。

具体看maven配置

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.14</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xxx</groupId>
    <artifactId>test</artifactId>
    <version>1.0</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- Spring框架基本的核心工具 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!-- SpringBoot Web容器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.tomcat.embed</groupId>
                    <artifactId>tomcat-embed-el</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.tomcat.embed</groupId>
                    <artifactId>tomcat-embed-websocket</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <!-- thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
            <exclusions>
                <exclusion>
                    <groupId>com.zaxxer</groupId>
                    <artifactId>HikariCP</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- 阿里数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.16</version>
        </dependency>

        <!-- Mysql驱动包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--常用工具类 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

        <!-- io常用工具类 -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

        <!-- excel工具 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.commons</groupId>
                    <artifactId>commons-math3</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.zaxxer</groupId>
                    <artifactId>SparseBitSet</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- servlet包 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.7.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>com.xxx.AdminApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

为了节省jar包体积,尽可能把不需要的依赖给排除。

2.2 后端处理逻辑

Controller内容

import com.xxx.domain.Result;
import com.xxx.domain.CellItem;
import com.xxx.domain.HelmetConfig;
import com.xxx.service.HelmetService;
import com.xxx.utils.file.DatUtil;
import com.xxx.utils.poi.ExcelUtil;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;

/**
 * 通用请求处理
 *
 * @author admin
 */
@Controller
public class CommonController {
    public static final String[] EXCEL_EXTENSION = {"xls", "xlsx", "XLS", "XLSX"};
    public static final String DAT_EXTENSION = "DAT";

    @Resource
    private HelmetService helmetService;

    @GetMapping(value = {"/", "/index"})
    public String index(Model model) {
        return "index";
    }

    /**
     * 通用下载请求
     */
    @GetMapping("/download")
    public void fileDownload(HttpServletResponse response) {
        List<HelmetConfig> list = helmetService.queryAll();
        ExcelUtil<HelmetConfig> util = new ExcelUtil<>(HelmetConfig.class);
        util.exportExcel(response, list, "Sheet1");
    }

    /**
     * 通用上传请求(单个)
     */
    @PostMapping("/upload")
    @ResponseBody
    public Result uploadFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return Result.error("文件不能为空");
        }
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        List<CellItem> list;
        if (Arrays.asList(EXCEL_EXTENSION).contains(extension)) {
            list = ExcelUtil.getData(file);
        } else if (DAT_EXTENSION.equalsIgnoreCase(extension)) {
            list = DatUtil.readDat(file);
        } else {
            return Result.error("文件格式不正确");
        }
        if (list.isEmpty()) {
            return Result.error("操作失败,请重试");
        }
        helmetService.batchAdd(list);
        return Result.success("操作成功,请点击【下载文件】");
    }
}

数据库根据最后的查询sql创建一个视图(View),通过mybatis对这个试图进行查询,然后把结构进行导出即可。

ExcelUtil.getData()内容

public static List<CellItem> getData(MultipartFile file) {
    InputStream inputStream = null;
    List<CellItem> rowList = new ArrayList<>();
    try {
        inputStream = file.getInputStream();
        XSSFWorkbook wb = new XSSFWorkbook(inputStream);

        int ignoreRows = 0;
        int sheetNum = wb.getNumberOfSheets();
        //for循环:取前N个表,下标从0开始
        for (int i = 0; i < sheetNum; i++) {
            XSSFSheet sheetI = wb.getSheetAt(i);
            //列数
            int cellSize = sheetI.getRow(0).getLastCellNum();
            //第N+1行开始,可以通过传参,从第N+1行开始取
            for (int rowIndex = ignoreRows; rowIndex <= sheetI.getLastRowNum(); rowIndex++) {
                XSSFRow row = sheetI.getRow(rowIndex);
                if (row == null) {
                    continue;
                }
                if (cellSize == 1) {
                    XSSFCell cell = row.getCell(0);
                    String cellValue = cell.getStringCellValue();
                    if (cellValue.contains(",")) {
                        CellItem item = new CellItem();
                        String[] cells = cellValue.split(",");
                        String deviceId = cells[1];
                        Boolean exists = checkExists(rowList, deviceId);
                        if (exists) {
                            continue;
                        }
                        item.setDeviceId(deviceId.trim());
                        item.setProductId(cells[2]);
                        item.setMac(cells[3]);
                        rowList.add(item);
                    }
                } else if (cellSize == 4){
                    //在每行中的每一列,从下标1开始,忽略第一列,一直取到所有
                    CellItem item = new CellItem();
                    String deviceId = row.getCell(1).getStringCellValue();
                    Boolean exists = checkExists(rowList, deviceId);
                    if (exists) {
                        continue;
                    }
                    item.setDeviceId(deviceId.trim());
                    item.setProductId(row.getCell(2).getStringCellValue());
                    item.setMac(row.getCell(3).getStringCellValue());
                    rowList.add(item);
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (Exception e) {
                log.error("文件流关闭失败:{}", e.getMessage());
            }
        }
    }
    return rowList;
}

private static Boolean checkExists(List<CellItem> rowList, String key) {
    for (int i = 0; i < rowList.size(); i++) {
        CellItem item = rowList.get(i);
        if (item.getDeviceId().equals(key.trim())) {
            return Boolean.TRUE;
        }
    }
    return Boolean.FALSE;
}

DatUtil.readDat()

public static List<CellItem> readDat(MultipartFile file) {
    List<CellItem> list = new ArrayList<>();
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
        String line;
        while ((line = reader.readLine()) != null) {
            String[] split = line.split(",");
            String deviceId = split[1];
            Boolean exists = checkExists(list, deviceId);
            if (exists) {
                continue;
            }
            CellItem item = new CellItem();
            item.setDeviceId(deviceId.trim());
            item.setMac(split[2]);
            item.setProductId(split[3]);
            list.add(item);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return list;
}

private static Boolean checkExists(List<CellItem> rowList, String key) {
    for (int i = 0; i < rowList.size(); i++) {
        CellItem item = rowList.get(i);
        if (item.getDeviceId().equals(key.trim())) {
            return Boolean.TRUE;
        }
    }
    return Boolean.FALSE;
}

导出的代码这里省略了。

2.3 配置

application.yml

# 开发环境配置
server:
  # 服务器的HTTP端口
  port: 8080
  servlet:
    # 应用的访问路径
    context-path: /

# Spring配置
spring:
  profiles:
    active: druid
  #thymeleaf 页面的缓存开关
  thymeleaf:
    enabled: true
    cache: true
    mode: HTML5
    encoding: utf-8
    suffix: .html
  # 文件上传
  servlet:
    multipart:
      # 单个文件大小
      max-file-size: 10MB
      # 设置总上传的文件大小
      max-request-size: 50MB

# MyBatis配置
mybatis:
  # 搜索指定包别名
  typeAliasesPackage: com.xxx.domain
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath:mapper/*.xml
  # 加载全局的配置文件
  configLocation: classpath:mybatis/mybatis-config.xml

# 日志配置
logging:
  level:
    com.xxx: info
    org.springframework: warn

数据库配置application-druid.yml

# 数据源配置
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://172.16.1.2:3306/test?useUnicode=true&useSSL=false&allowLoadLocalInfile=false&autoReconnect=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8
    username: root
    password: root
    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

2.3 前端处理逻辑

layui的相关文件放到resources/static目录,再新建一个index.html文件放入resources/templates目录,这两个目录是thymeleaf默认的,如果要修改可以在application.yml进行配置。静态文件如下:

在这里插入图片描述

为了压缩jar包的体积,把所有不必要的文件都精简掉了。

以下是index.html内容

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>测试</title>
  <script th:src="@{/layui.js}"></script>
  <link rel="stylesheet" th:href="@{/css/layui.css}" rel="external nofollow"  media="all">
</head>
<body>
  <div class="layui-card">
    <div class="layui-card-header">操作面板</div>
    <div class="layui-card-body">
      <div class="layui-tab" lay-filter="window">
        <ul class="layui-tab-title">
          <li class="layui-this" lay-id="uploadTab">文件上传</li>
          <li lay-id="downloadTab">文件下載</li>
        </ul>
        <div class="layui-tab-content">
          <div class="layui-tab-item layui-show">
            <form id="upload_form" class="layui-form" enctype="multipart/form-data">
              <div class="layui-form-item">
                <label class="layui-form-label">文件</label>
                <div class="layui-input-block">
                  <button type="button" class="layui-btn" id="upload">
                    <i class="layui-icon">&#xe61f;</i>选择文件
                  </button>
                </div>
              </div>
              <div class="layui-form-item">
                <div class="layui-input-block">
                  <button id="btnSubmit" class="layui-btn" onclick="return false;">立即提交</button>
                </div>
              </div>
            </form>
          </div>
          <div class="layui-tab-item">
            <div class="layui-form-item">
              <label class="layui-form-label">文件</label>
              <div class="layui-input-block">
                <button type="button" class="layui-btn" id="downloadBtn">
                  <i class="layui-icon">&#xe601;</i>下载文件
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>
</html>
<script>
    layui.use(['upload', 'layer', 'element'], function () {
        let $ = layui.jquery
            , layer = layui.layer
            , element = layui.element
            , upload = layui.upload;

        //执行实例
        upload.render({
            elem: '#upload' //绑定元素
            , url: '/upload' //上传接口
            , accept: 'file' //允许上传的文件类型,不写默认是图片
            , acceptMime: ".xlsx,.xls,.DAT,.dat" //不写默认验证图片格式,一定要省略【exts】参数
            , auto: false //选择文件后不自动上传
            , bindAction: '#btnSubmit' //指向一个按钮触发上传
            , before: function (obj) {
                layer.load(); //上传loading
            }
            ,done: function (res) {
                console.log(res)
                layer.closeAll('loading'); //关闭loading
                layer.alert(res.msg);
                if (res.code === 200) {
                    element.tabChange('window', 'downloadTab');
                }
            }
            , error: function (res) {
                console.error(res)
                layer.msg(res.msg);
                layer.closeAll('loading'); //关闭loading
            }
        });
        

        $("#downloadBtn").on('click', function () {
            location.href = "/download";
        })
    });
</script>

编辑好测试没问题直接打包放到服务器上执行就可以啦。

三、实现效果

3.1 文件导入

在这里插入图片描述

导入成功后会自动切换到【文件下载】的tab页

3.2 文件导出

在这里插入图片描述

到此这篇关于springboot+thymeleaf+layui的实现示例的文章就介绍到这了,更多相关springboot thymeleaf layui内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Arrays.asList方法总结

    Arrays.asList方法总结

    本文主要对Arrays.asList方法进行总结。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • 使用SSM+Layui+Bootstrap实现汽车维保系统的示例代码

    使用SSM+Layui+Bootstrap实现汽车维保系统的示例代码

    本文主要实现对汽车维修厂的信息化管理功能,。实现的主要功能包含用户管理、配置管理、汽车管理、故障管理、供应商管理、配件管理、维修订单管理、统计信息、公告管理、个人信息管理,感兴趣的可以了解一下
    2021-12-12
  • Java流程控制顺序结构原理解析

    Java流程控制顺序结构原理解析

    这篇文章主要介绍了Java流程控制顺序结构原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • springboot发送邮件功能的实现代码

    springboot发送邮件功能的实现代码

    发邮件是一个很常见的功能,在java中实现需要依靠JavaMailSender这个接口,今天通过本文给大家分享springboot发送邮件功能的实现代码,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • Springboot整合MongoDB进行CRUD操作的两种方式(实例代码详解)

    Springboot整合MongoDB进行CRUD操作的两种方式(实例代码详解)

    这篇文章主要介绍了Springboot整合MongoDB进行CRUD操作的两种方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • 详解JAVA生成将图片存入数据库的sql语句实现方法

    详解JAVA生成将图片存入数据库的sql语句实现方法

    这篇文章主要介绍了详解JAVA生成将图片存入数据库的sql语句实现方法的相关资料,这里就是实现java生成图片并存入数据库的实例,需要的朋友可以参考下
    2017-08-08
  • 在Java的Struts中判断是否调用AJAX及用拦截器对其优化

    在Java的Struts中判断是否调用AJAX及用拦截器对其优化

    这篇文章主要介绍了在Java的Struts中判断是否调用AJAX及用拦截器对其优化的方法,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
    2016-01-01
  • SpringBoot中@Scheduled实现服务启动时执行一次

    SpringBoot中@Scheduled实现服务启动时执行一次

    本文主要介绍了SpringBoot中@Scheduled实现服务启动时执行一次,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-08-08
  • Java 实战项目锤炼之校园宿舍管理系统的实现流程

    Java 实战项目锤炼之校园宿舍管理系统的实现流程

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+jsp+javaweb+mysql+ajax实现一个校园宿舍管理系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • 详解Android中的Toast源码

    详解Android中的Toast源码

    这篇文章主要介绍了详解Android中的Toast源码,Toast使用Java语言实现,需要的朋友可以参考下
    2015-07-07

最新评论