spring boot +vue 读取excel数据代码生成器

news2024/12/25 9:07:58

项目介绍

最近在开发工程中,需要根据excel中的数据生成标签类,手写太费劲啦,还得一边写一边对,受不了啦 决定写一个解析工具,自动生成代码

项目架构

项目采用springboot +vue的开发方式,但vue并不是分离项目,而是集成在项目内部,加入定时任务每天零点删除指定文件夹的生成文件,避免产生垃圾文件,提供工具生成和下载功能

项目开发 

引入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>


        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.squareup</groupId>
            <artifactId>javapoet</artifactId>
            <version>1.11.1</version>
        </dependency>


    </dependencies>

配置文件

server.port=10086
spring.servlet.multipart.max-file-size=20MB
spring.servlet.multipart.max-request-size=25MB

日志配置

<?xml version="1.0" encoding="utf-8" ?>
<!-- 从高到地低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
<!-- 日志输出规则  根据当前ROOT 级别,日志输出时,级别高于root默认的级别时  会输出 -->
<!-- 以下  每个配置的 filter 是过滤掉输出文件里面,会出现高级别文件,依然出现低级别的日志信息,通过filter 过滤只记录本级别的日志-->

<!-- 属性描述 scan:性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,
默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- 定义日志文件 输入位置 -->
    <property name="logPath" value="../excel-service-log" />
    <!-- 日志最大的历史 30天 -->
    <property name="maxHistory" value="30"/>

    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <!-- layout代表输出格式 -->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n</pattern>
        </layout>
    </appender>


    <!-- 日志输出文件 -->
    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n</pattern>
        </encoder>
        <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender-->
        <!-- 滚动策略,它根据时间来制定滚动策略.既负责滚动也负责触发滚动 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 输出路径 -->
            <fileNamePattern>${logPath}/info/%d.log</fileNamePattern>
            <!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6,
            则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除-->
            <maxHistory>${maxHistory}</maxHistory>

        </rollingPolicy>
    </appender>

    <!-- 特殊记录Error日志 -->
    <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 只记录ERROR级别日志,添加范围过滤,可以将该类型的日志特殊记录到某个位置 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logPath}/error/%d.log</fileNamePattern>
            <maxHistory>60</maxHistory>
        </rollingPolicy>
    </appender>

    <!--定义日志输出级别-->
    <logger name="com.test.excelservice.controller" level="INFO"/>
    <logger name="com.test.excelservice.scheduled" level="INFO"/>

    <root level="info">
        <!-- 引入控制台输出规则 -->
        <appender-ref ref="consoleLog" />
        <appender-ref ref="fileInfoLog" />
        <appender-ref ref="fileErrorLog" />
    </root>
</configuration>

引入vue、axios、element-ui以及字体文件

具体项目会放在资源中,想要的私聊或者下载 

index.html 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>微服务生成Tag工具</title>
    <!--引入网站图标-->
    <link rel="shortcut icon" href="/image/favicon.ico">
    <!-- 引入Vue -->
    <script type="text/javascript" th:src="@{/scripts/vue.min.js}"></script>
    <!-- 引入axios -->
    <script type="text/javascript" th:src="@{/scripts/axios-0.18.0.js}"></script>
    <!-- 引入组件库 -->
    <script type="text/javascript" th:src="@{/scripts/index.js}"></script>
    <!-- 引入样式 -->
    <link type="text/css" href="/css/index.css" rel="stylesheet">

</head>
<body>
<div id="app">
    <el-container>
        <el-header id="header">
            <div id="title">微服务生成Tag工具</div>
        </el-header>
        <el-main>
            <el-tabs v-model="activeName">
                <el-tab-pane label="Tag生成" name="first">
                    <el-card class="box-card" shadow="always">
                        <el-row>
                            <el-col :span="12">
                                <div><h2>自动生成表单信息</h2></div>
                                <el-form :model="formSelectData" :rules="rules" ref="ruleForm" class="demo-ruleForm">
                                    <el-form-item label="请输入生成文件文件夹" prop="dirPath">
                                        <el-input v-model="formSelectData.dirPath"
                                                  disabled="true"></el-input>
                                    </el-form-item>

                                    <el-form-item label="请输入要生成的sheet页名" prop="sheetName">
                                        <el-input v-model="formSelectData.sheetName"
                                                  placeholder="对应excel中sheet页名"></el-input>
                                    </el-form-item>

                                    <el-form-item label="生成的包名" prop="packageName">
                                        <el-input v-model="formSelectData.packageName"
                                                  placeholder="对应java代码中的包名"></el-input>
                                    </el-form-item>

                                    <el-form-item label="生成的客户端报文接口名" prop="clientInterFaceName">
                                        <el-input v-model="formSelectData.clientInterFaceName"
                                                  placeholder="对应接口名称"></el-input>
                                    </el-form-item>

                                    <el-form-item label="生成的服务端报文接口名" prop="ServerInterFaceName">
                                        <el-input v-model="formSelectData.ServerInterFaceName"
                                                  placeholder="对应接口名称"></el-input>
                                    </el-form-item>

                                </el-form>
                            </el-col>
                            <el-col :span="10" :offset="2">
                                <div id="empty"></div>
                                <el-upload
                                        class="upload-demo"
                                        drag
                                        action="String"
                                        :before-upload="beforeUploadHandle"
                                        :http-request="handleUploadForm"
                                        auto-upload="false"
                                        :show-file-list="false"
                                        multiple="false"
                                >
                                    <i class="el-icon-upload"></i>
                                    <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
                                </el-upload>
                            </el-col>
                        </el-row>
                    </el-card>
                </el-tab-pane>
                <el-tab-pane label="Tag下载" name="second">
                    <el-card class="box-card" shadow="always">
                        <el-table :data="tableData" border style="width: 100%">
                            <el-table-column
                                    label="文件夹路径"
                                    prop="dirPath"
                                    width="180">
                            </el-table-column>
                            <el-table-column
                                    label="文件名"
                                    width="180"
                                    prop="fileName"
                            >
                            </el-table-column>
                            <el-table-column label="操作">
                                <template slot-scope="scope">
                                    <el-button size="mini" @click="downLoadFile(scope.row)">
                                        下载
                                    </el-button>
                                </template>
                            </el-table-column>
                        </el-table>
                    </el-card>
                </el-tab-pane>
            </el-tabs>
        </el-main>
    </el-container>
</div>
<script>
    let app = new Vue(
        {
            el: "#app", // 挂载根节点
            mounted() {

            },
            data: {
                activeName: 'first',
                formSelectData: {
                    dirPath: "/opt/exceldata/data",
                    sheetName: "",
                    packageName: '',
                    clientInterFaceName: '',
                    ServerInterFaceName: '',
                },
                rules: {
                    dirPath: [
                        {required: true, message: '请输入生成文件夹', trigger: 'change'}
                    ],
                    sheetName: [
                        {required: true, message: '请输入excelSheet页名称', trigger: 'change'}
                    ],
                    packageName: [
                        {required: true, message: '请输入接口对应包名', trigger: 'change'}
                    ],
                    clientInterFaceName: [
                        {required: true, message: '请输入要生成的客户端接口名称', trigger: 'change'}
                    ],
                    ServerInterFaceName: [
                        {required: true, message: '请输入要生成的服务端接口名称', trigger: 'change'}
                    ],
                },
                tableData:[]
            },
            methods: {
                // 开启全局loading
                beginGlobalLoading() {
                    this.globalLoad = this.$loading({    //开启loading动画
                        lock: true,
                        text: '正在玩命加载,请稍等···',
                        spinner: 'el-icon-loading',// 设置图标
                        background: 'rgba(0,0,0,.7)'
                    })
                },
                // 关闭全局loading
                endGlobalLoading() {
                    if (this.globalLoad) {
                        this.globalLoad.close()
                    }
                },

                // 上传文件之前校验
                async beforeUploadHandle(file) {
                    try {
                        await this.$refs['ruleForm'].validate()
                        const extensionList = ["xlsx", "xls", "XLSX", "XLS"]
                        const fileExtension = file.name.split(".")[1]
                        if (file.size / 1024 / 1024 > 20) {
                            this.$message.warning('上传文件大小不能超过20MB!');
                            return Promise.reject(false);
                        }
                        if (!extensionList.includes(fileExtension)) {
                            this.$message.warning("文件类型必须是excel,请重新上传!!!");
                            return Promise.reject(false);
                        }
                    } catch (e) {
                        this.$message.warning("请填写左侧表单项之后在次上传文件!!!");
                        return Promise.reject(false);
                    }
                },

                // 覆盖默认上传行为
                handleUploadForm(param) {
                    let formData = new FormData();
                    formData.append('file', param.file);
                    formData.append('sheetName', this.formSelectData.sheetName);
                    formData.append('dirPath', this.formSelectData.dirPath);
                    formData.append('packageName', this.formSelectData.packageName);
                    formData.append('clientInterFaceName', this.formSelectData.clientInterFaceName);
                    formData.append('ServerInterFaceName', this.formSelectData.ServerInterFaceName);

                    axios.post("/parse/file", formData, {'Content-type': 'multipart/form-data'}).then((res) => {
                        if (res.data.code == 200) {
                           const data = res.data.data;
                           this.tableData = data;
                            this.endGlobalLoading();
                            this.$message.success('自动生成成功');
                        } else {
                            this.endGlobalLoading();
                            this.$message.error('自动生成失败');
                        }
                    })
                },

                // 下载方法
                downLoadFile(param){
                    console.log(param,"param");
                    let strings = param.packageName.split('.');
                    let packagePath = strings.join("\\");

                    const filePath = `${param.dirPath}\\${packagePath}\\${param.fileName}.java`
                    axios.get("/downLoadFile",{
                        params: {
                            path: filePath,
                            name: `${param.fileName}.java`
                        },
                        responseType: 'blob'
                    }).then(res => {
                        const blob = new Blob([res.data]);
                        const fileName = res.headers["content-disposition"].split(";")[1].split("filename=")[1];
                        let downloadElement = document.createElement("a");
                        let href = window.URL.createObjectURL(blob);
                        downloadElement.href = href;
                        downloadElement.download = decodeURIComponent(fileName);
                        document.body.appendChild(downloadElement);
                        downloadElement.click();
                        document.body.removeChild(downloadElement);
                        window.URL.revokeObjectURL(href);
                    })
                }
            }
        }
    );

</script>

<style>
    html,
    body {
        width: 100%;
        height: 100%;
    }

    #app {
        width: 100%;
        height: 100%;
    }

    #header {
        background-color: #409EFF;
    }

    #title {
        margin: 0 auto;
        font-family: ui-sans-serif;
        font-size: larger;
        position: relative;
        top: 50%;
        /*transform: translateX(-50%);*/
        transform: translateY(-50%);
        text-align: center;
        color: white;
        font-weight: bold;
    }

    .el-upload-dragger {
        width: 600px;
        height: 460px;
    }

    #empty {
        height: 110px;
    }

    .el-upload-dragger .el-icon-upload {
        margin-top: 200px;
    }
</style>
</body>
</html>

路由页面配置

package com.test.excelservice.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 跳转页面配置
 * @author shilei
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
    }

}

 解析逻辑

package com.test.excelservice.controller;

import com.alibaba.excel.EasyExcel;
import com.test.excelservice.generateor.GeneratorUtils;
import com.test.excelservice.model.GeneInfo;
import com.test.excelservice.model.ReqParam;
import com.test.excelservice.model.ResParam;
import com.test.excelservice.result.Result;
import com.test.excelservice.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 解析excel信息生成tag
 * @author shilei
 */
@RestController
public class ExcelController {

    private Logger logger = LoggerFactory.getLogger(ExcelController.class);

    private  Pattern pattern = Pattern.compile("[\u4e00-\u9fa5]");

    @RequestMapping("/parse/file")
    public Result<List<GeneInfo>> pareExcel(MultipartFile file, GeneInfo geneInfo) {

        try{
            logger.info("读取"+file.getOriginalFilename()+"文件");
            logger.info("读取"+geneInfo.getSheetName()+"sheet页的excel数据");
            // 读取excel数据
            List<HashMap<Integer ,String>> data = EasyExcel
                    .read(file.getInputStream())
                    .sheet(geneInfo.getSheetName())
                    .headRowNumber(0)
                    .doReadSync();

            // 请求参数list
            List<ReqParam> reqParams = new ArrayList<>();
            // 响应参数list
            List<ResParam> resParams = new ArrayList<>();
            // 读取请求参数标识
            boolean readerReqFlag =false;
            // 读取响应参数标识
            boolean readerResFlag =false;
            for (int i = 0; i < data.size(); i++) {

                HashMap<Integer, String> stringStringHashMap = data.get(i);

                if(stringStringHashMap.containsValue("请求报文")){
                    // 跳过一条
                    i+=1;
                    readerReqFlag = true;
                    continue;
                }
                if(stringStringHashMap.containsValue("响应报文")){
                    // 跳过一条
                    i+=1;
                    readerReqFlag = false;
                    readerResFlag = true;
                    continue;
                }
                // 读取请求报文
                if(readerReqFlag){
                    ReqParam reqParam = new ReqParam();
                    reqParam.setFiledName(stringStringHashMap.get(0));
                    reqParam.setFiledDesc(stringStringHashMap.get(1));
                    reqParams.add(reqParam);
                }
                // 读取响应报文
                if(readerResFlag){
                    String field = stringStringHashMap.get(0).toLowerCase();
                    Matcher matcher = pattern.matcher(field);
                    // 跳过List Row和中文描述的响应报文行
                    if(field.contains("list")||field.contains("row")||matcher.find()){
                        // 跳过一条
                        i+=1;
                        continue;
                    }
                    ResParam resParam = new ResParam();
                    resParam.setFiledName(stringStringHashMap.get(0));
                    resParam.setFiledDesc(stringStringHashMap.get(1));
                    resParams.add(resParam);
                }

            }
            logger.info("读取"+geneInfo.getSheetName()+"成功");
            if(StringUtils.isNotNull(reqParams) && StringUtils.isNotNull(resParams)){
                logger.info("正在生成接口中....");
                GeneratorUtils.generatorInterFace(geneInfo,reqParams,resParams);
                logger.info("生成接口成功!!!");
            }
            ArrayList<GeneInfo> geneInfos = new ArrayList<>();
            geneInfo.setFileName(geneInfo.getClientInterFaceName());
            // 添加客户端下载对象
            geneInfos.add(geneInfo);
            // 创建服务端下载对象
            GeneInfo serverGeneInfo = new GeneInfo();
            BeanUtils.copyProperties(geneInfo,serverGeneInfo);
            serverGeneInfo.setFileName(serverGeneInfo.getServerInterFaceName());
            geneInfos.add(serverGeneInfo);
            return new Result<List<GeneInfo>>(200,geneInfos);
        }catch (Exception e){
            logger.error("自动生成接口失败",e);
            return new Result<List<GeneInfo>>(500, Collections.emptyList());
        }
    }


    @GetMapping("/downLoadFile")
    public void downLoadFile(@RequestParam("path") String path, @RequestParam("name") String name, HttpServletResponse response) throws Exception {

        response.setContentType("text/html;charset=UTF-8");
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        long fileLength = (new File(path)).length();
        response.setContentType("application/octet-stream;charset=GBK");
        response.setHeader("Content-disposition", "attachment; filename=" + new String(name.getBytes("GB2312"), "ISO-8859-1"));
        response.setHeader("Content-Length", String.valueOf(fileLength));
        bis = new BufferedInputStream(new FileInputStream(path));
        bos = new BufferedOutputStream(response.getOutputStream());
        byte[] buff = new byte[2048];

        int bytesRead;
        while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
            bos.write(buff, 0, bytesRead);
        }

        bis.close();
        bos.close();

    }


}

解析工具类

package com.test.excelservice.generateor;

import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;
import com.test.excelservice.model.GeneInfo;
import com.test.excelservice.model.ReqParam;
import com.test.excelservice.model.ResParam;
import com.test.excelservice.util.StringUtils;

import javax.lang.model.element.Modifier;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * 生成接口工具类
 * @Author shilei
 */
public class GeneratorUtils {


     // 请求前缀
    public static final String RQ_PREFIX = "RQ_";

    // 响应前缀
    public static final String RS_PREFIX = "RS_";

    // 下划线
    public static final String UNDERLINE = "_";

    /**
     * 生成接口工具类
     */
    public static  void  generatorInterFace(GeneInfo geneInfo, List<ReqParam> reqParams, List<ResParam> resParams) throws IOException {

        HashMap<String, List<FieldSpec>> filedHashMap = generatorFiled(reqParams, resParams,geneInfo);


        Iterator<Map.Entry<String, List<FieldSpec>>> iterator = filedHashMap.entrySet().iterator();

        while (iterator.hasNext()){
            Map.Entry<String, List<FieldSpec>> next = iterator.next();

            TypeSpec builder = TypeSpec.interfaceBuilder(next.getKey()).addFields(next.getValue()).build();
            JavaFile file = JavaFile.builder(geneInfo.getPackageName(), builder)
                    .indent("    ")
                    .build();
            File dirFile = new File(geneInfo.getDirPath());
            if (!dirFile.getParentFile().exists()) {
                dirFile.getParentFile().mkdirs();
            }
            file.writeTo(dirFile);

        }
    }


    /**
     * 生成属性列表
     */

    public static HashMap<String,List<FieldSpec>> generatorFiled(List<ReqParam> reqParams, List<ResParam> resParams,GeneInfo geneInfo){
        // 最终结果
        HashMap<String,List<FieldSpec>> result = new HashMap<>();
        // 请求字段列表
        List<FieldSpec> reqFiledList = new ArrayList<>();
        // 响应字段列表
        List<FieldSpec> resFiledList = new ArrayList<>();
        // 处理之后的请求参数
        List<ReqParam> reqParamResult =new ArrayList<>();
        // 处理之后的响应参数
        List<ResParam> resParamResult =new ArrayList<>();

        for (ReqParam reqParam : reqParams) {
            // 响应报文加请求
            ResParam resParam = new ResParam();
            resParam.setFiledName(RQ_PREFIX+reqParam.getFiledName());
            resParam.setFiledDesc(reqParam.getFiledDesc());
            resParamResult.add(resParam);
            // 请求报文加前缀
            reqParam.setFiledName(RQ_PREFIX+reqParam.getFiledName());
            reqParamResult.add(reqParam);


        }
        for (ResParam resParam : resParams) {
            // 请求报文加响应
            ReqParam reqParam = new ReqParam();
            reqParam.setFiledName(RS_PREFIX+resParam.getFiledName());
            reqParam.setFiledDesc(resParam.getFiledDesc());
            reqParamResult.add(reqParam);
            // 响应报文加前缀
            resParam.setFiledName(RS_PREFIX+resParam.getFiledName());
            resParamResult.add(resParam);
        }

        if(StringUtils.isNotNull(reqParamResult)){
            for (ReqParam reqItem : reqParamResult) {
                FieldSpec filed = FieldSpec.builder(String.class, reqItem.getFiledName().toUpperCase())
                        .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
                        .initializer("$S",lowerFirst(removePrefix(reqItem.getFiledName())))
                        .addJavadoc(reqItem.getFiledDesc())
                        .build();
                reqFiledList.add(filed);
            }
        }

        if(StringUtils.isNotNull(resParamResult)){
            for (ResParam resItem : resParamResult) {
                FieldSpec filed = FieldSpec.builder(String.class, resItem.getFiledName().toUpperCase())
                        .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
                        .initializer("$S",upperFirst(removePrefix(resItem.getFiledName())))
                        .addJavadoc(resItem.getFiledDesc())
                        .build();
                resFiledList.add(filed);
            }
        }

        result.put(geneInfo.getClientInterFaceName(),reqFiledList);
        result.put(geneInfo.getServerInterFaceName(),resFiledList);

        return result;
    }


    /**
     * 去掉字符串前缀
     * @return String
     */
    public  static String removePrefix(String str) {
        if (str == null || "".equals(str)) {
            return "";
        } else {
            if (str.contains(UNDERLINE)) {
                String[] split = str.split(UNDERLINE);
                return split[1];
            }
            return str;

        }
    }

    /**
     * 首字母转小写
     * @param str
     * @return
     */
    public static String lowerFirst(String str) {
        str = Character.toLowerCase(str.charAt(0)) + str.substring(1);
        return str;
    }

    /**
     * 首字母转大写
     * @param str
     * @return
     */
    public static String upperFirst(String str) {
        str = Character.toUpperCase(str.charAt(0)) + str.substring(1);
        return str;
    }

}



定时任务删除指定文件

package com.test.excelservice.scheduled;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;

import java.io.File;

/**
 * 定时任务删除指定文件夹下的所有文件
 * @author shilei
 */
public class RemoveFileScheduled {

    /**
     * PATH 服务器下指定文件目录
     */
    public static final  String  PATH = "/opt/exceldata/data";

    private final Logger logger = LoggerFactory.getLogger(RemoveFileScheduled.class);

    @Scheduled(cron = "0 0 00 * * ?")
    public void executeRemove() {
        removeFile(new File(PATH));
    }

    public  void removeFile(File file){
        if (file == null || !file.exists()){
            logger.error("文件删除失败,请检查文件路径是否正确");
            return;
        }
        //取得这个目录下的所有子文件对象
        File[] files = file.listFiles();
        //遍历该目录下的文件对象
        for (File f: files){
            String name = file.getName();
            logger.info("文件名为"+ name);
            //判断子目录是否存在子目录,如果是文件则删除
            if (f.isDirectory()){
                removeFile(f);
            }else {
                f.delete();
            }
        }
        //删除空文件夹  for循环已经把上一层节点的目录清空。
        file.delete();
    }
}

运行效果 

 

 由于没有持久化到数据库,所以,下载不能够刷新页面,想加可以加一下

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

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

相关文章

day38-Mybatis映射

0目录 Mybatis映射 1.2.3 1. Mybatis映射 1.1 映射文件XXMapper.xml语法 1.2 namespace&#xff1a;命名空间 namespace 的命名必须跟某个接口同名 1.3 id&#xff1a;命名空间中的唯一标识符 接口中的方法与映射文件中的SQL语句id一一对应 1.4 parameterType&#xf…

尚硅谷大数据Flink1.17实战教程-笔记03【Flink运行时架构】

尚硅谷大数据技术-教程-学习路线-笔记汇总表【课程资料下载】视频地址&#xff1a;尚硅谷大数据Flink1.17实战教程从入门到精通_哔哩哔哩_bilibili 尚硅谷大数据Flink1.17实战教程-笔记01【Flink概述、Flink快速上手】尚硅谷大数据Flink1.17实战教程-笔记02【Flink部署】尚硅谷…

好用的Net反编译工具,界面和VS差不多,供大家学习研究参考

1、无需设置 由于它是一个便携式工具&#xff0c;它不需要您将其安装在目标计算机上&#xff0c;因为只需拆包其存档并启动可执行文件即可完全访问其功能。 您还可以从可移动存储介质(如USB闪存驱动器或外部HDD)运行它。此外&#xff0c;它不会修改系统中的注册表项&#xff0c…

学习记录——SpectFormer、DilateFormer、ShadowFormer

SpectFormer: Frequency and Attention is what you need in a Vision Transformer, arXiv2023 频域混合注意力SpectFormer 2023 论文&#xff1a;https://arxiv.org/abs/2304.06446 代码&#xff1a;https://badripatro.github.io/SpectFormers/ 摘要视觉变压器已经成功地应用…

【Spring——Spring的基础与创建】

目录 &#x1f367;1. 什么是 Spring &#xff1f; &#x1fad6;1.1 容器 &#x1f359;1.2 IoC &#x1f97d;1.3 汽车类——传统写法 &#x1f358;1.4 汽车类——IoC 写法 &#x1f32d;2. 配置 maven 国内源 &#x1f32e;2.1 在设置中勾选文件 &#x1f364;2.2 在…

SpringCloud学习路线(4)—— Nacos注册中心

一、认识和安装Nacos &#xff08;一&#xff09;概念&#xff1a; Nacos是Alibaba的产品&#xff0c;现在是SpringCloud中的一个组件&#xff0c;相较于Eureka功能更加丰富。 &#xff08;二&#xff09;下载地址&#xff1a; https://github.com/alibaba/nacos/releases &am…

一文看懂《关于网络安全和信息化工作重要指示》

7月14日至15日&#xff0c;全国网络安全和信息化工作会议在京召开。《关于网络安全和信息化工作重要指示》也在会上得到解读与传达。 从近年来党的二十大等重大会议上网络安全和数据安全等相关话题多次被提及、我国陆续发布多部网络安全&数据安全相关政策法规等等&#xf…

个人微信号二次开发的实现,api接口

各位兄弟姐妹们大家好&#xff01;&#xff01;&#xff01;&#xff01; 我又瞧到了好玩的微信机器人分享给大家&#xff01; 社群运营这几年风头正盛&#xff0c;不能落伍啊&#xff0c;我们也赶紧组建了社群。 但是微信群还是社交属性为主的&#xff0c;当我们运营多个社群的…

(栈队列堆) 剑指 Offer 09. 用两个栈实现队列 ——【Leetcode每日一题】

❓ 剑指 Offer 09. 用两个栈实现队列 难度&#xff1a;简单 用两个栈实现一个队列。队列的声明如下&#xff0c;请实现它的两个函数 appendTail 和 deleteHead &#xff0c;分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素&#xff0c;deleteHead …

如何通过振动传感器实现设备的故障诊断和预测性维护?

在现代工业生产中&#xff0c;设备的故障和停机时间对于企业的生产效率和经济效益有着巨大的影响。为了提高设备的可靠性和降低维护成本&#xff0c;越来越多的企业开始采用振动传感器作为关键的监测工具。振动传感器能够实时监测设备的振动情况&#xff0c;并通过数据分析和算…

自制编译器代码4.6含义

规则一&#xff0c;识别一个" 规则二&#xff0c;识别除了",,\n.\r的其他字符 规则三&#xff0c;这里第一个\意思是一个转义字符\&#xff0c;意思是ASCII码 比如\077就是八进制ASCII码的? 规则四&#xff0c;识别其他所有字符 规则五&#xff0c;回到defailt状态 …

不懂代码也不用怕!10款无代码网站搭建平台

作为设计师&#xff0c;对网站满脑子的构思&#xff0c;却受限于时间和技能&#xff08;比如写代码&#xff09;&#xff0c;这是何其无奈&#xff01;那个在你脑中盘桓许久的网站&#xff0c;或许是一个博客&#xff0c;可能是作品展示网站&#xff0c;但无论是哪种&#xff0…

华为OD机试真题 Java 实现【等差数列】【2023 B卷 100分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答…

GUI实例

运行代码&#xff1a; //GUI实例 #include"std_lib_facilities.h" #include"GUI/Simple_window.h" #include"GUI/GUI.h" #include"GUI/Graph.h" #include"GUI/Point.h"struct Lines_window :Window {Lines_window(Point xy…

《5.linux驱动开发-第2部分-5.2.字符设备驱动基础》最简单的模块源码分析 lsmod insmod modinfo rmmod dmesg

5.1.6.驱动应该这么学 5.1.6.1、先学好C语言 5.1.6.2、掌握相关预备知识 (1)硬件操作方面 (2)应用层API 5.1.6.3、驱动学习阶段 (1)注重实践&#xff0c;一步一步写驱动 (2)框架思维&#xff0c;多考虑整体和上下层 (3)先通过简单设备学linux驱动框架 (4)学会总结、记录&#x…

自动化测试框架性能测试报告模板

目录 一、项目概述 二、测试环境说明 三、测试方案 四、测试结果 五、结果分析 总结&#xff1a; 一、项目概述 1.1 编写目的 本次测试报告&#xff0c;为自动化测试框架性能测试总结报告。目的在于总结我们课程所压测的目标系统的性能点、优化历史和可优化方向。 1.2 …

高效太阳能太阳光模拟器

高效太阳能太阳光模拟器是一种能够高效模拟太阳光的设备。它能够产生与太阳光相近的光谱分布、光强和光照角度等特性的光线&#xff0c;用于太阳能相关的研究和应用中。 为了实现高效太阳能太阳光模拟器&#xff0c;以下几个方面是需要考虑的&#xff1a; 1. 光源&#xff1a;…

C++进阶—C++11新特性(移动语义右值引用可变参数模板lambda表达式function包装器bind函数)

目录 0. C11简介 1. 统一的列表初始化 1.1 {}初始化 1.2 std::initializer_list 2. 声明 2.1 auto 2.2 decltype 2.3 nullptr 3. 范围for循环 4. 智能指针 5. STL中一些变化 6. 右值引用和移动语义 6.1 左值引用和右值引用 6.2 左值引用与右值引用比较 6.3 右值…

三菱FX以太网模块设置ModbusTCP通讯

大家好&#xff0c;今天我们要来聊一聊转以太网捷米特JM-ETH-FX&#xff0c;这款设备内部集成了ModbusTCP通讯服务器&#xff0c;这意味着什么&#xff1f;ModbusTCP客户机&#xff0c;比如支持ModbusTCP的组态软件、OPC服务器、PLC以及使用高级语言开发的实现ModbusTCP客户机软…