diff --git a/storage/pom.xml b/storage/pom.xml
index 9b0dad2b..bd710ade 100644
--- a/storage/pom.xml
+++ b/storage/pom.xml
@@ -57,6 +57,7 @@
1.2.51
4.1.2
+ 1.9.0
3.27.0-GA
1.10.22
@@ -150,6 +151,11 @@
poi-ooxml
${poi.version}
+
+ org.apache.commons
+ commons-csv
+ ${csv.version}
+
diff --git a/storage/src/main/java/com/zfoo/storage/interpreter/ResourceReader.java b/storage/src/main/java/com/zfoo/storage/interpreter/ResourceReader.java
index ec40432a..d8627393 100644
--- a/storage/src/main/java/com/zfoo/storage/interpreter/ResourceReader.java
+++ b/storage/src/main/java/com/zfoo/storage/interpreter/ResourceReader.java
@@ -21,7 +21,8 @@ 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.ExcelToJsonUtils;
+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;
@@ -63,7 +64,9 @@ public class ResourceReader implements IResourceReader {
if (resourceEnum == ResourceEnum.JSON) {
resource = JsonUtils.string2Object(StringUtils.bytesToString(IOUtils.toByteArray(inputStream)), ResourceData.class);
} else if (resourceEnum == ResourceEnum.EXCEL_XLS || resourceEnum == ResourceEnum.EXCEL_XLSX) {
- resource = ExcelToJsonUtils.readResourceDataFromExcel(inputStream, clazz.getSimpleName());
+ resource = ExcelReaderUtils.readResourceDataFromExcel(inputStream, clazz.getSimpleName());
+ } else if (resourceEnum == ResourceEnum.CSV) {
+ resource = CsvReaderUtils.readResourceDataFromCSV(inputStream, clazz.getSimpleName());
} else {
throw new RunException("不支持文件[{}]的配置类型[{}]", clazz.getSimpleName(), suffix);
}
@@ -76,7 +79,7 @@ public class ResourceReader implements IResourceReader {
var iterator = resource.getRows().iterator();
// 从ROW_SERVER这行开始读取数据
while (iterator.hasNext()) {
- var columns = iterator.next().getColumns();
+ var columns = iterator.next();
var instance = ReflectionUtils.newInstance(clazz);
for (var fieldInfo : fieldInfos) {
diff --git a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceData.java b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceData.java
index 3b1fdb11..23d683bc 100644
--- a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceData.java
+++ b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceData.java
@@ -27,9 +27,9 @@ public class ResourceData {
// 配置表字段名
private List headers = new ArrayList<>();
// 配置表数据
- private List rows = new ArrayList<>();
+ private List> rows = new ArrayList<>();
- public static ResourceData valueOf(String name, List headers, List rows) {
+ public static ResourceData valueOf(String name, List headers, List> rows) {
var resourceData = new ResourceData();
resourceData.name = name;
resourceData.headers = headers;
@@ -53,11 +53,11 @@ public class ResourceData {
this.headers = headers;
}
- public List getRows() {
+ public List> getRows() {
return rows;
}
- public void setRows(List rows) {
+ public void setRows(List> rows) {
this.rows = rows;
}
diff --git a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceEnum.java b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceEnum.java
index 53e34e44..e203b875 100644
--- a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceEnum.java
+++ b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceEnum.java
@@ -33,6 +33,8 @@ public enum ResourceEnum {
JSON("json"),
+ CSV("csv"),
+
;
private static Map typeMap = new HashMap<>();
diff --git a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceRow.java b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceRow.java
deleted file mode 100644
index 764661dc..00000000
--- a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceRow.java
+++ /dev/null
@@ -1,51 +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.storage.model.resource;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author godotg
- * @version 4.0
- */
-public class ResourceRow {
-
- private int row;
-
- private List columns = new ArrayList<>();
-
- public static ResourceRow valueOf(int row, List columns) {
- var resourceRow = new ResourceRow();
- resourceRow.row = row;
- resourceRow.columns = columns;
- return resourceRow;
- }
-
- public int getRow() {
- return row;
- }
-
- public void setRow(int row) {
- this.row = row;
- }
-
- public List getColumns() {
- return columns;
- }
-
- public void setColumns(List columns) {
- this.columns = columns;
- }
-
-}
diff --git a/storage/src/main/java/com/zfoo/storage/util/CsvReaderUtils.java b/storage/src/main/java/com/zfoo/storage/util/CsvReaderUtils.java
new file mode 100644
index 00000000..f27dde9f
--- /dev/null
+++ b/storage/src/main/java/com/zfoo/storage/util/CsvReaderUtils.java
@@ -0,0 +1,97 @@
+/*
+ * 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.StringUtils;
+import com.zfoo.storage.model.resource.ResourceData;
+import com.zfoo.storage.model.resource.ResourceHeader;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVParser;
+import org.apache.commons.csv.CSVRecord;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.*;
+
+/**
+ * @author meiwei666
+ * @version 4.0
+ */
+public class CsvReaderUtils {
+
+ /**
+ * 构建配置表消息头
+ * @param iterator
+ * @param fileName
+ * @return
+ */
+ private static List getHeaders(Iterator iterator, String fileName) {
+ // 获取配置表的有效列名称,默认第一行就是字段名称
+ 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 descRow = iterator.next();
+
+ List headers = new ArrayList<>();
+ for (int i = 0; i < fieldRow.size(); i++) {
+ String fieldName = fieldRow.get(i);
+ if (fieldName == null) {
+ throw new RunException("{}列名不能为空,第{}列没有配置名字", fileName ,i + 1);
+ }
+ String filedType = typeRow.get(i);
+ if (filedType == null) {
+ throw new RunException("{}列类型不能为空,第{}列没有配置类型", fileName ,i + 1);
+ }
+// String desc = descRecord.get(i);
+ headers.add(ResourceHeader.valueOf(fieldName, filedType, i ));
+ }
+ return headers;
+ }
+
+ public static ResourceData readResourceDataFromCSV(InputStream input, String fileName){
+ CSVParser records = parseCsv(input, fileName);
+ Iterator iter = records.iterator();
+ List headers = getHeaders(iter, fileName);
+ List> rows = new ArrayList<>();
+ while (iter.hasNext()) {
+ CSVRecord record = iter.next();
+ List data = new ArrayList<>();
+ for (ResourceHeader header : headers) {
+ String value = record.get(header.getIndex());
+ if (StringUtils.isBlank(value)) {
+ value = StringUtils.EMPTY;
+ }
+ data.add(value);
+ }
+ rows.add(data);
+ }
+ return ResourceData.valueOf(fileName, headers, rows);
+ }
+
+ private static CSVParser parseCsv(InputStream input, String fileName) {
+ try {
+ return CSVFormat.EXCEL.parse(new InputStreamReader(input));
+ } catch (IOException e) {
+ throw new RunException("静态资源[{}]异常,无法读取文件", fileName);
+ }
+ }
+}
diff --git a/storage/src/main/java/com/zfoo/storage/util/ExcelToJsonUtils.java b/storage/src/main/java/com/zfoo/storage/util/ExcelReaderUtils.java
similarity index 86%
rename from storage/src/main/java/com/zfoo/storage/util/ExcelToJsonUtils.java
rename to storage/src/main/java/com/zfoo/storage/util/ExcelReaderUtils.java
index b5bcad67..41f70769 100644
--- a/storage/src/main/java/com/zfoo/storage/util/ExcelToJsonUtils.java
+++ b/storage/src/main/java/com/zfoo/storage/util/ExcelReaderUtils.java
@@ -20,25 +20,19 @@ 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.model.resource.ResourceRow;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.usermodel.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
import java.util.stream.Collectors;
/**
* @author meiwei666
* @version 4.0
*/
-public class ExcelToJsonUtils {
+public class ExcelReaderUtils {
public static void excelConvertJson(String inputDir, String outputDir) throws IOException {
var listFiles = FileUtils.getAllReadableFiles(new File(inputDir))
@@ -54,7 +48,7 @@ public class ExcelToJsonUtils {
var outputFilePath = FileUtils.joinPath(outputDir, jsonFileName);
FileUtils.deleteFile(new File(outputFilePath));
- FileUtils.writeStringToFile(new File(outputFilePath), JsonUtils.object2StringPrettyPrinter(resourceData), true);
+ FileUtils.writeStringToFile(new File(outputFilePath), JsonUtils.object2String(resourceData), true);
}
}
@@ -63,16 +57,17 @@ public class ExcelToJsonUtils {
var wb = createWorkbook(inputStream, fileName);
// 默认取到第一个sheet页
var sheet = wb.getSheetAt(0);
+ var iterator = sheet.iterator();
//设置所有列
- var headers = getHeaders(sheet, fileName);
+ var headers = getHeaders(iterator, fileName);
// 行数定位到有效数据行,默认是第四行为有效数据行
- var iterator = sheet.iterator();
- iterator.next();
- iterator.next();
- iterator.next();
+// var iterator = sheet.iterator();
+// iterator.next();
+// iterator.next();
+// iterator.next();
// 从ROW_SERVER这行开始读取数据
- List rows = new ArrayList<>();
+ List> rows = new ArrayList<>();
while (iterator.hasNext()) {
var row = iterator.next();
@@ -87,14 +82,14 @@ public class ExcelToJsonUtils {
var content = CellUtils.getCellStringValue(cell);
columns.add(content);
}
- rows.add(ResourceRow.valueOf(row.getRowNum() + 1, columns));
+ rows.add(columns);
}
return ResourceData.valueOf(fileName, headers, rows);
}
// 只读取代码里写的字段
- private static List getHeaders(Sheet sheet, String fileName) {
- var iterator = sheet.iterator();
+ private static List getHeaders(Iterator iterator, String fileName) {
+// var iterator = sheet.iterator();
// 获取配置表的有效列名称,默认第一行就是字段名称
var fieldRow = iterator.next();
if (fieldRow == null) {
@@ -105,7 +100,7 @@ public class ExcelToJsonUtils {
if (typeRow == null) {
throw new RunException("无法获取资源[class:{}]的Excel文件的类型控制列", fileName);
}
-
+ var desRow = iterator.next();
var headerList = new ArrayList();
var cellFieldMap = new HashMap();
for (var i = 0; i < fieldRow.getLastCellNum(); i++) {
diff --git a/storage/src/test/java/com/zfoo/storage/ApplicationTest.java b/storage/src/test/java/com/zfoo/storage/ApplicationTest.java
index 4250cdcf..c7ac921b 100644
--- a/storage/src/test/java/com/zfoo/storage/ApplicationTest.java
+++ b/storage/src/test/java/com/zfoo/storage/ApplicationTest.java
@@ -47,6 +47,7 @@ public class ApplicationTest {
var studentManager = context.getBean(StudentManager.class);
var studentResources = studentManager.studentResources;
+ var studentCsvResources = studentManager.studentCsvResources;
// 类名称和Excel名称必须完全一致,Excel的列名称必须对应对象的属性名称
// 类名称和Excel名称必须完全一致,Excel的列名称必须对应对象的属性名称
for (StudentResource resource : studentResources.getAll()) {
@@ -64,6 +65,10 @@ public class ApplicationTest {
var valuesByIndex = studentResources.getIndex("name", "james0");
logger.info(JsonUtils.object2String(valuesByIndex));
+ // 通过索引找对应的行
+ var csvValuesByIndex = studentCsvResources.getIndex("name", "james0");
+ logger.info(JsonUtils.object2String(csvValuesByIndex));
+
// Excel的映射内容需要在被Spring管理的bean的方法上加上@ResInjection注解,即可自动注入Excel对应的对象
var testManager = context.getBean(TestManager.class);
var testResources = testManager.testResources;
diff --git a/storage/src/test/java/com/zfoo/storage/StudentManager.java b/storage/src/test/java/com/zfoo/storage/StudentManager.java
index 06113f8b..ef07e04d 100644
--- a/storage/src/test/java/com/zfoo/storage/StudentManager.java
+++ b/storage/src/test/java/com/zfoo/storage/StudentManager.java
@@ -15,6 +15,7 @@ package com.zfoo.storage;
import com.zfoo.storage.model.anno.ResInjection;
import com.zfoo.storage.model.vo.Storage;
+import com.zfoo.storage.resource.StudentCsvResource;
import com.zfoo.storage.resource.StudentResource;
import org.springframework.stereotype.Component;
@@ -27,5 +28,7 @@ public class StudentManager {
@ResInjection
public Storage studentResources;
+ @ResInjection
+ public Storage studentCsvResources;
}
diff --git a/storage/src/test/java/com/zfoo/storage/excel/ExcelTest.java b/storage/src/test/java/com/zfoo/storage/excel/ExcelTest.java
index 46d84771..26780eba 100644
--- a/storage/src/test/java/com/zfoo/storage/excel/ExcelTest.java
+++ b/storage/src/test/java/com/zfoo/storage/excel/ExcelTest.java
@@ -13,7 +13,7 @@
package com.zfoo.storage.excel;
-import com.zfoo.storage.util.ExcelToJsonUtils;
+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;
@@ -37,7 +37,7 @@ public class ExcelTest {
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);
+ ExcelReaderUtils.excelConvertJson(inputDir, outputDir);
}
@Test
diff --git a/storage/src/test/java/com/zfoo/storage/resource/StudentCsvResource.java b/storage/src/test/java/com/zfoo/storage/resource/StudentCsvResource.java
new file mode 100644
index 00000000..eac5d698
--- /dev/null
+++ b/storage/src/test/java/com/zfoo/storage/resource/StudentCsvResource.java
@@ -0,0 +1,78 @@
+/*
+ * 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.resource;
+
+import com.zfoo.storage.model.anno.Id;
+import com.zfoo.storage.model.anno.Index;
+import com.zfoo.storage.model.anno.Resource;
+
+/**
+ * @author godotg
+ * @version 4.0
+ */
+@Resource
+public class StudentCsvResource {
+
+ @Id
+ private int id;
+
+ /**
+ * 索引,默认为可重复的索引
+ */
+ @Index
+ private String name;
+
+ private int age;
+ private float score;
+ private String[] courses;
+ private User[] users;
+ private User user;
+
+ /**
+ * 不想映射的字段必须加上transient关键字,这样就不会从Excel中去找对应的列
+ */
+ private transient String notMapContent;
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public float getScore() {
+ return score;
+ }
+
+ public String[] getCourses() {
+ return courses;
+ }
+
+ public User[] getUsers() {
+ return users;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public String getNotMapContent() {
+ return notMapContent;
+ }
+}
diff --git a/storage/src/test/resources/StudentResource.xlsx b/storage/src/test/resources/StudentResource.xlsx
deleted file mode 100644
index d7378b7a..00000000
Binary files a/storage/src/test/resources/StudentResource.xlsx and /dev/null differ
diff --git a/storage/src/test/resources/excel/StudentCsvResource.csv b/storage/src/test/resources/excel/StudentCsvResource.csv
new file mode 100644
index 00000000..116b2e8e
--- /dev/null
+++ b/storage/src/test/resources/excel/StudentCsvResource.csv
@@ -0,0 +1,7 @@
+id,name,age,score,courses,users,user
+string,string,int,float,array,array,string
+des,des,des,des,des,des,des
+1000,james0,10,60.8,"[""History"",""Chiness""]","[{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22},{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22}]","{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22}"
+1001,james1,10,70.1,"[""History"",""Chiness""]","[{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22},{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":23}]","{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22}"
+1002,james2,10,80.2,"[""History"",""Chiness""]","[{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22},{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":24}]","{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22}"
+1003,james3,10,59,"[""History"",""Chiness""]","[{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22},{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":25}]","{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22}"