mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-10-13 10:16:07 +00:00
refactor[storage]: storage code refactoring
This commit is contained in:
1 parent
356a96f787
commit
e1c547c9d6
23 files changed
+351
-316
No files matched your search
@@ -13,7 +13,6 @@
|
||||
package com.zfoo.boot;
|
||||
|
||||
import com.zfoo.storage.StorageContext;
|
||||
import com.zfoo.storage.interpreter.ResourceReader;
|
||||
import com.zfoo.storage.manager.StorageManager;
|
||||
import com.zfoo.storage.model.config.StorageConfig;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
@@ -38,12 +37,6 @@ public class StorageAutoConfiguration {
|
||||
return storageManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ResourceReader excelResourceReader() {
|
||||
return new ResourceReader();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public StorageContext storageContext() {
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The zfoo Authors
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.zfoo.boot;
|
||||
|
||||
import com.zfoo.boot.resource.StudentResource;
|
||||
import com.zfoo.protocol.ProtocolManager;
|
||||
import com.zfoo.protocol.generate.GenerateOperation;
|
||||
import com.zfoo.protocol.serializer.CodeLanguage;
|
||||
import com.zfoo.protocol.util.JsonUtils;
|
||||
import com.zfoo.storage.StorageContext;
|
||||
import com.zfoo.storage.model.config.StorageConfig;
|
||||
import com.zfoo.storage.model.vo.Storage;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
* @version 3.0
|
||||
*/
|
||||
@Ignore
|
||||
@SpringBootApplication(exclude = {
|
||||
// 排除MongoDB自动配置
|
||||
MongoAutoConfiguration.class
|
||||
})
|
||||
public class StorageTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(StorageTest.class);
|
||||
|
||||
@Bean
|
||||
public StorageConfig storageConfig(Environment environment) {
|
||||
var config = new StorageConfig();
|
||||
config.setScanPackage("com.zfoo.boot");
|
||||
config.setResourceLocation("classpath:/excel");
|
||||
config.setWriteable(true);
|
||||
config.setRecycle(false);
|
||||
return config;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startApplication() {
|
||||
var springBoot = new SpringApplicationBuilder();
|
||||
springBoot.sources(StorageTest.class).web(WebApplicationType.NONE).run();
|
||||
|
||||
var protocols = StorageContext.getStorageManager().storageMap().keySet();
|
||||
|
||||
var operation = new GenerateOperation();
|
||||
operation.getGenerateLanguages().add(CodeLanguage.GdScript);
|
||||
ProtocolManager.initProtocolAuto(protocols, operation);
|
||||
|
||||
var storage = (Storage<Integer, StudentResource>) StorageContext.getStorageManager().getStorage(StudentResource.class);
|
||||
for (StudentResource resource : storage.getAll()) {
|
||||
logger.info(JsonUtils.object2String(resource));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The zfoo Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.zfoo.boot.resource;
|
||||
|
||||
import com.zfoo.protocol.IPacket;
|
||||
import com.zfoo.storage.model.anno.Id;
|
||||
import com.zfoo.storage.model.anno.Resource;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
* @version 4.0
|
||||
*/
|
||||
@Resource
|
||||
public class StudentResource implements IPacket {
|
||||
|
||||
@Id
|
||||
public int id;
|
||||
|
||||
public String name;
|
||||
public int age;
|
||||
public float score;
|
||||
public String[] courses;
|
||||
public User[] users;
|
||||
public User user;
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,44 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<configuration scan="false" debug="false">
|
||||
|
||||
<contextName>com.zfoo.boot</contextName>
|
||||
|
||||
<property name="LOG_HOME" value="log/boot"/>
|
||||
<property name="PATTERN_FILE"
|
||||
value="%d{yyyy-MM-dd HH:mm:ss} [%5level] [%thread] %logger.%M\\(%F:%line\\) - %msg%n"/>
|
||||
<property name="PATTERN_CONSOLE"
|
||||
value="%d{yyyy-MM-dd HH:mm:ss} [%highlight(%5level)] [%thread] %logger.%M\\(%F:%line\\) - %msg%n"/>
|
||||
<!-- 负责写日志,控制台日志,会打印所有的包的所有级别日志 -->
|
||||
<appender name="zfoo_console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${PATTERN_CONSOLE}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 根logger -->
|
||||
<root level="info">
|
||||
<appender-ref ref="zfoo_console"/>
|
||||
</root>
|
||||
|
||||
<!--
|
||||
- 1.name:包名或类名,用来指定受此logger约束的某一个包或者具体的某一个类
|
||||
- 2.未设置打印级别,所以继承他的上级<root>的日志级别“DEBUG”
|
||||
- 3.未设置additivity,默认为true,将此logger的打印信息向上级传递;
|
||||
- 4.未设置appender,此logger本身不打印任何信息,级别为“DEBUG”及大于“DEBUG”的日志信息传递给root,
|
||||
- root接到下级传递的信息,交给已经配置好的名为“STDOUT”的appender处理,“STDOUT”appender将信息打印到控制台;
|
||||
-->
|
||||
<logger name="ch.qos.logback" level="info"/>
|
||||
|
||||
<!--*******************************************Spring********************************************************-->
|
||||
<!--logger中的name是指代码的包名或类名,路径要写全,可以配置不同包中的日志输出到不同的文件中。level是日志输出级别 -->
|
||||
<!--过滤掉spring的一些无用的DEBUG信息-->
|
||||
<logger name="org.springframework" level="info"/>
|
||||
<!-- additivity="false"表示不继承父logger的配置和父类没有关系-->
|
||||
<logger name="org.springframework.core" level="warn"/>
|
||||
|
||||
|
||||
<!--*******************************************Netty*********************************************************-->
|
||||
<logger name="io.netty" level="info"/>
|
||||
</configuration>
|
||||
@@ -467,10 +467,7 @@ public class OrmManager implements IOrmManager {
|
||||
throw new RunException("在Orm中只能使用Orm的Index注解,不能使用Storage的Index注解,为了避免不必要的误解和增强项目的健壮性,禁止这样使用");
|
||||
}
|
||||
|
||||
var filedList = Arrays.stream(clazz.getDeclaredFields())
|
||||
.filter(it -> !Modifier.isTransient(it.getModifiers()))
|
||||
.filter(it -> !Modifier.isStatic(it.getModifiers()))
|
||||
.collect(Collectors.toList());
|
||||
var filedList = ReflectionUtils.notStaticAndTransientFields(clazz);
|
||||
|
||||
for (var field : filedList) {
|
||||
// entity必须包含属性的get和set方法
|
||||
|
||||
@@ -18,11 +18,12 @@ import com.zfoo.protocol.exception.RunException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
@@ -89,10 +90,7 @@ public abstract class ClassUtils {
|
||||
// 必须要有一个空的构造器
|
||||
ReflectionUtils.publicEmptyConstructor(clazz);
|
||||
|
||||
var filedList = Arrays.stream(clazz.getDeclaredFields())
|
||||
.filter(it -> !Modifier.isTransient(it.getModifiers()))
|
||||
.filter(it -> !Modifier.isStatic(it.getModifiers()))
|
||||
.collect(Collectors.toList());
|
||||
var filedList = ReflectionUtils.notStaticAndTransientFields(clazz);
|
||||
|
||||
for (var field : filedList) {
|
||||
// 是一个基本类型变量
|
||||
|
||||
@@ -16,15 +16,19 @@ import com.zfoo.protocol.collection.ArrayUtils;
|
||||
import com.zfoo.protocol.exception.RunException;
|
||||
import com.zfoo.protocol.exception.UnknownException;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
@@ -319,6 +323,14 @@ public abstract class ReflectionUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取class中的普通field属性字段
|
||||
public static List<Field> notStaticAndTransientFields(Class<?> clazz) {
|
||||
return Arrays.stream(clazz.getDeclaredFields())
|
||||
.filter(it -> !Modifier.isStatic(it.getModifiers()))
|
||||
.filter(it -> !Modifier.isTransient(it.getModifiers()))
|
||||
.filter(it -> !it.isAnnotationPresent(Transient.class))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static String fieldToGetMethod(Class<?> clazz, Field field) {
|
||||
var fieldName = field.getName();
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
package com.zfoo.storage;
|
||||
|
||||
import com.zfoo.scheduler.model.StopWatch;
|
||||
import com.zfoo.storage.interpreter.IResourceReader;
|
||||
import com.zfoo.storage.manager.IStorageManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -37,8 +36,6 @@ public class StorageContext implements ApplicationListener<ApplicationContextEve
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private IResourceReader resourceReader;
|
||||
|
||||
private IStorageManager storageManager;
|
||||
|
||||
public static StorageContext getStorageContext() {
|
||||
@@ -49,14 +46,6 @@ public class StorageContext implements ApplicationListener<ApplicationContextEve
|
||||
return instance.applicationContext;
|
||||
}
|
||||
|
||||
public static StorageContext getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static IResourceReader getResourceReader() {
|
||||
return instance.resourceReader;
|
||||
}
|
||||
|
||||
public static IStorageManager getStorageManager() {
|
||||
return instance.storageManager;
|
||||
}
|
||||
@@ -69,7 +58,6 @@ public class StorageContext implements ApplicationListener<ApplicationContextEve
|
||||
// 初始化上下文
|
||||
StorageContext.instance = this;
|
||||
instance.applicationContext = event.getApplicationContext();
|
||||
instance.resourceReader = applicationContext.getBean(IResourceReader.class);
|
||||
instance.storageManager = applicationContext.getBean(IStorageManager.class);
|
||||
|
||||
// 初始化,并读取配置表
|
||||
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The zfoo Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
@@ -11,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.zfoo.storage.util;
|
||||
package com.zfoo.storage.interpreter;
|
||||
|
||||
import com.zfoo.protocol.exception.RunException;
|
||||
import com.zfoo.protocol.util.StringUtils;
|
||||
@@ -32,7 +31,7 @@ import java.util.List;
|
||||
* @author meiwei666
|
||||
* @version 4.0
|
||||
*/
|
||||
public abstract class CsvReaderUtils {
|
||||
public abstract class CsvReader {
|
||||
|
||||
public static ResourceData readResourceDataFromCSV(InputStream input, String fileName) {
|
||||
var records = parseCsv(input, fileName);
|
||||
+3
-26
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The zfoo Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
@@ -11,48 +10,26 @@
|
||||
* See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.zfoo.storage.util;
|
||||
package com.zfoo.storage.interpreter;
|
||||
|
||||
import com.zfoo.protocol.exception.RunException;
|
||||
import com.zfoo.protocol.util.FileUtils;
|
||||
import com.zfoo.protocol.util.JsonUtils;
|
||||
import com.zfoo.protocol.util.StringUtils;
|
||||
import com.zfoo.storage.model.resource.ResourceData;
|
||||
import com.zfoo.storage.model.resource.ResourceEnum;
|
||||
import com.zfoo.storage.model.resource.ResourceHeader;
|
||||
import com.zfoo.storage.util.CellUtils;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author meiwei666
|
||||
* @version 4.0
|
||||
*/
|
||||
public abstract class ExcelReaderUtils {
|
||||
|
||||
public static void excelConvertJson(String inputDir, String outputDir) throws IOException {
|
||||
var listFiles = FileUtils.getAllReadableFiles(new File(inputDir))
|
||||
.stream()
|
||||
.filter(it -> ResourceEnum.isExcel(FileUtils.fileExtName(it.getName())))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (var file : listFiles) {
|
||||
var fileSimpleName = FileUtils.fileSimpleName(file.getName());
|
||||
var jsonFileName = StringUtils.format("{}.json", fileSimpleName);
|
||||
var inputStream = FileUtils.openInputStream(file);
|
||||
var resourceData = readResourceDataFromExcel(inputStream, file.getName());
|
||||
|
||||
var outputFilePath = FileUtils.joinPath(outputDir, jsonFileName);
|
||||
FileUtils.deleteFile(new File(outputFilePath));
|
||||
FileUtils.writeStringToFile(new File(outputFilePath), JsonUtils.object2String(resourceData), true);
|
||||
}
|
||||
}
|
||||
public abstract class ExcelReader {
|
||||
|
||||
public static ResourceData readResourceDataFromExcel(InputStream inputStream, String fileName) {
|
||||
// 只读取代码里写的字段
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The zfoo Authors
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.zfoo.storage.interpreter;
|
||||
|
||||
import com.zfoo.protocol.util.IOUtils;
|
||||
import com.zfoo.protocol.util.JsonUtils;
|
||||
import com.zfoo.protocol.util.StringUtils;
|
||||
import com.zfoo.storage.model.resource.ResourceData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
* @version 3.0
|
||||
*/
|
||||
public abstract class JsonReader {
|
||||
|
||||
public static ResourceData readResourceDataFromCSV(InputStream input) {
|
||||
try {
|
||||
return JsonUtils.string2Object(StringUtils.bytesToString(IOUtils.toByteArray(input)), ResourceData.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+9
-47
@@ -13,26 +13,18 @@
|
||||
package com.zfoo.storage.interpreter;
|
||||
|
||||
import com.zfoo.protocol.exception.RunException;
|
||||
import com.zfoo.protocol.util.IOUtils;
|
||||
import com.zfoo.protocol.util.JsonUtils;
|
||||
import com.zfoo.protocol.util.ReflectionUtils;
|
||||
import com.zfoo.protocol.util.StringUtils;
|
||||
import com.zfoo.storage.StorageContext;
|
||||
import com.zfoo.storage.model.anno.Id;
|
||||
import com.zfoo.storage.model.resource.ResourceData;
|
||||
import com.zfoo.storage.model.resource.ResourceEnum;
|
||||
import com.zfoo.storage.strategy.*;
|
||||
import com.zfoo.storage.util.CsvReaderUtils;
|
||||
import com.zfoo.storage.util.ExcelReaderUtils;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.context.support.ConversionServiceFactoryBean;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -40,7 +32,7 @@ import java.util.stream.Collectors;
|
||||
* @author godotg
|
||||
* @version 4.0
|
||||
*/
|
||||
public class ResourceReader implements IResourceReader {
|
||||
public class ResourceInterpreter {
|
||||
|
||||
private static final TypeDescriptor TYPE_DESCRIPTOR = TypeDescriptor.valueOf(String.class);
|
||||
|
||||
@@ -58,16 +50,15 @@ public class ResourceReader implements IResourceReader {
|
||||
conversionServiceFactoryBean.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> read(InputStream inputStream, Class<T> clazz, String suffix) throws IOException {
|
||||
public static <T> List<T> read(InputStream inputStream, Class<T> clazz, String suffix) throws IOException {
|
||||
ResourceData resource = null;
|
||||
var resourceEnum = ResourceEnum.getResourceEnumByType(suffix);
|
||||
if (resourceEnum == ResourceEnum.JSON) {
|
||||
resource = JsonUtils.string2Object(StringUtils.bytesToString(IOUtils.toByteArray(inputStream)), ResourceData.class);
|
||||
resource = JsonReader.readResourceDataFromCSV(inputStream);
|
||||
} else if (resourceEnum == ResourceEnum.EXCEL_XLS || resourceEnum == ResourceEnum.EXCEL_XLSX) {
|
||||
resource = ExcelReaderUtils.readResourceDataFromExcel(inputStream, clazz.getSimpleName());
|
||||
resource = ExcelReader.readResourceDataFromExcel(inputStream, clazz.getSimpleName());
|
||||
} else if (resourceEnum == ResourceEnum.CSV) {
|
||||
resource = CsvReaderUtils.readResourceDataFromCSV(inputStream, clazz.getSimpleName());
|
||||
resource = CsvReader.readResourceDataFromCSV(inputStream, clazz.getSimpleName());
|
||||
} else {
|
||||
throw new RunException("不支持文件[{}]的配置类型[{}]", clazz.getSimpleName(), suffix);
|
||||
}
|
||||
@@ -94,7 +85,7 @@ public class ResourceReader implements IResourceReader {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void inject(Object instance, Field field, String content) {
|
||||
private static void inject(Object instance, Field field, String content) {
|
||||
try {
|
||||
var targetType = new TypeDescriptor(field);
|
||||
var value = conversionServiceFactoryBean.getObject().convert(content, TYPE_DESCRIPTOR, targetType);
|
||||
@@ -106,12 +97,8 @@ public class ResourceReader implements IResourceReader {
|
||||
}
|
||||
|
||||
// 只读取代码里写的字段
|
||||
private Collection<FieldInfo> getFieldInfos(Map<String, Integer> fieldMap, Class<?> clazz) {
|
||||
var fieldList = Arrays.stream(clazz.getDeclaredFields())
|
||||
.filter(it -> !Modifier.isTransient(it.getModifiers()))
|
||||
.filter(it -> !Modifier.isStatic(it.getModifiers()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
private static Collection<FieldInfo> getFieldInfos(Map<String, Integer> fieldMap, Class<?> clazz) {
|
||||
var fieldList = ReflectionUtils.notStaticAndTransientFields(clazz);
|
||||
for (var field : fieldList) {
|
||||
if (!fieldMap.containsKey(field.getName())) {
|
||||
throw new RunException("资源类[class:{}]的声明属性[filed:{}]无法获取,请检查配置表的格式", clazz, field.getName());
|
||||
@@ -123,35 +110,10 @@ public class ResourceReader implements IResourceReader {
|
||||
throw new RunException("资源类[class:{}]的主键[Id:{}]必须放在Excel配置表的第一列,请检查配置表的格式", clazz, field.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (!StorageContext.getStorageManager().storageConfig().isWriteable()) {
|
||||
if (Modifier.isPublic(field.getModifiers())) {
|
||||
throw new RunException("因为静态资源类是不能被修改的,资源类[class:{}]的属性[filed:{}]不能被public修饰,用private修饰或者开启配置writeable属性", clazz, field.getName());
|
||||
}
|
||||
|
||||
var setMethodName = StringUtils.EMPTY;
|
||||
try {
|
||||
setMethodName = ReflectionUtils.fieldToSetMethod(clazz, field);
|
||||
} catch (Exception e) {
|
||||
// 没有setMethod是正确的
|
||||
}
|
||||
if (StringUtils.isNotBlank(setMethodName)) {
|
||||
throw new RunException("因为静态资源类是不能被修改的,资源类[class:{}]的属性[filed:{}]不能含有set方法[{}],删除set方法或者开启配置writeable属性", clazz, field.getName(), setMethodName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fieldList.stream().map(it -> new FieldInfo(fieldMap.get(it.getName()), it)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Workbook createWorkbook(InputStream input, String name) {
|
||||
try {
|
||||
return WorkbookFactory.create(input);
|
||||
} catch (IOException e) {
|
||||
throw new RunException("静态资源[{}]异常,无法读取文件", name);
|
||||
}
|
||||
}
|
||||
|
||||
private static class FieldInfo {
|
||||
public final int index;
|
||||
public final Field field;
|
||||
@@ -162,7 +124,7 @@ public class ResourceReader implements IResourceReader {
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Integer> getFieldMap(ResourceData resource, Class<?> clazz) {
|
||||
public static Map<String, Integer> getFieldMap(ResourceData resource, Class<?> clazz) {
|
||||
var header = resource.getHeaders();
|
||||
if (header == null) {
|
||||
throw new RunException("无法获取资源[class:{}]的Excel文件的属性控制列", clazz.getSimpleName());
|
||||
@@ -15,7 +15,6 @@ package com.zfoo.storage.manager;
|
||||
|
||||
import com.zfoo.storage.model.config.StorageConfig;
|
||||
import com.zfoo.storage.model.vo.Storage;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -40,7 +39,6 @@ public interface IStorageManager {
|
||||
*/
|
||||
void initAfter();
|
||||
|
||||
@Nullable
|
||||
Storage<?, ?> getStorage(Class<?> clazz);
|
||||
|
||||
Map<Class<?>, Storage<?, ?>> storageMap();
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.util.ResourceUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
@@ -92,6 +93,29 @@ public class StorageManager implements IStorageManager {
|
||||
resourceDefinitionMap.put(resourceClazz, resourceDef);
|
||||
}
|
||||
|
||||
// 检查class字段是否合法
|
||||
if (!storageConfig.isWriteable()) {
|
||||
for (var definition : resourceDefinitionMap.values()) {
|
||||
var clazz = definition.getClazz();
|
||||
var fieldList = ReflectionUtils.notStaticAndTransientFields(clazz);
|
||||
for (var field : fieldList) {
|
||||
if (Modifier.isPublic(field.getModifiers())) {
|
||||
throw new RunException("因为静态资源类是不能被修改的,资源类[class:{}]的属性[filed:{}]不能被public修饰,用private修饰或者开启配置writeable属性", clazz, field.getName());
|
||||
}
|
||||
|
||||
var setMethodName = StringUtils.EMPTY;
|
||||
try {
|
||||
setMethodName = ReflectionUtils.fieldToSetMethod(clazz, field);
|
||||
} catch (Exception e) {
|
||||
// 没有setMethod是正确的
|
||||
}
|
||||
if (StringUtils.isNotBlank(setMethodName)) {
|
||||
throw new RunException("因为静态资源类是不能被修改的,资源类[class:{}]的属性[filed:{}]不能含有set方法[{}],删除set方法或者开启配置writeable属性", clazz, field.getName(), setMethodName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
for (var definition : resourceDefinitionMap.values()) {
|
||||
var clazz = definition.getClazz();
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.zfoo.protocol.util.AssertionUtils;
|
||||
import com.zfoo.protocol.util.IOUtils;
|
||||
import com.zfoo.protocol.util.ReflectionUtils;
|
||||
import com.zfoo.protocol.util.StringUtils;
|
||||
import com.zfoo.storage.StorageContext;
|
||||
import com.zfoo.storage.interpreter.ResourceInterpreter;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.io.InputStream;
|
||||
@@ -47,11 +47,10 @@ public class Storage<K, V> {
|
||||
public void init(InputStream inputStream, Class<?> resourceClazz, String suffix) {
|
||||
try {
|
||||
this.clazz = (Class<V>) resourceClazz;
|
||||
var reader = StorageContext.getResourceReader();
|
||||
idDef = IdDef.valueOf(resourceClazz);
|
||||
indexDefMap = IndexDef.createResourceIndexes(resourceClazz);
|
||||
|
||||
var list = reader.read(inputStream, resourceClazz, suffix);
|
||||
var list = ResourceInterpreter.read(inputStream, resourceClazz, suffix);
|
||||
|
||||
dataMap.clear();
|
||||
indexMap.clear();
|
||||
@@ -92,6 +91,10 @@ public class Storage<K, V> {
|
||||
return Collections.unmodifiableMap(dataMap);
|
||||
}
|
||||
|
||||
public IdDef getIdDef() {
|
||||
return idDef;
|
||||
}
|
||||
|
||||
public boolean contain(K key) {
|
||||
return dataMap.containsKey(key);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ package com.zfoo.storage.schema;
|
||||
import com.zfoo.protocol.util.DomUtils;
|
||||
import com.zfoo.protocol.util.StringUtils;
|
||||
import com.zfoo.storage.StorageContext;
|
||||
import com.zfoo.storage.interpreter.ResourceReader;
|
||||
import com.zfoo.storage.manager.StorageManager;
|
||||
import com.zfoo.storage.model.config.StorageConfig;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
@@ -40,7 +39,7 @@ public class StorageDefinitionParser implements BeanDefinitionParser {
|
||||
// 解析StorageConfig的配置
|
||||
parseStorageConfig(element, parserContext);
|
||||
|
||||
// 注册StorageContext,ExcelResourceReader
|
||||
// 注册StorageContext
|
||||
registerBeanDefinition(parserContext);
|
||||
|
||||
// 注册StorageManager
|
||||
@@ -87,12 +86,6 @@ public class StorageDefinitionParser implements BeanDefinitionParser {
|
||||
name = StringUtils.uncapitalize(clazz.getName());
|
||||
builder = BeanDefinitionBuilder.rootBeanDefinition(clazz);
|
||||
registry.registerBeanDefinition(name, builder.getBeanDefinition());
|
||||
|
||||
// 注册ResourceReader
|
||||
clazz = ResourceReader.class;
|
||||
name = StringUtils.uncapitalize(clazz.getName());
|
||||
builder = BeanDefinitionBuilder.rootBeanDefinition(clazz);
|
||||
registry.registerBeanDefinition(name, builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void resolvePlaceholder(String attributeName, String fieldName, BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
package com.zfoo.storage.strategy;
|
||||
|
||||
import com.zfoo.protocol.util.ClassUtils;
|
||||
import com.zfoo.protocol.util.StringUtils;
|
||||
import com.zfoo.storage.StorageContext;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
/**
|
||||
@@ -30,18 +30,8 @@ public class StringToClassConverter implements Converter<String, Class<?>> {
|
||||
source = "java.lang." + source;
|
||||
}
|
||||
|
||||
ClassLoader loader = null;
|
||||
|
||||
StorageContext context = StorageContext.getInstance();
|
||||
|
||||
if (context != null) {
|
||||
loader = StorageContext.getApplicationContext().getClassLoader();
|
||||
} else {
|
||||
loader = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
|
||||
try {
|
||||
return Class.forName(source, true, loader);
|
||||
return Class.forName(source, true, ClassUtils.getDefaultClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException(StringUtils.format("无法将字符串[{}]转换为Class对象", source));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The zfoo Authors
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.zfoo.storage.util;
|
||||
|
||||
import com.zfoo.protocol.exception.RunException;
|
||||
import com.zfoo.protocol.util.FileUtils;
|
||||
import com.zfoo.protocol.util.JsonUtils;
|
||||
import com.zfoo.protocol.util.ReflectionUtils;
|
||||
import com.zfoo.protocol.util.StringUtils;
|
||||
import com.zfoo.storage.interpreter.CsvReader;
|
||||
import com.zfoo.storage.interpreter.ExcelReader;
|
||||
import com.zfoo.storage.model.resource.ResourceEnum;
|
||||
import com.zfoo.storage.model.vo.Storage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
* @version 3.0
|
||||
*/
|
||||
public abstract class ExportUtils {
|
||||
|
||||
public static void excel2Json(String inputDir, String outputDir) throws IOException {
|
||||
var excelFiles = scanExcelFiles(inputDir);
|
||||
for (var excel : excelFiles) {
|
||||
var excelSimpleName = FileUtils.fileSimpleName(excel.getName());
|
||||
var jsonFileName = StringUtils.format("{}.json", excelSimpleName);
|
||||
var resourceData = ExcelReader.readResourceDataFromExcel(FileUtils.openInputStream(excel), excel.getName());
|
||||
|
||||
var outputFilePath = FileUtils.joinPath(outputDir, jsonFileName);
|
||||
FileUtils.deleteFile(new File(outputFilePath));
|
||||
FileUtils.writeStringToFile(new File(outputFilePath), JsonUtils.object2String(resourceData), true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void excel2Csv(String inputDir, String outputDir) throws IOException {
|
||||
var excelFiles = scanExcelFiles(inputDir);
|
||||
for (var excel : excelFiles) {
|
||||
var excelSimpleName = FileUtils.fileSimpleName(excel.getName());
|
||||
var csvFileName = StringUtils.format("{}.csv", excelSimpleName);
|
||||
var resourceData = CsvReader.readResourceDataFromCSV(FileUtils.openInputStream(excel), excel.getName());
|
||||
|
||||
var outputFilePath = FileUtils.joinPath(outputDir, csvFileName);
|
||||
FileUtils.deleteFile(new File(outputFilePath));
|
||||
FileUtils.writeStringToFile(new File(outputFilePath), JsonUtils.object2String(resourceData), true);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<File> scanExcelFiles(String inputDir) {
|
||||
return FileUtils.getAllReadableFiles(new File(inputDir))
|
||||
.stream()
|
||||
.filter(it -> ResourceEnum.isExcel(FileUtils.fileExtName(it.getName())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 将class里的map自动赋值storage
|
||||
public static <T> T autoWrapData(Class<T> clazz, Map<Class<?>, Storage<?, ?>> storageMap) {
|
||||
var instance = ReflectionUtils.newInstance(clazz);
|
||||
|
||||
var filedList = ReflectionUtils.notStaticAndTransientFields(clazz);
|
||||
|
||||
var wrapClass = new HashSet<Class<?>>();
|
||||
|
||||
for (var field : filedList) {
|
||||
var fieldType = field.getType();
|
||||
if (!fieldType.equals(Map.class)) {
|
||||
throw new RunException("[class:{}]类型声明不正确,导出的storage必须为Map接口类型", clazz.getCanonicalName());
|
||||
}
|
||||
|
||||
var type = field.getGenericType();
|
||||
var types = ((ParameterizedType) type).getActualTypeArguments();
|
||||
|
||||
var keyType = types[0];
|
||||
var valueType = types[1];
|
||||
var valueClass = (Class<?>) valueType;
|
||||
var storage = storageMap.get(valueClass);
|
||||
var idFieldType = storage.getIdDef().getField().getType();
|
||||
if (idFieldType.isPrimitive()) {
|
||||
if (idFieldType.equals(long.class) && keyType.equals(Long.class)) {
|
||||
} else if (idFieldType.equals(int.class) && keyType.equals(Integer.class)) {
|
||||
} else if (idFieldType.equals(short.class) && keyType.equals(Short.class)) {
|
||||
} else if (idFieldType.equals(byte.class) && keyType.equals(Byte.class)) {
|
||||
} else {
|
||||
throw new RunException("[class:{}]中的[field:{}]类型声明不正确,类型需要改为[Map<{}, {}>]", clazz.getSimpleName(), field.getName(), idFieldType, valueClass.getSimpleName());
|
||||
}
|
||||
} else if (!keyType.equals(idFieldType)) {
|
||||
throw new RunException("[class:{}]中的[field:{}]类型声明不正确,类型需要改为[Map<{}, {}>]", clazz.getSimpleName(), field.getName(), idFieldType, valueClass.getSimpleName());
|
||||
}
|
||||
if (!wrapClass.add(valueClass)) {
|
||||
throw new RunException("[class:{}]中含有重复的类型[{}]", clazz.getCanonicalName(), valueType);
|
||||
}
|
||||
ReflectionUtils.setField(field, instance, storage.getData());
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
package com.zfoo.storage.excel;
|
||||
|
||||
import com.zfoo.storage.util.ExcelReaderUtils;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
@@ -33,13 +32,6 @@ import java.util.Iterator;
|
||||
@Ignore
|
||||
public class ExcelTest {
|
||||
|
||||
@Test
|
||||
public void excelConvertJson() throws Exception{
|
||||
String inputDir = "E:\\workspace\\zfoo\\storage\\src\\test\\resources\\excel";
|
||||
String outputDir = "E:\\workspace\\zfoo\\storage\\src\\test\\resources\\excel";
|
||||
ExcelReaderUtils.excelConvertJson(inputDir, outputDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createExcelTest() throws IOException {
|
||||
//第一步创建workbook
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The zfoo Authors
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.zfoo.storage.export;
|
||||
|
||||
import com.zfoo.protocol.IPacket;
|
||||
import com.zfoo.protocol.ProtocolManager;
|
||||
import com.zfoo.protocol.buffer.ByteBufUtils;
|
||||
import com.zfoo.protocol.generate.GenerateOperation;
|
||||
import com.zfoo.protocol.serializer.CodeLanguage;
|
||||
import com.zfoo.protocol.util.FileUtils;
|
||||
import com.zfoo.protocol.util.JsonUtils;
|
||||
import com.zfoo.storage.manager.StorageManager;
|
||||
import com.zfoo.storage.model.anno.Id;
|
||||
import com.zfoo.storage.model.anno.Resource;
|
||||
import com.zfoo.storage.model.config.StorageConfig;
|
||||
import com.zfoo.storage.model.vo.Storage;
|
||||
import com.zfoo.storage.util.ExportUtils;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.UnpooledHeapByteBuf;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
* @version 3.0
|
||||
*/
|
||||
|
||||
|
||||
@Ignore
|
||||
public class ExportBinaryTest {
|
||||
|
||||
public static class User implements IPacket {
|
||||
|
||||
public String id;
|
||||
public String name;
|
||||
public String sex;
|
||||
public int age;
|
||||
|
||||
}
|
||||
|
||||
@Resource
|
||||
public static class StudentResource implements IPacket {
|
||||
|
||||
@Id
|
||||
public int id;
|
||||
|
||||
public String name;
|
||||
public int age;
|
||||
public float score;
|
||||
public String[] courses;
|
||||
public User[] users;
|
||||
public User user;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class ResourceData implements IPacket {
|
||||
|
||||
public Map<Integer, StudentResource> studentResources;
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
var config = new StorageConfig();
|
||||
config.setScanPackage("com.zfoo.storage.export");
|
||||
config.setResourceLocation("classpath:/excel");
|
||||
config.setWriteable(true);
|
||||
config.setRecycle(false);
|
||||
var storageManager = new StorageManager();
|
||||
storageManager.setStorageConfig(config);
|
||||
storageManager.initBefore();
|
||||
storageManager.initAfter();
|
||||
|
||||
// 生成协议
|
||||
var protocols = new HashSet<Class<?>>();
|
||||
protocols.add(ResourceData.class);
|
||||
protocols.addAll(storageManager.storageMap().keySet());
|
||||
var operation = new GenerateOperation();
|
||||
operation.getGenerateLanguages().add(CodeLanguage.GdScript);
|
||||
ProtocolManager.initProtocolAuto(protocols, operation);
|
||||
|
||||
// 生成数据
|
||||
var resourceData = ExportUtils.autoWrapData(ResourceData.class, storageManager.storageMap());
|
||||
var buffer = new UnpooledHeapByteBuf(ByteBufAllocator.DEFAULT, 100, Integer.MAX_VALUE);
|
||||
ProtocolManager.write(buffer, resourceData);
|
||||
var bytes = ByteBufUtils.readAllBytes(buffer);
|
||||
FileUtils.writeInputStreamToFile(new File("D:/github/godot-bird/binary_data.cfg"), new ByteArrayInputStream(bytes));
|
||||
|
||||
var storage = (Storage<Integer, StudentResource>) storageManager.getStorage(StudentResource.class);
|
||||
for (StudentResource resource : storage.getAll()) {
|
||||
System.out.println(JsonUtils.object2String(resource));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+12
-7
@@ -10,19 +10,24 @@
|
||||
* See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.zfoo.boot.resource;
|
||||
package com.zfoo.storage.export;
|
||||
|
||||
import com.zfoo.protocol.IPacket;
|
||||
import com.zfoo.storage.util.ExportUtils;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
* @version 3.0
|
||||
*/
|
||||
public class User implements IPacket {
|
||||
@Ignore
|
||||
public class ExportCsvTest {
|
||||
|
||||
public String id;
|
||||
public String name;
|
||||
public String sex;
|
||||
public int age;
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
var inputDir = "E:\\workspace\\zfoo\\storage\\src\\test\\resources\\excel";
|
||||
var outputDir = "E:\\workspace\\zfoo\\storage\\src\\test\\resources\\excel";
|
||||
ExportUtils.excel2Json(inputDir, outputDir);
|
||||
}
|
||||
|
||||
}
|
||||
+13
-13
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The zfoo Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
@@ -11,23 +10,24 @@
|
||||
* See the License for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.zfoo.storage.interpreter;
|
||||
package com.zfoo.storage.export;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import com.zfoo.storage.util.ExportUtils;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* 解释器模式设计的文本解析器
|
||||
* <p>
|
||||
* interpreter [in'ter·pret·er || ɪn'tɜrprɪtə(r) /-'tɜːp-]
|
||||
* n. 直译程序, 翻译员, 解释者
|
||||
*
|
||||
* @author godotg
|
||||
* @version 4.0
|
||||
* @version 3.0
|
||||
*/
|
||||
public interface IResourceReader {
|
||||
@Ignore
|
||||
public class ExportJsonTest {
|
||||
|
||||
<T> List<T> read(InputStream inputStream, Class<T> clazz, String suffix) throws IOException;
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
var inputDir = "E:\\workspace\\zfoo\\storage\\src\\test\\resources\\excel";
|
||||
var outputDir = "E:\\workspace\\zfoo\\storage\\src\\test\\resources\\excel";
|
||||
ExportUtils.excel2Json(inputDir, outputDir);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user