1、概述
?實現用戶excel上傳、解析、對于用戶輸入的中文翻譯為字典碼或者id,實現用戶輸入的參數校驗,最后入庫。如果用戶輸入的參數有問題,返回校驗結果給前端。
excel解析使用My-Excel組件,校驗使用hibernate-validator,反向翻譯組件使用easy-trans。
2、maven
?不一定使用我指定的版本,也可以使用其他的替代組件,本文主要是給大家一個思路。
<!--請注意,如果用的新版本要用org.dromara的groupId untrans-driver需要和easy-trans主版本保持一致 -->
<dependency><groupId>com.fhs-opensource</groupId><artifactId>easy-trans-untrans-driver</artifactId><version>2.2.15</version>
</dependency><!--解析excel的插件,也可以使用easy-excel --><dependency><groupId>com.github.liaochong</groupId><artifactId>myexcel</artifactId><version>4.4.2</version></dependency><!--參數校驗插件 -->
<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>6.2.5.Final</version>
</dependency>
3、校驗插件代碼
?首先自定義2個分組,第一個分組是對用戶的必填和格式校驗,第二個分組是對用戶填寫的數據反向翻譯后,判斷是否正常的校驗(比如字典 有男女? 他給個TS肯定翻譯不到value,也要報錯)。
public class ValidationGroups {public ValidationGroups() {}/*** excel導入第一遍監察*/public @interface excelImportFirst {}/*** excel導入第二遍監察*/public @interface excelImportSecond {}}
接著自定義參數校驗工具類
public class ValidateUtil {private static final Validator validator =Validation.buildDefaultValidatorFactory().getValidator();/*** 通過組來校驗實體類*/public static <T> String validate(T t, Class<?>... groups) {Set<ConstraintViolation<T>> constraintViolations = validator.validate(t, groups);if (constraintViolations.size() > 0) {StringBuilder validateError = new StringBuilder();for (ConstraintViolation<T> constraintViolation : constraintViolations) {validateError.append(constraintViolation.getMessage()).append(";");}return validateError.toString();}return null;}/*** 通過組來校驗實體類*/public static <T> String validate(List<T> objs, Class<?>... groups) {StringBuilder validateError = new StringBuilder();boolean hasError = false;for (int i = 0; i < objs.size(); i++) {String result = validate(objs.get(i), groups);if(result!=null){validateError.append("第" + (i+1) + "行:" + result);hasError = true;}}return hasError ? validateError.toString() : null;}}
4、easy-trans的yml配置
主要配置上db-type? 支持mysql和postgresql
easy-trans:#啟用redis緩存 如果不用redis請設置為falseis-enable-redis: true#啟用全局翻譯(攔截所有responseBody進行自動翻譯),如果對于性能要求很高可關閉此配置is-enable-global: true#啟用平鋪模式is-enable-tile: true#字典緩存放到redis 微服務模式請開啟dict-use-redis: true #數據庫類型指定,反向翻譯使用 db-type: mysql
5、新增pojo,用于接收excel的數據
? 支持組合唯一鍵,比如? ?財務部的王磊? 財務部是org表的name? 王磊是user表的name。
?比如:下面類里面的 domainId
?支持字典反向翻譯,比如男女之類的 ,下面類里面的modelType
?當然也支持表里面的唯一鍵,比如身份證號碼,手機號等。下面類里面的layeringId
package com.xhb.data.center.dgp.api.excel;import com.fhs.core.trans.anno.UnTrans;
import com.fhs.core.trans.constant.UnTransType;
import com.github.liaochong.myexcel.core.annotation.ExcelColumn;
import com.xhb.data.center.api.validate.ValidationGroups;
import lombok.Data;
import org.hibernate.validator.constraints.Length;import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;/*** 模型表excel導入POJO*/
@Data
public class ModelingLogicalTableImport {@NotBlank(message = "業務主題名稱不能為空",groups = {ValidationGroups.excelImportFirst.class})@ExcelColumn(title = "主題域(*)")private String subjectName;@NotBlank(message = "主題域名稱不能為空",groups = {ValidationGroups.excelImportFirst.class})@ExcelColumn(title = "業務主題(*)")private String domainName;@NotBlank(message = "數倉分層名稱不能為空",groups = {ValidationGroups.excelImportFirst.class})@ExcelColumn(title = "數倉分層名稱(*)")private String layeringName;@NotBlank(message = "doris集群名稱不能為空",groups = {ValidationGroups.excelImportFirst.class})@ExcelColumn(title = "集群名稱(*)")private String clusterName;@NotBlank(message = "doris庫名稱不能為空",groups = {ValidationGroups.excelImportFirst.class})@ExcelColumn(title = "所在庫(*)")private String databaseName;@NotBlank(message = "模型中文名稱不能為空",groups = {ValidationGroups.excelImportFirst.class})@Length(max = 64,message = "模型中文名稱不能超過{max}位",groups = {ValidationGroups.excelImportFirst.class})@ExcelColumn(title = "中文名稱(*)")private String chName;@NotBlank(message = "模型英文名稱不能為空",groups = {ValidationGroups.excelImportFirst.class})@Length(max = 64,message = "模型英文名稱不能超過{max}位",groups = {ValidationGroups.excelImportFirst.class})@ExcelColumn(title = "英文名稱(*)")private String enName;@ExcelColumn(title = "數據模型(*)")private String modelTypeName;@ExcelColumn(title = "副本數(*)")private Integer replicationNum;@ExcelColumn(title = "事實表類型(*)")private String factTableTypeName;@ExcelColumn(title = "業務過程中文名稱(*)")private String processName;@ExcelColumn(title = "模型描述")private String description;@NotBlank(message = "集群匹配不到數據",groups = {ValidationGroups.excelImportSecond.class})@UnTrans(type = UnTransType.SIMPLE,refs = {"clusterName", "databaseName"},tableName = "dgp_warehouse_doris_cluster c join dgp_warehouse_doris_database d on c.id=d.cluster_id",columns = {"c.name", "d.database_name"},uniqueColumn = "d.id")private String clusterDatabaseId;@NotBlank(message = "主題域匹配不到數據",groups = {ValidationGroups.excelImportSecond.class})@UnTrans(type = UnTransType.SIMPLE,refs = {"subjectName", "domainName"},tableName = "dgp_warehouse_plan_subject s join dgp_warehouse_plan_domain d on s.id=d.subject_id",columns = {"s.name", "d.name"},uniqueColumn = "d.id")private String domainId;@NotBlank(message = "數據模型匹配不到數據",groups = {ValidationGroups.excelImportSecond.class})@UnTrans(refs = "modelTypeName", type = UnTransType.DICTIONARY, dict = "dgp_modeling_model_type")private String modelType;@NotBlank(message = "數倉分層匹配不到數據",groups = {ValidationGroups.excelImportSecond.class})@UnTrans(type = UnTransType.SIMPLE,refs = {"layeringName"},tableName = "dgp_warehouse_plan_layering",columns = {"name"})private String layeringId;@UnTrans(type = UnTransType.SIMPLE,refs = {"subjectName", "domainName", "processName"},tableName = "dgp_warehouse_plan_subject s join dgp_warehouse_plan_domain d on s.id=d.subject_id join dgp_modeling_process p",columns = {"s.name", "d.name", "p.ch_name"}, uniqueColumn = "p.id")private String processId;@UnTrans(type = UnTransType.DICTIONARY,refs = {"factTableTypeName"},dict = "dgp_modeling_fact_table_type")private String factTableType;private List<ModelingLogicalColumnImport> columns = new ArrayList<>();
}
6、controller
在controller里面接收文件對象,然后轉換成pojo。我下面的demo是表導入,一次導入多個表,每個表又有多個字段。所以搞了2個sheet,大多數一個sheet就行了。
7、service層代碼
大致思路:先校驗參數,在校驗參數的方法里已經做了反向翻譯了。校驗不通過直接拋異常,校驗通過繼續下面的excel pojo轉po 然后 批量入庫操作。
校驗參數:
1、先進行基礎校驗,判斷必填的是否填寫了,格式是否正確。
2、反向翻譯
3、校驗反向翻譯的結果字段,比如xxid xxType。比如客戶輸入了一個張三,但是沒匹配到張三對應的userid? 客戶輸入了TS 但是字典里只有男女,沒匹配到TS的字典碼 都會在第二次校驗里校驗出來。
4、如果有錯誤,則拋異常,然后全局異常攔截后返回json給前端