最近在开发工程中,需要根据excel中的数据生成标签类,手写太费劲啦,还得一边写一边对,受不了啦 决定写一个解析工具,自动生成代码
项目采用springboot +vue的开发方式,但vue并不是分离项目,而是集成在项目内部,加入定时任务每天零点删除指定文件夹的生成文件,避免产生垃圾文件,提供工具生成和下载功能
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-thymeleaf
com.alibaba
easyexcel
2.1.1
com.squareup
javapoet
1.11.1
server.port=10086
spring.servlet.multipart.max-file-size=20MB
spring.servlet.multipart.max-request-size=25MB
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n
${logPath}/info/%d.log
${maxHistory}
ERROR
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n
${logPath}/error/%d.log
60
具体项目会放在资源中,想要的私聊或者下载
微服务生成Tag工具
微服务生成Tag工具
自动生成表单信息
将文件拖到此处,或点击上传
下载
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> pareExcel(MultipartFile file, GeneInfo geneInfo) {
try{
logger.info("读取"+file.getOriginalFilename()+"文件");
logger.info("读取"+geneInfo.getSheetName()+"sheet页的excel数据");
// 读取excel数据
List> data = EasyExcel
.read(file.getInputStream())
.sheet(geneInfo.getSheetName())
.headRowNumber(0)
.doReadSync();
// 请求参数list
List reqParams = new ArrayList<>();
// 响应参数list
List resParams = new ArrayList<>();
// 读取请求参数标识
boolean readerReqFlag =false;
// 读取响应参数标识
boolean readerResFlag =false;
for (int i = 0; i < data.size(); i++) {
HashMap 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 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>(200,geneInfos);
}catch (Exception e){
logger.error("自动生成接口失败",e);
return new Result>(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 reqParams, List resParams) throws IOException {
HashMap> filedHashMap = generatorFiled(reqParams, resParams,geneInfo);
Iterator>> iterator = filedHashMap.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry> 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> generatorFiled(List reqParams, List resParams,GeneInfo geneInfo){
// 最终结果
HashMap> result = new HashMap<>();
// 请求字段列表
List reqFiledList = new ArrayList<>();
// 响应字段列表
List resFiledList = new ArrayList<>();
// 处理之后的请求参数
List reqParamResult =new ArrayList<>();
// 处理之后的响应参数
List 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();
}
}
由于没有持久化到数据库,所以,下载不能够刷新页面,想加可以加一下