diff --git a/protocol/src/main/java/com/zfoo/protocol/util/JsonUtils.java b/protocol/src/main/java/com/zfoo/protocol/util/JsonUtils.java index f9a1e6cb..3b1dfac3 100644 --- a/protocol/src/main/java/com/zfoo/protocol/util/JsonUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/util/JsonUtils.java @@ -59,7 +59,6 @@ public abstract class JsonUtils { DefaultPrettyPrinter prettyPrinter = (DefaultPrettyPrinter) MAPPER.getSerializationConfig().getDefaultPrettyPrinter(); DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(StringUtils.TAB_ASCII, FileUtils.LS); prettyPrinter.indentObjectsWith(indenter); - prettyPrinter.indentArraysWith(indenter); MAPPER_TURBO.setSerializationInclusion(JsonInclude.Include.NON_NULL); MAPPER_TURBO.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); diff --git a/storage/README.md b/storage/README.md index 1b463fe6..8755a7b4 100644 --- a/storage/README.md +++ b/storage/README.md @@ -5,6 +5,8 @@ - 利用Java动态语言的反射特性,用最少的代码去解析Excel +- 支持Excel导出Json文件 + ### Ⅱ. 自动映射 - Excel的第一行对应Java类属性,第二行和第三行不会起到注释的作用,其中第一列必须是Id属性 @@ -16,7 +18,7 @@ ![Image text](../doc/image/storage/storage02.png) - 解析过后有两种使用方式 - 1. 通过注解 + 1. 通过注解 ``` @Component public class StudentManager { @@ -26,7 +28,7 @@ } ``` - 2. 通过类动态获取 + 2. 通过类动态获取 ``` Storage studentResources = (Storage) StorageContext.getStorageManager().getStorage(StudentResource.class); ``` @@ -45,10 +47,10 @@ var students = studentResources.getIndex("name", "james0"); - 唯一索引通过Storage.getUniqueIndex()获取,需要把索引注解标注为@Index(unique = true) -### Ⅲ. 热更新Excel +### Ⅲ. 热更新Excel/Json - [tank](https://github.com/zfoo-project/tank-game-server/blob/main/common/src/main/java/com/zfoo/tank/common/util/HotUtils.java) - 分布式热更新Excel配置文件实现 + 分布式热更新Excel/Json配置文件实现 ### Ⅳ. 用途 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 0b62bad6..ec40432a 100644 --- a/storage/src/main/java/com/zfoo/storage/interpreter/ResourceReader.java +++ b/storage/src/main/java/com/zfoo/storage/interpreter/ResourceReader.java @@ -76,11 +76,11 @@ public class ResourceReader implements IResourceReader { var iterator = resource.getRows().iterator(); // 从ROW_SERVER这行开始读取数据 while (iterator.hasNext()) { - var row = iterator.next(); + var columns = iterator.next().getColumns(); var instance = ReflectionUtils.newInstance(clazz); for (var fieldInfo : fieldInfos) { - var content = row.get(fieldInfo.index); + var content = columns.get(fieldInfo.index); if (StringUtils.isNotEmpty(content) || fieldInfo.field.getType() == String.class) { inject(instance, fieldInfo.field, content); } 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 14c8908b..3b1fdb11 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,7 +27,15 @@ 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) { + var resourceData = new ResourceData(); + resourceData.name = name; + resourceData.headers = headers; + resourceData.rows = rows; + return resourceData; + } public String getName() { return name; @@ -45,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 39947d0b..53e34e44 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 @@ -13,6 +13,7 @@ package com.zfoo.storage.model.resource; import com.zfoo.protocol.util.AssertionUtils; +import com.zfoo.protocol.util.StringUtils; import org.springframework.lang.Nullable; import java.util.HashMap; @@ -58,6 +59,15 @@ public enum ResourceEnum { return typeMap.containsKey(type); } + public static boolean isExcel(String type) { + var resourceEnum = getResourceEnumByType(type); + return resourceEnum == ResourceEnum.EXCEL_XLS || resourceEnum == ResourceEnum.EXCEL_XLSX; + } + + public static String typesToString() { + return StringUtils.joinWith(StringUtils.SPACE, typeMap.values().toArray()); + } + public String getType() { return type; } diff --git a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceHeader.java b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceHeader.java index 9ca387aa..89f0627a 100644 --- a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceHeader.java +++ b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceHeader.java @@ -25,13 +25,12 @@ public class ResourceHeader { //列 private int index; - public ResourceHeader() { - } - - public ResourceHeader(String name, String type, int index) { - this.name = name; - this.type = type; - this.index = index; + public static ResourceHeader valueOf(String name, String type, int index) { + var resourceHeader = new ResourceHeader(); + resourceHeader.name = name; + resourceHeader.type = type; + resourceHeader.index = index; + return resourceHeader; } public String getName() { 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 new file mode 100644 index 00000000..764661dc --- /dev/null +++ b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceRow.java @@ -0,0 +1,51 @@ +/* + * 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/ExcelToJsonUtils.java b/storage/src/main/java/com/zfoo/storage/util/ExcelToJsonUtils.java index 2274e404..dab02835 100644 --- a/storage/src/main/java/com/zfoo/storage/util/ExcelToJsonUtils.java +++ b/storage/src/main/java/com/zfoo/storage/util/ExcelToJsonUtils.java @@ -20,6 +20,7 @@ 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; @@ -42,27 +43,28 @@ public class ExcelToJsonUtils { public static void excelConvertJson(String inputDir, String outputDir) throws IOException { var listFiles = FileUtils.getAllReadableFiles(new File(inputDir)) .stream() - .filter(it -> ResourceEnum.containsResourceEnum(FileUtils.fileExtName(it.getName()))) + .filter(it -> ResourceEnum.isExcel(FileUtils.fileExtName(it.getName()))) .collect(Collectors.toList()); for (var file : listFiles) { - var fileName = StringUtils.format("{}.json", FileUtils.fileSimpleName(file.getName())); + var fileSimpleName = FileUtils.fileSimpleName(file.getName()); + var jsonFileName = StringUtils.format("{}.json", fileSimpleName); var inputStream = FileUtils.openInputStream(file); - var resourceData = readResourceDataFromExcel(inputStream, fileName); - FileUtils.writeStringToFile(new File(FileUtils.joinPath(outputDir, fileName)), JsonUtils.object2StringPrettyPrinter(resourceData)); + var resourceData = readResourceDataFromExcel(inputStream, file.getName()); + + var outputFilePath = FileUtils.joinPath(outputDir, jsonFileName); + FileUtils.deleteFile(new File(outputFilePath)); + FileUtils.writeStringToFile(new File(outputFilePath), JsonUtils.object2StringPrettyPrinter(resourceData)); } } public static ResourceData readResourceDataFromExcel(InputStream inputStream, String fileName) { // 只读取代码里写的字段 var wb = createWorkbook(inputStream, fileName); - var resource = new ResourceData(); - resource.setName(fileName); // 默认取到第一个sheet页 var sheet = wb.getSheetAt(0); //设置所有列 var headers = getHeaders(sheet, fileName); - resource.setHeaders(headers); // 行数定位到有效数据行,默认是第四行为有效数据行 var iterator = sheet.iterator(); @@ -70,19 +72,18 @@ public class ExcelToJsonUtils { iterator.next(); iterator.next(); // 从ROW_SERVER这行开始读取数据 - List> data = new ArrayList<>(); + List rows = new ArrayList<>(); while (iterator.hasNext()) { var row = iterator.next(); - List rowData = new ArrayList<>(); + var columns = new ArrayList(); for (var header : headers) { var cell = row.getCell(header.getIndex()); var content = CellUtils.getCellStringValue(cell); - rowData.add(content); + columns.add(content); } - data.add(rowData); + rows.add(ResourceRow.valueOf(row.getRowNum() + 1, columns)); } - resource.setRows(data); - return resource; + return ResourceData.valueOf(fileName, headers, rows); } // 只读取代码里写的字段 @@ -122,7 +123,7 @@ public class ExcelToJsonUtils { if (Objects.nonNull(previousValue)) { throw new RunException("资源[class:{}]的Excel文件出现重复的属性控制列[field:{}]", fileName, fieldName); } - headerList.add(new ResourceHeader(fieldName, typeName, i)); + headerList.add(ResourceHeader.valueOf(fieldName, typeName, i)); } return headerList; }