perf[storage]: 优化了配置表读取功能

This commit is contained in:
meiwei
2022-07-07 19:56:46 +08:00
parent e8b1d8f079
commit b6838471f2
17 changed files with 190 additions and 328 deletions
@@ -13,7 +13,6 @@
package com.zfoo.boot;
import com.zfoo.storage.StorageContext;
import com.zfoo.storage.interpreter.ExcelResourceReader;
import com.zfoo.storage.manager.StorageManager;
import com.zfoo.storage.model.config.StorageConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -27,6 +27,6 @@ import java.util.List;
*/
public interface IResourceReader {
<T> List<T> read(InputStream inputStream, Class<T> clazz);
<T> List<T> read(InputStream inputStream, Class<T> clazz, String suffix);
}
@@ -1,156 +0,0 @@
package com.zfoo.storage.interpreter;
import com.zfoo.protocol.exception.RunException;
import com.zfoo.protocol.util.JsonUtils;
import com.zfoo.protocol.util.ReflectionUtils;
import com.zfoo.protocol.util.StringUtils;
import com.zfoo.storage.model.anno.Id;
import com.zfoo.storage.strategy.*;
import org.apache.commons.io.IOUtils;
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.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
public class JsonResourceReader implements IResourceReader {
private static final TypeDescriptor TYPE_DESCRIPTOR = TypeDescriptor.valueOf(String.class);
private static final ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
static {
var converters = new HashSet<>();
converters.add(new JsonToArrayConverter());
converters.add(new JsonToMapConverter());
converters.add(new JsonToObjectConverter());
converters.add(new StringToClassConverter());
converters.add(new StringToDateConverter());
converters.add(new StringToMapConverter());
conversionServiceFactoryBean.setConverters(converters);
conversionServiceFactoryBean.afterPropertiesSet();
}
@Override
public <T> List<T> read(InputStream inputStream, Class<T> clazz) {
String txt = readTxt(inputStream, clazz);
JsonResource JsonResource = JsonUtils.string2Object(txt, JsonResource.class);
var result = new ArrayList<T>();
// 默认取到第一个sheet页
var fieldInfos = getFieldInfos(JsonResource, clazz);
var iterator = JsonResource.getData().iterator();
// 从ROW_SERVER这行开始读取数据
while (iterator.hasNext()) {
var row = iterator.next();
var instance = ReflectionUtils.newInstance(clazz);
for (var fieldInfo : fieldInfos) {
var content = row.get(fieldInfo.index);
if (StringUtils.isNotEmpty(content) || fieldInfo.field.getType() == String.class) {
inject(instance, fieldInfo.field, content);
}
}
result.add(instance);
}
return result;
}
private void inject(Object instance, Field field, String content) {
try {
var targetType = new TypeDescriptor(field);
var value = conversionServiceFactoryBean.getObject().convert(content, TYPE_DESCRIPTOR, targetType);
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, instance, value);
} catch (Exception e) {
throw new RunException(e, "无法将Excel资源[class:{}]中的[content:{}]转换为属性[field:{}]", instance.getClass().getSimpleName(), content, field.getName());
}
}
// 只读取代码里写的字段
private Collection<FieldInfo> getFieldInfos(JsonResource resource, Class<?> clazz) {
var fieldRow = resource.getColumns();
if (fieldRow == null) {
throw new RunException("无法获取资源[class:{}]的Excel文件的属性控制列", clazz.getSimpleName());
}
var cellFieldMap = new HashMap<String, Integer>();
for (var i = 0; i < fieldRow.size(); i++) {
var cell = fieldRow.get(i);
if (Objects.isNull(cell)) {
continue;
}
var name = cell.getName();
if (StringUtils.isEmpty(name)) {
continue;
}
var previousValue = cellFieldMap.put(name, i);
if (Objects.nonNull(previousValue)) {
throw new RunException("资源[class:{}]的Excel文件出现重复的属性控制列[field:{}]", clazz.getSimpleName(), name);
}
}
var fieldList = Arrays.stream(clazz.getDeclaredFields())
.filter(it -> !Modifier.isTransient(it.getModifiers()))
.filter(it -> !Modifier.isStatic(it.getModifiers()))
.collect(Collectors.toList());
for (var field : fieldList) {
if (!cellFieldMap.containsKey(field.getName())) {
throw new RunException("资源类[class:{}]的声明属性[filed:{}]无法获取,请检查配置表的格式", clazz, field.getName());
}
if (field.isAnnotationPresent(Id.class)) {
var cellIndex = cellFieldMap.get(field.getName());
if (cellIndex != 0) {
throw new RunException("资源类[class:{}]的主键[Id:{}]必须放在Excel配置表的第一列,请检查配置表的格式", clazz, field.getName());
}
}
if (Modifier.isPublic(field.getModifiers())) {
throw new RunException("因为静态资源类是不能被修改的,所以资源类[class:{}]的属性[filed:{}]不能被public修饰,请改为private修饰", 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方法[{}]", clazz, field.getName(), setMethodName);
}
}
return fieldList.stream().map(it -> new FieldInfo(cellFieldMap.get(it.getName()), it)).collect(Collectors.toList());
}
private String readTxt(InputStream input, Class<?> clazz) {
try {
return IOUtils.toString(input, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RunException("静态资源[{}]异常,无法读取文件", clazz.getSimpleName());
}
}
private static class FieldInfo {
public final int index;
public final Field field;
public FieldInfo(int index, Field field) {
this.index = index;
this.field = field;
}
}
}
@@ -7,11 +7,11 @@ import java.util.List;
* 配置文件资源
*
*/
public class JsonResource {
public class ResourceConfig {
// 文件名
private String name;
//配置表字段名
private List<ColumnMeta> columns = new ArrayList<>();
private List<Header> header = new ArrayList<>();
// 配置表数据
private List<List<String>> data = new ArrayList<>();
@@ -23,12 +23,12 @@ public class JsonResource {
this.name = name;
}
public List<ColumnMeta> getColumns() {
return columns;
public List<Header> getHeader() {
return header;
}
public void setColumns(List<ColumnMeta> columns) {
this.columns = columns;
public void setHeader(List<Header> header) {
this.header = header;
}
public List<List<String>> getData() {
@@ -39,7 +39,7 @@ public class JsonResource {
this.data = data;
}
public static class ColumnMeta {
public static class Header {
//字段名
private String name;
//类型
@@ -47,10 +47,10 @@ public class JsonResource {
//
private int index;
public ColumnMeta() {
public Header() {
}
public ColumnMeta(String name, String type, int index) {
public Header(String name, String type, int index) {
this.name = name;
this.type = type;
this.index = index;
@@ -14,12 +14,15 @@
package com.zfoo.storage.interpreter;
import com.zfoo.protocol.exception.RunException;
import com.zfoo.protocol.util.JsonUtils;
import com.zfoo.protocol.util.ReflectionUtils;
import com.zfoo.protocol.util.StringUtils;
import com.zfoo.storage.interpreter.ResourceConfig.Header;
import com.zfoo.storage.model.anno.Id;
import com.zfoo.storage.strategy.*;
import com.zfoo.storage.util.CellUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
@@ -30,6 +33,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
@@ -37,7 +41,7 @@ import java.util.stream.Collectors;
* @author jaysunxiao
* @version 3.0
*/
public class ExcelResourceReader implements IResourceReader {
public class ResourceReader implements IResourceReader {
private static final TypeDescriptor TYPE_DESCRIPTOR = TypeDescriptor.valueOf(String.class);
@@ -56,33 +60,27 @@ public class ExcelResourceReader implements IResourceReader {
}
@Override
public <T> List<T> read(InputStream inputStream, Class<T> clazz) {
var wb = createWorkbook(inputStream, clazz);
public <T> List<T> read(InputStream inputStream, Class<T> clazz, String suffix) {
ResourceConfig resource = null;
if (suffix.equals("txt")) {
resource = readJson(inputStream, clazz.getSimpleName());
} else {
resource = readExcel(inputStream, clazz.getSimpleName());
}
var result = new ArrayList<T>();
//获取所有字段
var cellFieldMap = getFieldMap(resource, clazz);
var fieldInfos = getFieldInfos(cellFieldMap, clazz);
// 默认取到第一个sheet页
var sheet = wb.getSheetAt(0);
var fieldInfos = getFieldInfos(sheet, clazz);
var iterator = sheet.iterator();
// 行数定位到有效数据行默认是第四行为有效数据行
iterator.next();
iterator.next();
iterator.next();
var iterator = resource.getData().iterator();
// 从ROW_SERVER这行开始读取数据
while (iterator.hasNext()) {
var row = iterator.next();
var instance = ReflectionUtils.newInstance(clazz);
var idCell = row.getCell(0);
if (StringUtils.isBlank(CellUtils.getCellStringValue(idCell))) {
continue;
}
for (var fieldInfo : fieldInfos) {
var cell = row.getCell(fieldInfo.index);
var content = CellUtils.getCellStringValue(cell);
var content = row.get(fieldInfo.index);
if (StringUtils.isNotEmpty(content) || fieldInfo.field.getType() == String.class) {
inject(instance, fieldInfo.field, content);
}
@@ -91,7 +89,81 @@ public class ExcelResourceReader implements IResourceReader {
}
return result;
}
public ResourceConfig readExcel(InputStream inputStream, String name) {
var wb = createWorkbook(inputStream, name);
var resource = new ResourceConfig();
resource.setName(name);
// 默认取到第一个sheet页
var sheet = wb.getSheetAt(0);
//设置所有列
var headers = getHeaders(sheet, name);
resource.setHeader(headers);
// 行数定位到有效数据行默认是第四行为有效数据行
var iterator = sheet.iterator();
iterator.next();
iterator.next();
iterator.next();
// 从ROW_SERVER这行开始读取数据
List<List<String>> data = new ArrayList<>();
while (iterator.hasNext()) {
var row = iterator.next();
List<String> rowData = new ArrayList<>();
for (var header : headers) {
var cell = row.getCell(header.getIndex());
var content = CellUtils.getCellStringValue(cell);
rowData.add(content);
}
data.add(rowData);
}
resource.setData(data);
return resource;
}
// 只读取代码里写的字段
private List<Header> getHeaders(Sheet sheet, String fileName) {
var iterator = sheet.iterator();
// 获取配置表的有效列名称默认第一行就是字段名称
var fieldRow = iterator.next();
if (fieldRow == null) {
throw new RunException("无法获取资源[class:{}]的Excel文件的属性控制列", fileName);
}
//默认第二行字段类型
var typeRow = iterator.next();
if (typeRow == null) {
throw new RunException("无法获取资源[class:{}]的Excel文件的类型控制列", fileName);
}
var headerList = new ArrayList<Header>();
var cellFieldMap = new HashMap<String, Integer>();
for (var i = 0; i < fieldRow.getLastCellNum(); i++) {
var fieldCell = fieldRow.getCell(i);
if (Objects.isNull(fieldCell)) {
continue;
}
var typeCell = typeRow.getCell(i);
if (Objects.isNull(typeCell)) {
continue;
}
var fieldName = CellUtils.getCellStringValue(fieldCell);
if (StringUtils.isEmpty(fieldName)) {
continue;
}
var typeName = CellUtils.getCellStringValue(typeCell);
if (StringUtils.isEmpty(typeName)) {
continue;
}
var previousValue = cellFieldMap.put(fieldName, i);
if (Objects.nonNull(previousValue)) {
throw new RunException("资源[class:{}]的Excel文件出现重复的属性控制列[field:{}]", fileName, fieldName);
}
headerList.add(new Header(fieldName, typeName, i));
}
return headerList;
}
private void inject(Object instance, Field field, String content) {
try {
var targetType = new TypeDescriptor(field);
@@ -103,43 +175,20 @@ public class ExcelResourceReader implements IResourceReader {
}
}
// 只读取代码里写的字段
private Collection<FieldInfo> getFieldInfos(Sheet sheet, Class<?> clazz) {
var fieldRow = getFieldRow(sheet);
if (fieldRow == null) {
throw new RunException("无法获取资源[class:{}]的Excel文件的属性控制列", clazz.getSimpleName());
}
var cellFieldMap = new HashMap<String, Integer>();
for (var i = 0; i < fieldRow.getLastCellNum(); i++) {
var cell = fieldRow.getCell(i);
if (Objects.isNull(cell)) {
continue;
}
var name = CellUtils.getCellStringValue(cell);
if (StringUtils.isEmpty(name)) {
continue;
}
var previousValue = cellFieldMap.put(name, i);
if (Objects.nonNull(previousValue)) {
throw new RunException("资源[class:{}]的Excel文件出现重复的属性控制列[field:{}]", clazz.getSimpleName(), name);
}
}
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());
for (var field : fieldList) {
if (!cellFieldMap.containsKey(field.getName())) {
if (!fieldMap.containsKey(field.getName())) {
throw new RunException("资源类[class:{}]的声明属性[filed:{}]无法获取,请检查配置表的格式", clazz, field.getName());
}
if (field.isAnnotationPresent(Id.class)) {
var cellIndex = cellFieldMap.get(field.getName());
var cellIndex = fieldMap.get(field.getName());
if (cellIndex != 0) {
throw new RunException("资源类[class:{}]的主键[Id:{}]必须放在Excel配置表的第一列,请检查配置表的格式", clazz, field.getName());
}
@@ -160,27 +209,17 @@ public class ExcelResourceReader implements IResourceReader {
}
}
return fieldList.stream().map(it -> new FieldInfo(cellFieldMap.get(it.getName()), it)).collect(Collectors.toList());
return fieldList.stream().map(it -> new FieldInfo(fieldMap.get(it.getName()), it)).collect(Collectors.toList());
}
// 获取配置表的有效列名称默认第一行就是字段名称
private Row getFieldRow(Sheet sheet) {
var iterator = sheet.iterator();
var row = iterator.next();
return row;
}
private Workbook createWorkbook(InputStream input, Class<?> clazz) {
private Workbook createWorkbook(InputStream input, String name) {
try {
return WorkbookFactory.create(input);
} catch (IOException e) {
throw new RunException("静态资源[{}]异常,无法读取文件", clazz.getSimpleName());
throw new RunException("静态资源[{}]异常,无法读取文件", name);
}
}
private static class FieldInfo {
public final int index;
public final Field field;
@@ -190,4 +229,39 @@ public class ExcelResourceReader implements IResourceReader {
this.field = field;
}
}
public Map<String, Integer> getFieldMap(ResourceConfig resource, Class<?> clazz) {
var header = resource.getHeader();
if (header == null) {
throw new RunException("无法获取资源[class:{}]的Excel文件的属性控制列", clazz.getSimpleName());
}
var cellFieldMap = new HashMap<String, Integer>();
for (var i = 0; i < header.size(); i++) {
var cell = header.get(i);
if (Objects.isNull(cell)) {
continue;
}
var name = cell.getName();
if (StringUtils.isEmpty(name)) {
continue;
}
var previousValue = cellFieldMap.put(name, i);
if (Objects.nonNull(previousValue)) {
throw new RunException("资源[class:{}]的Excel文件出现重复的属性控制列[field:{}]", clazz.getSimpleName(), name);
}
}
return cellFieldMap;
}
private ResourceConfig readJson(InputStream input, String name) {
try {
var jsonStr = IOUtils.toString(input, StandardCharsets.UTF_8);
//将json字符转换成对象
return JsonUtils.string2Object(jsonStr, ResourceConfig.class);
} catch (IOException e) {
throw new RunException("静态资源[{}]异常,无法读取文件", name);
}
}
}
@@ -16,6 +16,7 @@ package com.zfoo.storage.manager;
import com.zfoo.protocol.collection.CollectionUtils;
import com.zfoo.protocol.exception.ExceptionUtils;
import com.zfoo.protocol.exception.RunException;
import com.zfoo.protocol.util.FileUtils;
import com.zfoo.protocol.util.ReflectionUtils;
import com.zfoo.protocol.util.StringUtils;
import com.zfoo.storage.StorageContext;
@@ -98,8 +99,10 @@ public class StorageManager implements IStorageManager {
try {
for (var definition : resourceDefinitionMap.values()) {
var clazz = definition.getClazz();
var resource = definition.getResource();
var fileExtName = FileUtils.fileExtName(resource.getFilename());
Storage<?, ?> storage = new Storage<>();
storage.init(definition.getResource().getInputStream(), definition.getClazz());
storage.init(resource.getInputStream(), definition.getClazz(), fileExtName);
storageMap.putIfAbsent(clazz, storage);
allStorageUsableMap.put(clazz, false);
}
@@ -224,7 +227,7 @@ public class StorageManager implements IStorageManager {
try {
var resourceList = new ArrayList<Resource>();
var packageSearchPath = StringUtils.format("{}/**/{}.{}", storageConfig.getResourceLocation(), clazz.getSimpleName(), storageConfig.getResourceSuffix());
var packageSearchPath = StringUtils.format("{}/**/{}.*", storageConfig.getResourceLocation(), clazz.getSimpleName());
packageSearchPath = packageSearchPath.replaceAll("//", "/");
try {
resourceList.addAll(Arrays.asList(resourcePatternResolver.getResources(packageSearchPath)));
@@ -234,7 +237,7 @@ public class StorageManager implements IStorageManager {
// 通配符无法匹配根目录,所以如果找不到,再从根目录查找一遍
if (CollectionUtils.isEmpty(resourceList)) {
packageSearchPath = StringUtils.format("{}/{}.{}", storageConfig.getResourceLocation(), clazz.getSimpleName(), storageConfig.getResourceSuffix());
packageSearchPath = StringUtils.format("{}/{}.*", storageConfig.getResourceLocation(), clazz.getSimpleName());
packageSearchPath = packageSearchPath.replaceAll("//", "/");
resourceList.addAll(Arrays.asList(resourcePatternResolver.getResources(packageSearchPath)));
}
@@ -25,8 +25,6 @@ public class StorageConfig {
private String resourceLocation;
private String resourceSuffix;
public String getId() {
return id;
}
@@ -50,12 +48,4 @@ public class StorageConfig {
public void setResourceLocation(String resourceLocation) {
this.resourceLocation = resourceLocation;
}
public String getResourceSuffix() {
return resourceSuffix;
}
public void setResourceSuffix(String resourceSuffix) {
this.resourceSuffix = resourceSuffix;
}
}
@@ -44,14 +44,14 @@ public class Storage<K, V> {
public Storage() {
}
public void init(InputStream inputStream, Class<?> resourceClazz) {
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);
var list = reader.read(inputStream, resourceClazz, suffix);
dataMap.clear();
indexMap.clear();
@@ -16,8 +16,7 @@ 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.ExcelResourceReader;
import com.zfoo.storage.interpreter.JsonResourceReader;
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;
@@ -70,20 +69,9 @@ public class StorageDefinitionParser implements BeanDefinitionParser {
resolvePlaceholder("id", "id", builder, element, parserContext);
resolvePlaceholder("package", "scanPackage", builder, scanElement, parserContext);
resolvePlaceholder("location", "resourceLocation", builder, resourceElement, parserContext);
resolvePlaceholder("suffix", "resourceSuffix", builder, resourceElement, parserContext);
parserContext.getRegistry().registerBeanDefinition(clazz.getCanonicalName(), builder.getBeanDefinition());
// 注册ExcelResourceReader
Class<?> readerClazz = ExcelResourceReader.class;
var resourceSuffix = resourceElement.getAttribute("suffix");
if (resourceSuffix.equals("txt")) {
readerClazz = JsonResourceReader.class;
}
var readerName = StringUtils.uncapitalize(readerClazz.getName());
builder = BeanDefinitionBuilder.rootBeanDefinition(readerClazz);
parserContext.getRegistry().registerBeanDefinition(readerName, builder.getBeanDefinition());
}
private void registerBeanDefinition(ParserContext parserContext) {
@@ -99,11 +87,11 @@ public class StorageDefinitionParser implements BeanDefinitionParser {
builder = BeanDefinitionBuilder.rootBeanDefinition(clazz);
registry.registerBeanDefinition(name, builder.getBeanDefinition());
// 注册ExcelResourceReader
// clazz = ExcelResourceReader.class;
// 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) {
@@ -16,8 +16,8 @@ package com.zfoo.storage.util;
import com.zfoo.protocol.exception.RunException;
import com.zfoo.protocol.util.JsonUtils;
import com.zfoo.protocol.util.StringUtils;
import com.zfoo.storage.interpreter.JsonResource;
import com.zfoo.storage.interpreter.JsonResource.ColumnMeta;
import com.zfoo.storage.interpreter.ResourceConfig;
import com.zfoo.storage.interpreter.ResourceConfig.Header;
import java.io.File;
import java.io.IOException;
@@ -34,15 +34,13 @@ import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
/**
* @author jaysunxiao
* @author meiwei666
* @version 3.0
*/
public class ExcelToJsonUtils {
public static void main(String[] args) throws Exception{
File inputDir = new File("E:\\workspace\\zfoo\\storage\\src\\test\\resources\\excel");
String outputDir = "E:\\workspace\\zfoo\\storage\\src\\test\\resources\\excel";
var listFiles = FileUtils.listFiles(inputDir, new String[] { "xls", "xlsx"}, true);
public static void excelConvertJson(String inputDir, String outputDir) throws Exception{
var listFiles = FileUtils.listFiles(new File(inputDir), new String[] { "xls", "xlsx"}, true);
for (var file : listFiles) {
var fileName = getFileName(file);
var inputStream = FileUtils.openInputStream(file);
@@ -51,7 +49,7 @@ public class ExcelToJsonUtils {
}
}
public static void writeJsonFile(String outDir, String jsonStr, String name) {
private static void writeJsonFile(String outDir, String jsonStr, String name) {
System.out.println("resource: " + name + ".txt");
PrintWriter pw = null;
try {
@@ -79,13 +77,13 @@ public class ExcelToJsonUtils {
public static String read(InputStream inputStream, String fileName) {
var wb = createWorkbook(inputStream, fileName);
var resource = new JsonResource();
var resource = new ResourceConfig();
resource.setName(fileName);
// 默认取到第一个sheet页
var sheet = wb.getSheetAt(0);
//设置所有列
var columns = getColumnMetas(sheet, fileName);
resource.setColumns(columns);
var headers = getHeaders(sheet, fileName);
resource.setHeader(headers);
// 行数定位到有效数据行,默认是第四行为有效数据行
var iterator = sheet.iterator();
@@ -97,8 +95,8 @@ public class ExcelToJsonUtils {
while (iterator.hasNext()) {
var row = iterator.next();
List<String> rowData = new ArrayList<>();
for (var column : columns) {
var cell = row.getCell(column.getIndex());
for (var header : headers) {
var cell = row.getCell(header.getIndex());
var content = CellUtils.getCellStringValue(cell);
rowData.add(content);
}
@@ -109,7 +107,7 @@ public class ExcelToJsonUtils {
}
// 只读取代码里写的字段
private static List<ColumnMeta> getColumnMetas(Sheet sheet, String fileName) {
private static List<Header> getHeaders(Sheet sheet, String fileName) {
var iterator = sheet.iterator();
// 获取配置表的有效列名称,默认第一行就是字段名称
var fieldRow = iterator.next();
@@ -122,7 +120,7 @@ public class ExcelToJsonUtils {
throw new RunException("无法获取资源[class:{}]的Excel文件的类型控制列", fileName);
}
var columnMetaList = new ArrayList<ColumnMeta>();
var headerList = new ArrayList<Header>();
var cellFieldMap = new HashMap<String, Integer>();
for (var i = 0; i < fieldRow.getLastCellNum(); i++) {
var fieldCell = fieldRow.getCell(i);
@@ -145,9 +143,9 @@ public class ExcelToJsonUtils {
if (Objects.nonNull(previousValue)) {
throw new RunException("资源[class:{}]的Excel文件出现重复的属性控制列[field:{}]", fileName, fieldName);
}
columnMetaList.add(new ColumnMeta(fieldName, typeName, i));
headerList.add(new Header(fieldName, typeName, i));
}
return columnMetaList;
return headerList;
}
private static Workbook createWorkbook(InputStream input, String fileName) {
@@ -157,6 +155,5 @@ public class ExcelToJsonUtils {
throw new RunException("静态资源[{}]异常,无法读取文件", fileName);
}
}
}
@@ -45,8 +45,6 @@
<xsd:complexType name="resource">
<!-- 本地资源路径 -->
<xsd:attribute name="location" type="xsd:string" use="required"/>
<!-- 资源文件后缀 -->
<xsd:attribute name="suffix" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="configType">
@@ -45,35 +45,6 @@ public class ApplicationTest {
// Excel的映射内容需要在被Spring管理的bean的方法上加上@ResInjection注解,即可自动注入Excel对应的对象
// 参考StudentManager中的标准用法
var studentManager = context.getBean(StudentManager.class);
var studentResources = studentManager.studentResources;
// 类名称和Excel名称必须完全一致,Excel的列名称必须对应对象的属性名称
for (StudentResource resource : studentResources.getAll()) {
logger.info(JsonUtils.object2String(resource));
}
System.out.println(StringUtils.MULTIPLE_HYPHENS);
// 通过id找到对应的行
var id = 1000;
var valueById = studentResources.get(id);
logger.info(JsonUtils.object2String(valueById));
System.out.println(StringUtils.MULTIPLE_HYPHENS);
// 通过索引找对应的行
var valuesByIndex = studentResources.getIndex("name", "james0");
logger.info(JsonUtils.object2String(valuesByIndex));
}
@Test
public void startStorageTestTxt() {
// 加载配置文件,配置文件中必须引入storage
// 配置文件中scan,需要映射Excel的类所在位置,会自动搜索文件夹下的Excel文件,Excel文件可以放在指定文件夹的任意目录
// 配置文件中resource,需要映射Excel的文件所在位置
var context = new ClassPathXmlApplicationContext("application.xml");
// Excel的映射内容需要在被Spring管理的bean的方法上加上@ResInjection注解,即可自动注入Excel对应的对象
// 参考StudentManager中的标准用法
var studentManager = context.getBean(StudentManager.class);
var studentResources = studentManager.studentResources;
// 类名称和Excel名称必须完全一致,Excel的列名称必须对应对象的属性名称
@@ -92,16 +63,6 @@ public class ApplicationTest {
// 通过索引找对应的行
var valuesByIndex = studentResources.getIndex("name", "james0");
logger.info(JsonUtils.object2String(valuesByIndex));
}
// storage教程
@Test
public void startStorageTestTxt2() {
// 加载配置文件,配置文件中必须引入storage
// 配置文件中scan,需要映射Excel的类所在位置,会自动搜索文件夹下的Excel文件,Excel文件可以放在指定文件夹的任意目录
// 配置文件中resource,需要映射Excel的文件所在位置
var context = new ClassPathXmlApplicationContext("application.xml");
// Excel的映射内容需要在被Spring管理的bean的方法上加上@ResInjection注解,即可自动注入Excel对应的对象
var testManager = context.getBean(TestManager.class);
@@ -112,9 +73,10 @@ public class ApplicationTest {
logger.info(JsonUtils.object2String(resource));
}
// 通过id找到对应的行
var id = 2;
var valueById = testResources.get(id);
logger.info(JsonUtils.object2String(valueById));
id = 2;
var resource = testResources.get(id);
logger.info(JsonUtils.object2String(resource));
System.out.println(StringUtils.MULTIPLE_HYPHENS);
}
}
@@ -24,7 +24,7 @@ import org.springframework.stereotype.Component;
* @author jaysunxiao
* @version 3.0
*/
//@Component
@Component
public class TestManager {
@ResInjection
@@ -13,6 +13,7 @@
package com.zfoo.storage.excel;
import com.zfoo.storage.util.ExcelToJsonUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
@@ -32,6 +33,13 @@ 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";
ExcelToJsonUtils.excelConvertJson(inputDir, outputDir);
}
@Test
public void createExcelTest() throws IOException {
//第一步创建workbook
@@ -24,7 +24,7 @@ import com.zfoo.storage.model.anno.Resource;
* @author jaysunxiao
* @version 3.0
*/
//@Resource
@Resource
public class TestResource {
@Id
+2 -3
View File
@@ -49,9 +49,8 @@
<storage:storage id="resourceManager">
<storage:scan package="com.zfoo.**.resource"/>
<!-- 如果是类路径一classpath开头,如果是其它目录则以file开头-->
<storage:resource location="classpath:/excel" suffix="txt"/>
<!--<storage:resource location="classpath:/excel" suffix="xlsx"/>-->
<!-- <storage:resource location="file:C:\Users\jaysunxiao\Desktop\excel" suffix="xlsx"/>-->
<storage:resource location="classpath:/excel"/>
<!-- <storage:resource location="file:C:\Users\jaysunxiao\Desktop\excel"/>-->
</storage:storage>
</beans>