Jelajahi Sumber

逆向解析

gaocr 3 tahun lalu
induk
melakukan
dc14f5fc17
68 mengubah file dengan 8219 tambahan dan 17 penghapusan
  1. TEMPAT SAMPAH
      jdbc/kingbase8-8.6.0.jar
  2. 32 0
      pom.xml
  3. 269 0
      src/main/java/com/goer/common/chiner/model/ColumnField.java
  4. 71 0
      src/main/java/com/goer/common/chiner/model/Diagram.java
  5. 72 0
      src/main/java/com/goer/common/chiner/model/Dict.java
  6. 98 0
      src/main/java/com/goer/common/chiner/model/DictItem.java
  7. 89 0
      src/main/java/com/goer/common/chiner/model/Domain.java
  8. 123 0
      src/main/java/com/goer/common/chiner/model/Module.java
  9. 99 0
      src/main/java/com/goer/common/chiner/model/Project.java
  10. 135 0
      src/main/java/com/goer/common/chiner/model/ProjectOriginal.java
  11. 179 0
      src/main/java/com/goer/common/chiner/model/TableEntity.java
  12. 106 0
      src/main/java/com/goer/common/chiner/model/TableIndex.java
  13. 59 0
      src/main/java/com/goer/common/chiner/model/TableIndexColumnField.java
  14. 71 0
      src/main/java/com/goer/common/chiner/model/View.java
  15. 98 0
      src/main/java/com/goer/common/chiner/model/pdm/PDBaseObject.java
  16. 87 0
      src/main/java/com/goer/common/chiner/model/pdm/PDColumn.java
  17. 52 0
      src/main/java/com/goer/common/chiner/model/pdm/PDDomain.java
  18. 36 0
      src/main/java/com/goer/common/chiner/model/pdm/PDKey.java
  19. 54 0
      src/main/java/com/goer/common/chiner/model/pdm/PDTable.java
  20. 24 0
      src/main/java/com/goer/common/chiner/model/pdm/PrimaryKey.java
  21. 98 0
      src/main/java/com/goer/common/command/AbstractDBCommand.java
  22. 12 0
      src/main/java/com/goer/common/command/Command.java
  23. 59 0
      src/main/java/com/goer/common/command/ExecResult.java
  24. 83 0
      src/main/java/com/goer/common/command/impl/DBReverseGetAllTablesListImpl.java
  25. 103 0
      src/main/java/com/goer/common/command/impl/DBReverseGetTableDDLImpl.java
  26. 366 0
      src/main/java/com/goer/common/command/impl/GenDocxImpl.java
  27. 118 0
      src/main/java/com/goer/common/command/impl/ParseDDLToTableImpl.java
  28. 430 0
      src/main/java/com/goer/common/command/impl/ParsePDMFileImpl.java
  29. 63 0
      src/main/java/com/goer/common/command/impl/PingLoadDriverClassImpl.java
  30. 67 0
      src/main/java/com/goer/common/command/kit/ConnParseKit.java
  31. 405 0
      src/main/java/com/goer/common/dialect/DBDialect.java
  32. 55 0
      src/main/java/com/goer/common/dialect/DBDialectMatcher.java
  33. 43 0
      src/main/java/com/goer/common/dialect/impl/DBDialectDB2.java
  34. 75 0
      src/main/java/com/goer/common/dialect/impl/DBDialectDM.java
  35. 68 0
      src/main/java/com/goer/common/dialect/impl/DBDialectKingbase.java
  36. 65 0
      src/main/java/com/goer/common/dialect/impl/DBDialectMySQL.java
  37. 44 0
      src/main/java/com/goer/common/dialect/impl/DBDialectOracle.java
  38. 29 0
      src/main/java/com/goer/common/dialect/impl/DBDialectPostgreSQL.java
  39. 191 0
      src/main/java/com/goer/common/dialect/impl/DBDialectSQLServer.java
  40. 101 0
      src/main/java/com/goer/common/dialect/impl/DBDialectSQLite.java
  41. 68 0
      src/main/java/com/goer/common/utils/fisok/raw/RawConsts.java
  42. 26 0
      src/main/java/com/goer/common/utils/fisok/raw/holder/DateHolder.java
  43. 80 0
      src/main/java/com/goer/common/utils/fisok/raw/io/ByteInputStream.java
  44. 82 0
      src/main/java/com/goer/common/utils/fisok/raw/io/ByteOutputStream.java
  45. 655 0
      src/main/java/com/goer/common/utils/fisok/raw/kit/DateKit.java
  46. 657 0
      src/main/java/com/goer/common/utils/fisok/raw/kit/FileKit.java
  47. 187 0
      src/main/java/com/goer/common/utils/fisok/raw/kit/IOKit.java
  48. 85 0
      src/main/java/com/goer/common/utils/fisok/raw/kit/JSONKit.java
  49. 93 0
      src/main/java/com/goer/common/utils/fisok/raw/kit/JdbcKit.java
  50. 467 0
      src/main/java/com/goer/common/utils/fisok/raw/kit/StringKit.java
  51. 432 0
      src/main/java/com/goer/common/utils/fisok/raw/kit/ValidateKit.java
  52. 54 0
      src/main/java/com/goer/common/utils/fisok/raw/lang/RawException.java
  53. 387 0
      src/main/java/com/goer/common/utils/fisok/raw/lang/ValueObject.java
  54. 72 0
      src/main/java/com/goer/common/utils/fisok/sqloy/core/DBType.java
  55. 87 0
      src/main/java/com/goer/common/utils/fisok/sqloy/kit/DBTypeKit.java
  56. 35 0
      src/main/java/com/goer/project/model/modelDbs/controller/ModelDbsController.java
  57. 8 0
      src/main/java/com/goer/project/model/modelDbs/mapper/ModelDbsMapper.java
  58. 8 0
      src/main/java/com/goer/project/model/modelDbs/service/IModelDbsService.java
  59. 11 0
      src/main/java/com/goer/project/model/modelDbs/service/impl/ModelDbsServiceImpl.java
  60. 100 4
      src/main/java/com/goer/project/model/modelEntity/controller/ModelEntityController.java
  61. 4 0
      src/main/java/com/goer/project/model/modelEntity/service/IModelEntityService.java
  62. 136 0
      src/main/java/com/goer/project/model/modelEntity/service/impl/ModelEntityServiceImpl.java
  63. 6 1
      src/main/resources/mybatis/model/ModelDbsMapper.xml
  64. 46 5
      src/main/resources/templates/model/modelDbs/add.html
  65. 46 5
      src/main/resources/templates/model/modelDbs/edit.html
  66. 28 2
      src/main/resources/templates/model/modelDbs/modelDbs.html
  67. 93 0
      src/main/resources/templates/model/modelEntity/importTable.html
  68. 37 0
      src/main/resources/templates/model/modelEntity/modelEntity.html

TEMPAT SAMPAH
jdbc/kingbase8-8.6.0.jar


+ 32 - 0
pom.xml

@@ -275,6 +275,38 @@
             <artifactId>gson</artifactId>
             <version>2.8.2</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.kingbase</groupId>
+            <artifactId>kingbase8</artifactId>
+            <version>8.6.0</version>
+            <scope>system</scope>
+            <systemPath>${project.basedir}/jdbc/kingbase8-8.6.0.jar</systemPath>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun.odps</groupId>
+            <artifactId>odps-jdbc</artifactId>
+            <version>3.2.9</version>
+        </dependency>
+
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+            <version>2.9.9</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.deepoove</groupId>
+            <artifactId>poi-tl</artifactId>
+            <version>1.10.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+            <version>2.1.3</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 269 - 0
src/main/java/com/goer/common/chiner/model/ColumnField.java

@@ -0,0 +1,269 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.goer.common.utils.fisok.raw.kit.StringKit;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/12
+ * @desc : 列字段信息
+ * 来源于siner结构json文件:entities.fields
+ */
+@JsonPropertyOrder({
+        "rowNo",
+        "defKey",
+        "defName",
+        "comment",
+        "domain",
+        "type",
+        "len",
+        "scale",
+        "primaryKey",
+        "notNull",
+        "autoIncrement",
+        "defaultValue",
+        "hideInGraph",
+})
+public class ColumnField implements Serializable,Cloneable {
+    @JsonIgnore
+    private TableEntity tableEntity;
+    private int rowNo;              //行号,从1开始
+    private String defKey;          //字段代码
+    private String defName;         //字段名称
+    private String comment = "";    //字段注释说明
+    private String domain = "";                     //数据域(暂时留空,前端自行匹配)
+    private String type = "";       //字段数据类型,如varchar
+    private Integer len = null;     //字段长度,如32
+    private Integer scale = null;   //字段小数位数据
+    private String typeFullName = "";//类型+长度+小数位数
+    private Boolean primaryKey = Boolean.FALSE;     //是否主键
+    private String primaryKeyName = "";
+    private Boolean notNull = Boolean.FALSE;        //是否允许为空
+    private String notNullName = "";
+    private Boolean autoIncrement = Boolean.FALSE;  //是否自增
+    private String autoIncrementName = "";
+    private String refDict = "";               //引用数据字典
+    private String defaultValue = "";               //默认值
+    private Boolean hideInGraph = Boolean.FALSE;    //关系图是否隐藏(第15个之前,默认为true)
+
+    public TableEntity getTableEntity() {
+        return tableEntity;
+    }
+
+    public void setTableEntity(TableEntity tableEntity) {
+        this.tableEntity = tableEntity;
+    }
+
+    public int getRowNo() {
+        return rowNo;
+    }
+
+    public void setRowNo(int rowNo) {
+        this.rowNo = rowNo;
+    }
+
+    public String getDefKey() {
+        return defKey;
+    }
+
+    public void setDefKey(String defKey) {
+        this.defKey = defKey;
+    }
+
+    public String getDefName() {
+        return defName;
+    }
+
+    public void setDefName(String defName) {
+        this.defName = defName;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public Integer getLen() {
+        return len;
+    }
+
+    public void setLen(Integer len) {
+        this.len = len;
+    }
+
+    public Integer getScale() {
+        return scale;
+    }
+
+    public void setScale(Integer scale) {
+        this.scale = scale;
+    }
+
+    /**
+     * 字段类型+长度+小数位数
+     * @return
+     */
+    public String getTypeFullName() {
+        return typeFullName;
+    }
+
+    public void setTypeFullName(String typeFullName) {
+        this.typeFullName = typeFullName;
+    }
+
+    public Boolean getPrimaryKey() {
+        return primaryKey;
+    }
+
+    public void setPrimaryKey(Boolean primaryKey) {
+        this.primaryKey = primaryKey;
+    }
+
+    public Boolean getNotNull() {
+        return notNull;
+    }
+
+    public void setNotNull(Boolean notNull) {
+        this.notNull = notNull;
+    }
+
+    public Boolean getAutoIncrement() {
+        return autoIncrement;
+    }
+
+    public void setAutoIncrement(Boolean autoIncrement) {
+        this.autoIncrement = autoIncrement;
+    }
+
+    public String getRefDict() {
+        return refDict;
+    }
+
+    public void setRefDict(String refDict) {
+        this.refDict = refDict;
+    }
+
+    public String getDefaultValue() {
+        return defaultValue;
+    }
+
+    public void setDefaultValue(String defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    public Boolean getHideInGraph() {
+        return hideInGraph;
+    }
+
+    public void setHideInGraph(Boolean hideInGraph) {
+        this.hideInGraph = hideInGraph;
+    }
+
+    public String getDomain() {
+        return domain;
+    }
+
+    public void setDomain(String domain) {
+        this.domain = domain;
+    }
+
+    public String getPrimaryKeyName() {
+        return primaryKeyName;
+    }
+
+    public void setPrimaryKeyName(String primaryKeyName) {
+        this.primaryKeyName = primaryKeyName;
+    }
+
+    public String getNotNullName() {
+        return notNullName;
+    }
+
+    public void setNotNullName(String notNullName) {
+        this.notNullName = notNullName;
+    }
+
+    public String getAutoIncrementName() {
+        return autoIncrementName;
+    }
+
+    public void setAutoIncrementName(String autoIncrementName) {
+        this.autoIncrementName = autoIncrementName;
+    }
+
+    public void fillConvertNames(){
+        //处理类型名
+        StringBuffer buffer = new StringBuffer(type);
+        if(len != null && len > 0){
+            buffer.append("(").append(len);
+            if(scale != null && scale > 0){
+                buffer.append(",").append(scale);
+            }
+            buffer.append(")");
+        }
+        typeFullName = buffer.toString();
+
+        if(primaryKey.equals(Boolean.TRUE)){
+            primaryKeyName = "√";
+        }
+        if(notNull.equals(Boolean.TRUE)){
+            notNullName = "√";
+        }
+        if(autoIncrement.equals(Boolean.TRUE)){
+            autoIncrementName = "√";
+        }
+        if(StringKit.isNotBlank(refDict)){
+            Dict dict = lookupDict(tableEntity.getDicts(),refDict);
+            String dictText = "";
+            if(dict != null){
+                dictText = "<字典:"+dict.getDefKey()+">";
+            }
+            if(StringKit.isNotBlank(comment)
+                    && comment.indexOf(dictText) < 0
+                    && StringKit.isNotBlank(dictText)){
+                comment += dictText;
+            }else{
+                comment = dictText;
+            }
+        }
+    }
+
+    public Dict lookupDict(List<Dict> dictList,String dictId){
+        for(Dict dict : dictList){
+            if(dictId.equals(dict.getId())){
+                return dict;
+            }
+        }
+        return null;
+    }
+}

+ 71 - 0
src/main/java/com/goer/common/chiner/model/Diagram.java

@@ -0,0 +1,71 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import com.deepoove.poi.data.RenderData;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+import java.io.Serializable;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/22
+ * @desc :
+ */
+@JsonPropertyOrder({
+        "defKey",
+        "defName",
+})
+public class Diagram implements Serializable,Cloneable{
+    private String id;              //关系图ID
+    private String defKey;          //关系图代码
+    private String defName;         //关系图名称
+    @JsonIgnore
+    private RenderData renderData;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getDefKey() {
+        return defKey;
+    }
+
+    public void setDefKey(String defKey) {
+        this.defKey = defKey;
+    }
+
+    public String getDefName() {
+        return defName;
+    }
+
+    public void setDefName(String defName) {
+        this.defName = defName;
+    }
+
+    public RenderData getRenderData() {
+        return renderData;
+    }
+
+    public void setRenderData(RenderData renderData) {
+        this.renderData = renderData;
+    }
+}

+ 72 - 0
src/main/java/com/goer/common/chiner/model/Dict.java

@@ -0,0 +1,72 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/22
+ * @desc :
+ */
+public class Dict implements Serializable,Cloneable{
+    private String id;
+    private String defKey;
+    private String defName;
+    private String intro;
+    private List<DictItem> items;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getDefKey() {
+        return defKey;
+    }
+
+    public void setDefKey(String defKey) {
+        this.defKey = defKey;
+    }
+
+    public String getDefName() {
+        return defName;
+    }
+
+    public void setDefName(String defName) {
+        this.defName = defName;
+    }
+
+    public String getIntro() {
+        return intro;
+    }
+
+    public void setIntro(String intro) {
+        this.intro = intro;
+    }
+
+    public List<DictItem> getItems() {
+        return items;
+    }
+
+    public void setItems(List<DictItem> items) {
+        this.items = items;
+    }
+}

+ 98 - 0
src/main/java/com/goer/common/chiner/model/DictItem.java

@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import java.io.Serializable;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/24
+ * @desc :
+ */
+public class DictItem implements Serializable,Cloneable {
+    private String id;
+    private int rowNo;              //行号,从1开始
+    private String defKey;
+    private String defName;
+    private String intro;
+    private String parentKey;
+    private Boolean enabled;
+    private Boolean enabledName;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public int getRowNo() {
+        return rowNo;
+    }
+
+    public void setRowNo(int rowNo) {
+        this.rowNo = rowNo;
+    }
+
+    public String getDefKey() {
+        return defKey;
+    }
+
+    public void setDefKey(String defKey) {
+        this.defKey = defKey;
+    }
+
+    public String getDefName() {
+        return defName;
+    }
+
+    public void setDefName(String defName) {
+        this.defName = defName;
+    }
+
+    public String getIntro() {
+        return intro;
+    }
+
+    public void setIntro(String intro) {
+        this.intro = intro;
+    }
+
+    public String getParentKey() {
+        return parentKey;
+    }
+
+    public void setParentKey(String parentKey) {
+        this.parentKey = parentKey;
+    }
+
+    public Boolean getEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public Boolean getEnabledName() {
+        return enabledName;
+    }
+
+    public void setEnabledName(Boolean enabledName) {
+        this.enabledName = enabledName;
+    }
+}

+ 89 - 0
src/main/java/com/goer/common/chiner/model/Domain.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import java.util.Map;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/7/7
+ * @desc :
+ */
+public class Domain {
+    private String id;
+    private String defKey;
+    private String defName;
+    private String applyFor;
+    private Integer len;
+    private Integer scale;
+    private Map<String,Object> uiHint;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getDefKey() {
+        return defKey;
+    }
+
+    public void setDefKey(String defKey) {
+        this.defKey = defKey;
+    }
+
+    public String getDefName() {
+        return defName;
+    }
+
+    public void setDefName(String defName) {
+        this.defName = defName;
+    }
+
+    public String getApplyFor() {
+        return applyFor;
+    }
+
+    public void setApplyFor(String applyFor) {
+        this.applyFor = applyFor;
+    }
+
+    public Integer getLen() {
+        return len;
+    }
+
+    public void setLen(Integer len) {
+        this.len = len;
+    }
+
+    public Integer getScale() {
+        return scale;
+    }
+
+    public void setScale(Integer scale) {
+        this.scale = scale;
+    }
+
+    public Map<String, Object> getUiHint() {
+        return uiHint;
+    }
+
+    public void setUiHint(Map<String, Object> uiHint) {
+        this.uiHint = uiHint;
+    }
+}

+ 123 - 0
src/main/java/com/goer/common/chiner/model/Module.java

@@ -0,0 +1,123 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/22
+ * @desc :
+ */
+public class Module implements Serializable,Cloneable {
+    private String defKey;          //表代码
+    private String defName;         //表名称
+    private List<TableEntity> entities;
+    private List<View> views;
+    private List<Dict> dicts;
+    private List<Diagram> diagrams;
+
+    public String getDefKey() {
+        return defKey;
+    }
+
+    public void setDefKey(String defKey) {
+        this.defKey = defKey;
+    }
+
+    public String getDefName() {
+        return defName;
+    }
+
+    public void setDefName(String defName) {
+        this.defName = defName;
+    }
+
+    public List<TableEntity> getEntities() {
+        return entities;
+    }
+
+    public void setEntities(List<TableEntity> entities) {
+        this.entities = entities;
+    }
+
+    public List<View> getViews() {
+        return views;
+    }
+
+    public void setViews(List<View> views) {
+        this.views = views;
+    }
+
+    public List<Dict> getDicts() {
+        return dicts;
+    }
+
+    public void setDicts(List<Dict> dicts) {
+        this.dicts = dicts;
+    }
+
+    public List<Diagram> getDiagrams() {
+        return diagrams;
+    }
+
+    public void setDiagrams(List<Diagram> diagrams) {
+        this.diagrams = diagrams;
+    }
+    public void fillEntitiesRowNo(){
+        if(entities == null){
+            return;
+        }
+        for(int i=1;i<=entities.size();i++){
+            TableEntity entity = entities.get(i-1);
+            if(entity==null){
+                continue;
+            }
+            entity.setRowNo(i);
+        }
+    }
+    public void fillDictsRowNo(){
+        if(dicts == null){
+            return;
+        }
+        for(int i=1;i<=dicts.size();i++){
+            Dict dict = dicts.get(i-1);
+            if(dict==null){
+                continue;
+            }
+            List<DictItem> items = dict.getItems();
+            for(int j=1;j<=items.size();j++){
+                DictItem item = items.get(j-1);
+                if(item==null){
+                    continue;
+                }
+                item.setRowNo(j);
+            }
+        }
+    }
+
+    public boolean isEmpty(){
+        if((entities == null || entities.size() == 0)
+        &&(diagrams == null || diagrams.size() == 0)
+        &&(dicts == null || dicts.size() == 0)){
+            return true;
+        }else{
+            return false;
+        }
+
+    }
+}

+ 99 - 0
src/main/java/com/goer/common/chiner/model/Project.java

@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/22
+ * @desc :
+ */
+public class Project implements Serializable,Cloneable {
+    private String name;
+    private String describe;
+    private String avatar;
+    private String version;
+    private String createdTime;
+    private String updatedTime;
+    private Object profile;
+    private List<Module> modules;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescribe() {
+        return describe;
+    }
+
+    public void setDescribe(String describe) {
+        this.describe = describe;
+    }
+
+    public String getAvatar() {
+        return avatar;
+    }
+
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getCreatedTime() {
+        return createdTime;
+    }
+
+    public void setCreatedTime(String createdTime) {
+        this.createdTime = createdTime;
+    }
+
+    public String getUpdatedTime() {
+        return updatedTime;
+    }
+
+    public void setUpdatedTime(String updatedTime) {
+        this.updatedTime = updatedTime;
+    }
+
+    public Object getProfile() {
+        return profile;
+    }
+
+    public void setProfile(Object profile) {
+        this.profile = profile;
+    }
+
+    public List<Module> getModules() {
+        return modules;
+    }
+
+    public void setModules(List<Module> modules) {
+        this.modules = modules;
+    }
+}

+ 135 - 0
src/main/java/com/goer/common/chiner/model/ProjectOriginal.java

@@ -0,0 +1,135 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/22
+ * @desc :
+ */
+public class ProjectOriginal implements Serializable,Cloneable  {
+    private String name;
+    private String describe;
+    private String avatar;
+    private String version;
+    private String createdTime;
+    private String updatedTime;
+    private Object profile;
+    private List<Object> entities;
+    private List<Object> views;
+    private List<Object> dicts;
+    private List<Object> viewGroups;
+    private List<Object> diagrams;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescribe() {
+        return describe;
+    }
+
+    public void setDescribe(String describe) {
+        this.describe = describe;
+    }
+
+    public String getAvatar() {
+        return avatar;
+    }
+
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getCreatedTime() {
+        return createdTime;
+    }
+
+    public void setCreatedTime(String createdTime) {
+        this.createdTime = createdTime;
+    }
+
+    public String getUpdatedTime() {
+        return updatedTime;
+    }
+
+    public void setUpdatedTime(String updatedTime) {
+        this.updatedTime = updatedTime;
+    }
+
+    public Object getProfile() {
+        return profile;
+    }
+
+    public void setProfile(Object profile) {
+        this.profile = profile;
+    }
+
+    public List<Object> getEntities() {
+        return entities;
+    }
+
+    public void setEntities(List<Object> entities) {
+        this.entities = entities;
+    }
+
+    public List<Object> getViews() {
+        return views;
+    }
+
+    public void setViews(List<Object> views) {
+        this.views = views;
+    }
+
+    public List<Object> getDicts() {
+        return dicts;
+    }
+
+    public void setDicts(List<Object> dicts) {
+        this.dicts = dicts;
+    }
+
+    public List<Object> getViewGroups() {
+        return viewGroups;
+    }
+
+    public void setViewGroups(List<Object> viewGroups) {
+        this.viewGroups = viewGroups;
+    }
+
+    public List<Object> getDiagrams() {
+        return diagrams;
+    }
+
+    public void setDiagrams(List<Object> diagrams) {
+        this.diagrams = diagrams;
+    }
+}

+ 179 - 0
src/main/java/com/goer/common/chiner/model/TableEntity.java

@@ -0,0 +1,179 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/12
+ * @desc : 表实体
+ */
+@JsonPropertyOrder({
+        "id",
+        "rowNo",
+        "defKey",
+        "defName",
+        "comment",
+        "properties",
+        "fields",
+        "indexes"
+})
+public class TableEntity implements Serializable,Cloneable {
+    private String id;
+    private int rowNo;              //行号,从1开始
+    private String defKey;          //表代码
+    private String defName;         //表名称
+    private String comment = "";    //表注释说明
+    private Map<String,String> properties = new LinkedHashMap<String,String>();     //扩展属性
+    private List<ColumnField> fields = new ArrayList<ColumnField>();                //字段列表
+    private List<TableIndex> indexes = new ArrayList<TableIndex>();             //表索引
+    @JsonIgnore
+    private List<Dict> dicts = new ArrayList<>();
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public int getRowNo() {
+        return rowNo;
+    }
+
+    public void setRowNo(int rowNo) {
+        this.rowNo = rowNo;
+    }
+
+    public String getDefKey() {
+        return defKey;
+    }
+
+    public void setDefKey(String defKey) {
+        this.defKey = defKey;
+    }
+
+    public String getDefName() {
+        return defName;
+    }
+
+    public void setDefName(String defName) {
+        this.defName = defName;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public Map<String, String> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Map<String, String> properties) {
+        this.properties = properties;
+    }
+
+    public List<ColumnField> getFields() {
+        return fields;
+    }
+
+    public void setFields(List<ColumnField> fields) {
+        this.fields = fields;
+    }
+
+    public List<TableIndex> getIndexes() {
+        return indexes;
+    }
+
+    public void setIndexes(List<TableIndex> indexes) {
+        this.indexes = indexes;
+    }
+
+    public List<Dict> getDicts() {
+        return dicts;
+    }
+
+    public void setDicts(List<Dict> dicts) {
+        this.dicts = dicts;
+    }
+
+    /**
+     * 查找字段
+     * @param columnDefKey
+     * @return
+     */
+    public ColumnField lookupField(String columnDefKey){
+        List<ColumnField> fieldList = getFields();
+        for(ColumnField field : fieldList){
+            if(columnDefKey.equalsIgnoreCase(field.getDefKey())){
+                return field;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 查找索引
+     * @param indexDefKey
+     * @return
+     */
+    public TableIndex lookupIndex(String indexDefKey){
+        List<TableIndex> indexes = getIndexes();
+        for(TableIndex index : indexes){
+            if(indexDefKey.equalsIgnoreCase(index.getDefKey())){
+                return index;
+            }
+        }
+        return null;
+    }
+
+    public void fillFieldsCalcValue(){
+        for(int i=1;i<=fields.size();i++){
+            ColumnField field = fields.get(i-1);
+            field.setTableEntity(this);
+            field.fillConvertNames();
+            field.setRowNo(i);
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        TableEntity entity = (TableEntity) o;
+        return Objects.equals(defKey, entity.defKey) &&
+                Objects.equals(defName, entity.defName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(defKey, defName);
+    }
+}

+ 106 - 0
src/main/java/com/goer/common/chiner/model/TableIndex.java

@@ -0,0 +1,106 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/20
+ * @desc : 数据表的索引
+ */
+@JsonPropertyOrder({
+        "defKey",
+        "unique",
+        "defName",
+        "comment",
+        "fields",
+})
+public class TableIndex implements Serializable,Cloneable {
+    private String id;
+    private String defKey;          //索引代码
+    private boolean unique = false; //索引是否唯一
+    private String defName;         //索引名称
+    private String comment = "";    //索引注释说明
+    private List<TableIndexColumnField> fields = new ArrayList<>(); //索引下的字段明细
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getDefKey() {
+        return defKey;
+    }
+
+    public void setDefKey(String defKey) {
+        this.defKey = defKey;
+    }
+
+    public boolean isUnique() {
+        return unique;
+    }
+
+    public void setUnique(boolean unique) {
+        this.unique = unique;
+    }
+
+    public String getDefName() {
+        return defName;
+    }
+
+    public void setDefName(String defName) {
+        this.defName = defName;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public List<TableIndexColumnField> getFields() {
+        return fields;
+    }
+
+    public void setFields(List<TableIndexColumnField> fields) {
+        this.fields = fields;
+    }
+
+    /**
+     * 查找索引
+     * @param fieldDefKey
+     * @return
+     */
+    public TableIndexColumnField lookupField(String fieldDefKey){
+        List<TableIndexColumnField> fields = getFields();
+        for(TableIndexColumnField field : fields){
+            if(fieldDefKey.equalsIgnoreCase(field.getFieldDefKey())){
+                return field;
+            }
+        }
+        return null;
+    }
+}

+ 59 - 0
src/main/java/com/goer/common/chiner/model/TableIndexColumnField.java

@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+import java.io.Serializable;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/20
+ * @desc : 索引引用的字段
+ */
+@JsonPropertyOrder({
+        "defKey",
+        "ascOrDesc",
+})
+public class TableIndexColumnField implements Serializable,Cloneable {
+    private String id;
+    private String fieldDefKey;
+    private String ascOrDesc;
+
+    public String getFieldDefKey() {
+        return fieldDefKey;
+    }
+
+    public void setFieldDefKey(String fieldDefKey) {
+        this.fieldDefKey = fieldDefKey;
+    }
+
+    public String getAscOrDesc() {
+        return ascOrDesc;
+    }
+
+    public void setAscOrDesc(String ascOrDesc) {
+        this.ascOrDesc = ascOrDesc;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+}

+ 71 - 0
src/main/java/com/goer/common/chiner/model/View.java

@@ -0,0 +1,71 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model;
+
+import java.io.Serializable;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/22
+ * @desc :
+ */
+public class View implements Serializable,Cloneable{
+    private String id;
+    private int rowNo;              //行号,从1开始
+    private String defKey;          //表代码
+    private String defName;         //表名称
+    private String comment = "";    //表注释说明
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public int getRowNo() {
+        return rowNo;
+    }
+
+    public void setRowNo(int rowNo) {
+        this.rowNo = rowNo;
+    }
+
+    public String getDefKey() {
+        return defKey;
+    }
+
+    public void setDefKey(String defKey) {
+        this.defKey = defKey;
+    }
+
+    public String getDefName() {
+        return defName;
+    }
+
+    public void setDefName(String defName) {
+        this.defName = defName;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+}

+ 98 - 0
src/main/java/com/goer/common/chiner/model/pdm/PDBaseObject.java

@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model.pdm;
+
+import java.util.Date;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/7/4
+ * @desc :
+ */
+public class PDBaseObject {
+    private String id;
+    private String objectID;
+    private String name;
+    private String code;
+    private Date creationDate;
+    private String creator;
+    private Date modificationDate;
+    private String modifier;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getObjectID() {
+        return objectID;
+    }
+
+    public void setObjectID(String objectID) {
+        this.objectID = objectID;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public Date getCreationDate() {
+        return creationDate;
+    }
+
+    public void setCreationDate(Date creationDate) {
+        this.creationDate = creationDate;
+    }
+
+    public String getCreator() {
+        return creator;
+    }
+
+    public void setCreator(String creator) {
+        this.creator = creator;
+    }
+
+    public Date getModificationDate() {
+        return modificationDate;
+    }
+
+    public void setModificationDate(Date modificationDate) {
+        this.modificationDate = modificationDate;
+    }
+
+    public String getModifier() {
+        return modifier;
+    }
+
+    public void setModifier(String modifier) {
+        this.modifier = modifier;
+    }
+}

+ 87 - 0
src/main/java/com/goer/common/chiner/model/pdm/PDColumn.java

@@ -0,0 +1,87 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model.pdm;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/7/4
+ * @desc :
+ */
+public class PDColumn extends PDBaseObject {
+    private String comment;
+    private String dataType;
+    private Integer length;
+    private Integer precision;
+    private Boolean mandatory;
+    private String domain;
+    private Boolean primaryKey;
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public String getDataType() {
+        return dataType;
+    }
+
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+
+    public Integer getLength() {
+        return length;
+    }
+
+    public void setLength(Integer length) {
+        this.length = length;
+    }
+
+    public Integer getPrecision() {
+        return precision;
+    }
+
+    public void setPrecision(Integer precision) {
+        this.precision = precision;
+    }
+
+    public Boolean getMandatory() {
+        return mandatory;
+    }
+
+    public void setMandatory(Boolean mandatory) {
+        this.mandatory = mandatory;
+    }
+
+    public String getDomain() {
+        return domain;
+    }
+
+    public void setDomain(String domain) {
+        this.domain = domain;
+    }
+
+    public Boolean getPrimaryKey() {
+        return primaryKey;
+    }
+
+    public void setPrimaryKey(Boolean primaryKey) {
+        this.primaryKey = primaryKey;
+    }
+}

+ 52 - 0
src/main/java/com/goer/common/chiner/model/pdm/PDDomain.java

@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model.pdm;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/7/4
+ * @desc : PDM文件的数据域模型
+ */
+public class PDDomain extends PDBaseObject {
+
+    private String dataType;
+    private Integer length;
+    private Integer precision;
+
+    public String getDataType() {
+        return dataType;
+    }
+
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+
+    public Integer getLength() {
+        return length;
+    }
+
+    public void setLength(Integer length) {
+        this.length = length;
+    }
+
+    public Integer getPrecision() {
+        return precision;
+    }
+
+    public void setPrecision(Integer precision) {
+        this.precision = precision;
+    }
+}

+ 36 - 0
src/main/java/com/goer/common/chiner/model/pdm/PDKey.java

@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model.pdm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/7/4
+ * @desc :
+ */
+public class PDKey extends PDBaseObject {
+    private List<PDColumn> columns = new ArrayList<>();
+
+    public List<PDColumn> getColumns() {
+        return columns;
+    }
+
+    public void setColumns(List<PDColumn> columns) {
+        this.columns = columns;
+    }
+}

+ 54 - 0
src/main/java/com/goer/common/chiner/model/pdm/PDTable.java

@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model.pdm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/7/4
+ * @desc :
+ */
+public class PDTable extends PDBaseObject {
+    private String comment;
+    private List<PDColumn> columns = new ArrayList<>();
+    private List<PDKey> keys = new ArrayList<>();
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public List<PDColumn> getColumns() {
+        return columns;
+    }
+
+    public void setColumns(List<PDColumn> columns) {
+        this.columns = columns;
+    }
+
+    public List<PDKey> getKeys() {
+        return keys;
+    }
+
+    public void setKeys(List<PDKey> keys) {
+        this.keys = keys;
+    }
+}

+ 24 - 0
src/main/java/com/goer/common/chiner/model/pdm/PrimaryKey.java

@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.chiner.model.pdm;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/7/4
+ * @desc :
+ */
+public class PrimaryKey extends PDBaseObject {
+}

+ 98 - 0
src/main/java/com/goer/common/command/AbstractDBCommand.java

@@ -0,0 +1,98 @@
+package com.goer.common.command;
+
+import com.goer.common.utils.fisok.raw.kit.JdbcKit;
+import com.goer.common.utils.fisok.raw.kit.StringKit;
+import com.goer.project.model.modelDbs.domain.ModelDbs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc : 数据库相关操作命令的抽像
+ */
+public abstract class AbstractDBCommand<T> implements Command<T> {
+    public static final String KEY_DRIVER_CLASS_NAME = "driver_class_name";
+    public static final String KEY_URL = "url";
+    public static final String KEY_USERNAME = "username";
+    public static final String KEY_PASSWORD = "password";
+
+    protected Logger logger = LoggerFactory.getLogger(getClass());
+
+    protected String driverClassName;
+    protected String url;
+    protected String username;
+    protected String password;
+    private Connection dbConn = null;
+    protected Map<String,String> extProps = new LinkedHashMap<>();
+
+    public void init(Map<String,String> params){
+        //如果有数据库连接了,就不要初始化了
+        if(dbConn != null){
+            return;
+        }
+        driverClassName = params.get(KEY_DRIVER_CLASS_NAME);
+        url = params.get(KEY_URL);
+        username = params.get(KEY_USERNAME);
+        password = params.get(KEY_PASSWORD);
+        if(url.indexOf("{and}")>0){
+            url = url.replaceAll("\\{and\\}","&");
+        }
+        Iterator<String> iterator = params.keySet().iterator();
+        while (iterator.hasNext()){
+            String key = StringKit.nvl(iterator.next(),"");
+            if(!inRemainProps(key)){
+                String value = StringKit.nvl(params.get(key),"");
+                extProps.put(key,value);
+            }
+        }
+    }
+
+    /**
+     * 键值是否为保留值
+     * @param key
+     * @return
+     */
+    private boolean inRemainProps(String key){
+        if(key.equalsIgnoreCase(KEY_DRIVER_CLASS_NAME)
+            ||key.equalsIgnoreCase(KEY_URL)
+            ||key.equalsIgnoreCase(KEY_USERNAME)
+            ||key.equalsIgnoreCase(KEY_PASSWORD)){
+            return true;
+        }else{
+            return false;
+        }
+    }
+
+    public Connection getDbConn() {
+        return dbConn;
+    }
+
+    public void setDbConn(Connection dbConn) {
+        this.dbConn = dbConn;
+    }
+
+    public Connection createConnect(){
+        if(dbConn != null){
+            return dbConn;
+        }else{
+            Properties props = new Properties();
+            if(StringKit.isNotBlank(username)){
+                props.put("user", username);
+            }
+            if(StringKit.isNotBlank(password)){
+                props.put("password", password);
+            }
+            if(extProps.size() > 0){
+                props.putAll(extProps);
+            }
+            return JdbcKit.getConnection(driverClassName, url, props);
+        }
+    }
+}

+ 12 - 0
src/main/java/com/goer/common/command/Command.java

@@ -0,0 +1,12 @@
+package com.goer.common.command;
+
+import java.util.Map;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc : 执行命令的抽像
+ */
+public interface Command<T> {
+    T exec(Map<String, String> params);
+}

+ 59 - 0
src/main/java/com/goer/common/command/ExecResult.java

@@ -0,0 +1,59 @@
+package com.goer.common.command;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc : 执行命令的返回结果对象
+ */
+@JsonPropertyOrder({
+        "code",
+        "status",
+        "body",
+        "properties",
+})
+public class ExecResult implements Serializable {
+    public static final String SUCCESS = "SUCCESS";
+    public static final String FAILED = "FAILED";
+
+    private String status = SUCCESS;
+    private Object body;
+    private Map<String,Object> properties = new HashMap<String,Object>();
+
+    public ExecResult() {
+    }
+
+    public ExecResult(String status, String body) {
+        this.status = status;
+        this.body = body;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public Object getBody() {
+        return body;
+    }
+
+    public void setBody(Object body) {
+        this.body = body;
+    }
+
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Map<String, Object> properties) {
+        this.properties = properties;
+    }
+}

+ 83 - 0
src/main/java/com/goer/common/command/impl/DBReverseGetAllTablesListImpl.java

@@ -0,0 +1,83 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.command.impl;
+
+import com.goer.common.chiner.model.TableEntity;
+import com.goer.common.command.AbstractDBCommand;
+import com.goer.common.command.ExecResult;
+import com.goer.common.dialect.DBDialect;
+import com.goer.common.dialect.DBDialectMatcher;
+import com.goer.common.utils.fisok.raw.kit.JdbcKit;
+import com.goer.common.utils.fisok.sqloy.core.DBType;
+import com.goer.common.utils.fisok.sqloy.kit.DBTypeKit;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/12
+ * @desc : 数据库逆向,解析表清单功能
+ */
+public class DBReverseGetAllTablesListImpl extends AbstractDBCommand<ExecResult> {
+
+    @Override
+    public ExecResult exec(Map<String, String> params) {
+        super.init(params);
+        ExecResult ret = new ExecResult();
+
+        //获取连接正常的情况下,进入下一步
+        Connection conn = null;
+        List<TableEntity> tableEntities = null;
+        try {
+            conn = createConnect();
+            tableEntities = fetchTableEntities(conn);
+            ret.setStatus(ExecResult.SUCCESS);
+            ret.setBody(tableEntities);
+        } catch (Exception e) {
+            ret.setStatus(ExecResult.FAILED);
+            ret.setBody(e.getMessage());
+            logger.error("", e);
+        } finally {
+            JdbcKit.close(conn);
+        }
+
+        return ret;
+    }
+
+    /**
+     * 获取所有数据表列表
+     *
+     * @param conn
+     * @return
+     */
+    protected List<TableEntity> fetchTableEntities(Connection conn) throws SQLException {
+        List<TableEntity> tableEntities = new ArrayList<>();
+        try {
+            DBType dbType = DBTypeKit.getDBType(conn);
+            DBDialect dbDialect = DBDialectMatcher.getDBDialect(dbType);
+            tableEntities = dbDialect.getAllTables(conn);
+        } catch (SQLException e) {
+            logger.error("读取表清单出错", e);
+            throw new RuntimeException(e);
+        }
+
+        return tableEntities;
+    }
+}

+ 103 - 0
src/main/java/com/goer/common/command/impl/DBReverseGetTableDDLImpl.java

@@ -0,0 +1,103 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.command.impl;
+
+import com.goer.common.chiner.model.TableEntity;
+import com.goer.common.command.AbstractDBCommand;
+import com.goer.common.command.ExecResult;
+import com.goer.common.dialect.DBDialect;
+import com.goer.common.dialect.DBDialectMatcher;
+import com.goer.common.utils.fisok.raw.kit.JdbcKit;
+import com.goer.common.utils.fisok.raw.kit.StringKit;
+import com.goer.common.utils.fisok.sqloy.core.DBType;
+import com.goer.common.utils.fisok.sqloy.kit.DBTypeKit;
+import com.goer.project.model.modelDbs.domain.ModelDbs;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/14
+ * @desc : 数据库逆向,解析表清单的字段以及索引
+ */
+public class DBReverseGetTableDDLImpl extends AbstractDBCommand<ExecResult> {
+    @Override
+    public ExecResult exec(Map<String, String> params) {
+        super.init(params);
+        String tables = params.get("tables").toUpperCase();
+        if (StringKit.isBlank(tables)) {
+            throw new IllegalArgumentException("parameter [tables] not exists");
+        }
+        List<String> tableList = Arrays.stream(tables.split(","))
+                .collect(Collectors.toList());
+
+
+        ExecResult ret = new ExecResult();
+
+        Connection conn = null;
+        try {
+            conn = createConnect();
+            List<TableEntity> tableEntities = fillTableEntities(conn, tableList);
+            ret.setStatus(ExecResult.SUCCESS);
+            ret.setBody(tableEntities);
+        } catch (Exception e) {
+            ret.setStatus(ExecResult.FAILED);
+            ret.setBody(e.getMessage());
+            logger.error("", e);
+        } finally {
+            JdbcKit.close(conn);
+        }
+        return ret;
+    }
+
+    /**
+     * 获取所有数据表实体的字段及索引
+     *
+     * @param conn
+     * @param tableNameList
+     * @return
+     */
+    protected List<TableEntity> fillTableEntities(Connection conn, List<String> tableNameList) {
+        List<TableEntity> tableEntities = new ArrayList<TableEntity>();
+
+        try {
+            DatabaseMetaData meta = conn.getMetaData();
+            DBType dbType = DBTypeKit.getDBType(meta);
+            DBDialect dbDialect = DBDialectMatcher.getDBDialect(dbType);
+
+            for (String tableName : tableNameList) {
+                TableEntity tableEntity = dbDialect.createTableEntity(conn, meta, tableName);
+                if (tableEntity == null) {
+                    continue;
+                }
+                tableEntity.fillFieldsCalcValue();
+                tableEntities.add(tableEntity);
+            }
+        } catch (SQLException e) {
+            logger.error("读取表清单出错", e);
+            throw new RuntimeException("读取表清单出错|" + e.getMessage(), e);
+        }
+
+        return tableEntities;
+    }
+}

+ 366 - 0
src/main/java/com/goer/common/command/impl/GenDocxImpl.java

@@ -0,0 +1,366 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.command.impl;
+
+import com.deepoove.poi.XWPFTemplate;
+import com.deepoove.poi.config.Configure;
+import com.deepoove.poi.config.ConfigureBuilder;
+import com.deepoove.poi.data.PictureRenderData;
+import com.deepoove.poi.data.PictureType;
+import com.deepoove.poi.plugin.bookmark.BookmarkRenderPolicy;
+import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
+import com.goer.common.chiner.model.*;
+import com.goer.common.command.Command;
+import com.goer.common.command.ExecResult;
+import com.goer.common.utils.fisok.raw.kit.FileKit;
+import com.goer.common.utils.fisok.raw.kit.IOKit;
+import com.goer.common.utils.fisok.raw.kit.JSONKit;
+import com.goer.common.utils.fisok.raw.lang.ValueObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/14
+ * @desc : 生成WORD文件
+ */
+public class GenDocxImpl implements Command<ExecResult> {
+    protected Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Override
+    public ExecResult exec(Map<String, String> params) {
+        String sinerFile = params.get("sinerFile");
+        String docxTpl = params.get("docxTpl");
+        String imgDir = params.get("imgDir");
+        String imgExt = params.get("imgExt");
+        String outFile = params.get("outFile"); //输出的文档文件
+        String out = params.get("out");         //输出的结果json文件
+
+        ExecResult ret = new ExecResult();
+
+        try {
+            exec(sinerFile, docxTpl, imgDir, imgExt, outFile,out);
+            ret.setStatus(ExecResult.SUCCESS);
+            ret.setBody(outFile);
+        } catch (Exception e) {
+            String message = e.getMessage();
+            if(message == null){
+                message = e.toString();
+            }
+            ret.setStatus(ExecResult.FAILED);
+            ret.setBody(message);
+            logger.error("", e);
+        }
+        return ret;
+    }
+
+    protected void exec(String sinerFile, String docxTpl, String imgDir, String imgExt, String outFile,String out) throws IOException {
+        File inDataFile = new File(sinerFile);
+        File docTplFile = new File(docxTpl);
+        File outDocxFile = new File(outFile);
+
+        String jsonText = parseFile(inDataFile);
+
+        Project project = null;
+        ProjectOriginal projectOriginal = JSONKit.jsonToBean(jsonText,ProjectOriginal.class);
+        List<Object> objectEntities = projectOriginal.getEntities();
+        List<Object> objectViews = projectOriginal.getViews();
+        List<Object> objectDicts = projectOriginal.getDicts();
+        List<Object> objectDiagrams = projectOriginal.getDiagrams();
+        List<Object> viewGroups = projectOriginal.getViewGroups();
+
+        String textEntities = JSONKit.toJsonString(objectEntities);
+        String textViews = JSONKit.toJsonString(objectViews);
+        String textDicts = JSONKit.toJsonString(objectDicts);
+        String textDiagrams = JSONKit.toJsonString(objectDiagrams);
+
+        List<TableEntity> entities = JSONKit.jsonToBeanList(textEntities,TableEntity.class);
+        List<View> views = JSONKit.jsonToBeanList(textViews,View.class);
+        List<Dict> dicts = JSONKit.jsonToBeanList(textDicts,Dict.class);
+        List<Diagram> diagrams = JSONKit.jsonToBeanList(textDiagrams,Diagram.class);
+        if(entities == null){
+            entities = new ArrayList<>();
+        }
+        if(views == null){
+            views = new ArrayList<>();
+        }
+        if(dicts == null){
+            dicts = new ArrayList<>();
+        }
+        if(diagrams == null){
+            diagrams = new ArrayList<>();
+        }
+
+        List<Module> modules = new ArrayList<Module>();
+        project = JSONKit.jsonToBean(jsonText,Project.class);
+        project.setModules(modules);
+
+        if(viewGroups == null || viewGroups.size() == 0){
+            //如果没有分组,则构建一个默认分组
+            Module module = new Module();
+            modules.add(module);
+            module.setDefKey("CHINER");
+            module.setDefName(project.getName());
+
+
+            module.setEntities(entities);
+            module.setViews(views);
+            module.setDicts(dicts);
+            module.setDiagrams(diagrams);
+            //处理关系图
+            for(Diagram diagram : diagrams){
+                PictureRenderData renderData = createPictureRenderData(imgDir,imgExt,diagram.getId());
+                if(renderData != null){
+                    diagram.setRenderData(renderData);
+                }
+            }
+
+            for(TableEntity entity : entities){
+                entity.setDicts(dicts);
+                entity.fillFieldsCalcValue();
+            }
+
+            module.fillEntitiesRowNo();
+            module.fillDictsRowNo();
+
+        }else{
+            List<TableEntity> findedEntities = new ArrayList<>();
+            List<Diagram> findDiagrams = new ArrayList<>();
+            List<Dict> findedDicts = new ArrayList<>();
+
+            //处理模块中包含的数据表+数据字典
+            for(Object viewGroup : viewGroups){
+                Map<String,Object> mapModule = ( Map<String,Object>)viewGroup;
+                String moduleDefKey = ValueObject.valueOf(mapModule.get("defKey")).strValue("");
+                String moduleDefName = ValueObject.valueOf(mapModule.get("defName")).strValue("");
+
+                Module module = new Module();
+                modules.add(module);
+                module.setDefKey(moduleDefKey);
+                module.setDefName(moduleDefName);
+                module.setEntities(new ArrayList<>());
+                module.setDicts(new ArrayList<>());
+                module.setDiagrams(new ArrayList<>());
+                //填充好本模块
+                fillModule(module,mapModule,entities,dicts,diagrams,findedEntities,findDiagrams,findedDicts,imgDir,imgExt);
+            }
+
+            //处理没有包含在模块中的表+关系图+数据字典
+            List<TableEntity> remainTableEntities = new ArrayList<>();
+            List<Diagram> remainDiagrams = new ArrayList<>();
+            List<Dict> remainDicts = new ArrayList<>();
+            for(TableEntity entity : entities){
+                //没有被找到过,说明不在模块分组里
+                if(findedEntities.indexOf(entity) < 0){
+                    remainTableEntities.add(entity);
+                }
+            }
+            for(Diagram diagram : diagrams){
+                if(findDiagrams.indexOf(diagram) < 0){
+                    remainDiagrams.add(diagram);
+                }
+            }
+            for(Dict dict : dicts){
+                if(findedDicts.indexOf(dict) < 0){
+                    remainDicts.add(dict);
+                }
+            }
+            //其他模块这个分组只有内容不空时,才能加到模型中去
+            Module otherModule = new Module();
+            otherModule.setDefKey("OTHER");
+            otherModule.setDefName("其他补充");
+            otherModule.setEntities(new ArrayList<>());
+            otherModule.setDiagrams(new ArrayList<>());
+            otherModule.setDicts(new ArrayList<>());
+            otherModule.setEntities(remainTableEntities);
+            otherModule.setDiagrams(remainDiagrams);
+            otherModule.setDicts(remainDicts);
+            if(!otherModule.isEmpty()){
+                modules.add(otherModule);
+            }
+
+        }
+
+
+        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
+        ConfigureBuilder builder = Configure.newBuilder();
+        Configure config = builder
+                .bind("entities", policy)
+                .bind("fields", policy)
+                .bind("items", policy)
+//                    .bind("image", new PictureRenderPolicy())
+                .addPlugin('>', new BookmarkRenderPolicy())
+//                .addPlugin('>', new BookmarkTextRenderData())
+                .build();
+
+
+//        System.out.println(JSONKit.toJsonString(project,true));
+        try(OutputStream osOutDocxFile = new FileOutputStream(outDocxFile);){
+            XWPFTemplate template = XWPFTemplate.compile(docTplFile,config).render(project);
+            template.write(osOutDocxFile);
+            osOutDocxFile.flush();
+            osOutDocxFile.close();
+            template.close();
+        }catch (Exception e){
+            throw e;
+        }
+
+
+    }
+
+    protected PictureRenderData createPictureRenderData(String imgDir,String imgExt,String diagramId){
+        String filePath = imgDir+"/"+diagramId+".png";
+        FileInputStream fileIn = null;
+        double width = 650.0;
+        double height = 400.0;
+        try {
+            File inFile = new File(filePath);
+            if(!inFile.exists()){
+                return null;
+            }
+            fileIn = new FileInputStream(inFile);
+            BufferedImage bufferedImage = ImageIO.read(fileIn);
+            width = bufferedImage.getWidth();
+            height = bufferedImage.getHeight();
+        } catch (IOException e) {
+            logger.error("读取图片文件出错",e);
+            return null;
+        } finally {
+            IOKit.close(fileIn);
+        }
+
+        PictureRenderData renderData = null;
+        try {
+            fileIn = new FileInputStream(filePath);
+//            renderData = new PictureRenderData(650, (int)(height/width*650), imgExt, fileIn);
+            PictureType pictureType = PictureType.suggestFileType(imgExt);
+            renderData = new PictureRenderData(650, (int)(height/width*650), pictureType, fileIn);
+        } catch (FileNotFoundException e) {
+            logger.error("图片文件不存在",e);
+            return null;
+        } finally {
+            IOKit.close(fileIn);
+        }
+
+        return renderData;
+
+    }
+
+    private void fillModule(Module module,
+                            Map<String, Object> mapModule,
+                            List<TableEntity> entities,
+                            List<Dict> dicts,
+                            List<Diagram> diagrams,
+                            List<TableEntity> findedEntities,
+                            List<Diagram> findDiagrams,
+                            List<Dict> findedDicts,
+                            String imgDir,
+                            String imgExt
+                            ) {
+        List<String> refEntities = (List<String>) mapModule.get("refEntities");
+        List<String> refViews = (List<String>) mapModule.get("refViews");
+        List<String> refDiagrams = (List<String>) mapModule.get("refDiagrams");
+        List<String> refDicts = (List<String>) mapModule.get("refDicts");
+
+        if (refEntities != null && refEntities.size() >= 0) {
+            for (String entityDefKey : refEntities) {
+                TableEntity entity = lookupTableEntity(entities, entityDefKey);
+                if (entity != null) {
+//                    entity.fillFieldsCalcValue();
+                    findedEntities.add(entity);
+                    module.getEntities().add(entity);
+                }
+            }
+        }
+
+        if (refDicts != null && refDicts.size() > 0) {
+            for (String dictDefKey : refDicts) {
+                Dict dict = lookupDict(dicts, dictDefKey);
+                if(dict != null){
+                    findedDicts.add(dict);
+                    module.getDicts().add(dict);
+                }
+            }
+        }
+
+        if(refDiagrams != null && refDiagrams.size() > 0){
+            for(String diagramId : refDiagrams){
+                Diagram diagram = lookupDiagram(diagrams,diagramId);
+                if(diagram != null){
+                    module.getDiagrams().add(diagram);
+                    findDiagrams.add(diagram);
+                    PictureRenderData renderData = createPictureRenderData(imgDir,imgExt,diagram.getId());
+                    if(renderData != null){
+                        diagram.setRenderData(renderData);
+                    }
+                }
+            }
+        }
+
+        for(TableEntity entity : entities){
+            entity.setDicts(dicts);
+            entity.fillFieldsCalcValue();
+        }
+        module.fillEntitiesRowNo();
+        module.fillDictsRowNo();
+    }
+
+    private TableEntity lookupTableEntity(List<TableEntity> entities,String entityDefKey){
+        for(TableEntity entity : entities){
+            if(entityDefKey.equalsIgnoreCase(entity.getId())){
+                return entity;
+            }
+        }
+        return null;
+    }
+
+    private Diagram lookupDiagram(List<Diagram> diagrams,String diagramId){
+        for(Diagram diagram : diagrams){
+            if(diagramId.equalsIgnoreCase(diagram.getId())){
+                return diagram;
+            }
+        }
+        return null;
+    }
+
+
+    private Dict lookupDict(List<Dict> dicts,String dictDefKey){
+        for(Dict dict : dicts){
+            if(dictDefKey.equalsIgnoreCase(dict.getId())){
+                return dict;
+            }
+        }
+        return null;
+    }
+
+    protected String parseFile(File sinerFile) throws IOException {
+        String jsonText = null;
+        try(InputStream inputStream = FileKit.openInputStream(sinerFile)) {
+            jsonText = IOKit.toString(inputStream, "UTF-8");
+//            mapObject = JSONKit.jsonToMap(jsonText);
+        } catch (IOException e) {
+            throw e;
+        }
+        return jsonText;
+    }
+}

+ 118 - 0
src/main/java/com/goer/common/command/impl/ParseDDLToTableImpl.java

@@ -0,0 +1,118 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.command.impl;
+
+import com.goer.common.chiner.model.TableEntity;
+import com.goer.common.command.AbstractDBCommand;
+import com.goer.common.command.ExecResult;
+import com.goer.common.utils.fisok.raw.kit.FileKit;
+import com.goer.common.utils.fisok.raw.kit.IOKit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/9/11
+ * @desc : 将DDL语句解析为表结构
+ */
+public class ParseDDLToTableImpl extends AbstractDBCommand<ExecResult> {
+    protected Logger logger = LoggerFactory.getLogger(getClass());
+    private static String DB_URL = "jdbc:h2:mem:MockChiner;DB_CLOSE_DELAY=-1";
+
+    public ExecResult exec(Map<String, String> params) {
+        String ddlFile = params.get("ddlFile");
+        ExecResult ret = new ExecResult();
+        Connection conn = null;
+        try {
+            String ddlContent = readDDLFile(ddlFile);
+
+            conn = DriverManager.getConnection(DB_URL);
+            createTable(conn,ddlContent);
+
+            String tables = getALLTablesString(conn);
+            IOKit.close(conn);//conn.getMetaData(); 只能使用一次,所以要重新取一次
+            conn = DriverManager.getConnection(DB_URL);
+            ret = parseTableDDL(conn,tables);
+        } catch (IOException | SQLException e) {
+            ret.setBody(e.getMessage());
+            ret.setStatus(ExecResult.FAILED);
+            logger.error(e.getMessage(),e);
+        } finally {
+            IOKit.close(conn);
+        }
+        return ret;
+    }
+
+    private String readDDLFile(String ddlFile) throws IOException {
+        File inFile = new File(ddlFile);
+        InputStream inputStream = null;
+        try {
+            inputStream = FileKit.openInputStream(inFile);
+            String ddlContent = IOKit.toString(inputStream,"UTF-8");
+            return ddlContent;
+        } catch (FileNotFoundException e) {
+            logger.error("读取DDL文件出错:"+ddlFile, e);
+            throw new RuntimeException(e);
+        } finally {
+            IOKit.close(inputStream);
+        }
+    }
+
+    private void createTable(Connection connection,String ddlScript) throws SQLException, IOException {
+        Statement stmt = connection.createStatement();
+        stmt.execute(ddlScript);
+    }
+
+    private String getALLTablesString(Connection connection){
+        Map<String,String> params = new HashMap<>();
+        DBReverseGetAllTablesListImpl cmd = new DBReverseGetAllTablesListImpl();
+        cmd.setDbConn(connection);
+        ExecResult ret = cmd.exec(new HashMap<>());
+        if(ret.getStatus().equals(ExecResult.SUCCESS)){
+            StringBuffer tables = new StringBuffer();
+            List<TableEntity> dataList = (List<TableEntity>)ret.getBody();
+            dataList.forEach(tableEntity->{
+                tables.append(tableEntity.getDefKey()).append(",");
+            });
+            if(tables.length()>0){
+                return tables.substring(0,tables.length()-1);
+            }
+        }
+        return "";
+    }
+
+    private ExecResult parseTableDDL(Connection connection,String tables){
+        Map<String,String> params = new HashMap<>();
+        params.put("tables",tables);
+
+        DBReverseGetTableDDLImpl cmd = new DBReverseGetTableDDLImpl();
+        cmd.setDbConn(connection);
+        ExecResult ret = cmd.exec(params);
+        return ret;
+    }
+}

+ 430 - 0
src/main/java/com/goer/common/command/impl/ParsePDMFileImpl.java

@@ -0,0 +1,430 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.command.impl;
+
+import com.goer.common.chiner.model.*;
+import com.goer.common.chiner.model.pdm.PDColumn;
+import com.goer.common.chiner.model.pdm.PDDomain;
+import com.goer.common.chiner.model.pdm.PDKey;
+import com.goer.common.chiner.model.pdm.PDTable;
+import com.goer.common.command.Command;
+import com.goer.common.command.ExecResult;
+import com.goer.common.command.kit.ConnParseKit;
+import com.goer.common.utils.fisok.raw.kit.StringKit;
+import com.goer.common.utils.fisok.raw.lang.ValueObject;
+import org.apache.commons.lang3.tuple.Pair;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.Node;
+import org.dom4j.io.SAXReader;
+import org.dom4j.tree.FlyweightProcessingInstruction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/14
+ * @desc : 解析PDM文件
+ */
+public class ParsePDMFileImpl implements Command<ExecResult> {
+    protected Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Override
+    public ExecResult exec(Map<String, String> params) {
+
+        String pdmFile = params.get("pdmFile");
+
+        SAXReader reader = new SAXReader();
+        File inFile = new File(pdmFile);
+
+        ExecResult ret = new ExecResult();
+        try {
+            Document document = reader.read(inFile);
+            List<Node> contentList = document.content();
+            if(contentList == null || contentList.size() == 0){
+                throw new IllegalStateException("文件"+pdmFile+"格式不正确");
+            }
+            FlyweightProcessingInstruction declearNode = (FlyweightProcessingInstruction)contentList.get(0);
+            String projectName = declearNode.getValue("Name");
+            String version = declearNode.getValue("version");
+            if(version.length()>3){
+                version = version.substring(0,4);
+            }
+            //低于16.5版本
+            if(version.compareTo("16.5") < 0){
+                throw new IllegalStateException("文件["+pdmFile+"]版本为["+version+"],不正确,请使用PowerDesigner-16.5以上版本的结果文件,如果没有,请你先用16.5的打开旧文件后另存为。");
+            }
+
+
+            List<Node> domainNodeList = document.selectNodes("/Model/o:RootObject/c:Children/o:Model/c:Domains/o:PhysicalDomain");
+//            List<Node> tableNodeList = document.selectNodes("/Model/o:RootObject/c:Children/*/c:Tables/o:Table");
+            List<Node> tableNodeList = document.selectNodes("//c:Tables/o:Table");  //使用通配置查找所有表
+
+            List<PDTable> tableList = new ArrayList<>();
+            List<PDDomain> domainList = new ArrayList<>();
+            for(Node domainNode : domainNodeList){
+                PDDomain domain = createDomain(domainNode);
+                if(domain == null){
+                    continue;
+                }
+                domainList.add(domain);
+            }
+            for(Node tableNode : tableNodeList){
+                PDTable table = createTable(tableNode,domainList);
+                if(table == null){
+                    continue;
+                }
+                tableList.add(table);
+            }
+
+
+            List<TableEntity> tableEntities = new ArrayList<>();
+            List<Domain> domains = new ArrayList<Domain>();
+
+            //填充模型数据
+            fillTableEntities(tableList,tableEntities);
+            fillDomains(domainList,domains);
+
+            ret.setBody(new HashMap<String,Object>(){{
+                put("projectName",projectName);
+                put("tables",tableEntities);
+                put("domains",domains);
+            }});
+            ret.setStatus(ExecResult.SUCCESS);
+        } catch (DocumentException e) {
+            String message = e.getMessage();
+            if(StringKit.isBlank(message)){
+                message = e.toString();
+            }
+            ret.setBody(message);
+            ret.setStatus(ExecResult.FAILED);
+            logger.error("",e);
+        }
+
+        return ret;
+    }
+
+    private void fillTableEntities(List<PDTable> tableList,List<TableEntity> tableEntities){
+        for(PDTable pdTable : tableList){
+            TableEntity te = new TableEntity();
+            te.setDefKey(pdTable.getCode());
+            te.setDefName(pdTable.getName());
+            te.setComment(pdTable.getComment());
+            te.setRowNo(tableList.indexOf(pdTable)+1);
+
+            List<PDColumn> pdColumns = pdTable.getColumns();
+            for(int i=0;i<pdColumns.size();i++){
+                PDColumn pdColumn = pdColumns.get(i);
+                ColumnField field = new ColumnField();
+                field.setDefKey(pdColumn.getCode());
+                field.setDefName(pdColumn.getName());
+                field.setComment(pdColumn.getComment());
+                field.setDomain(pdColumn.getDomain());
+                field.setType(pdColumn.getDataType());
+                field.setLen(pdColumn.getLength());
+                field.setScale(pdColumn.getPrecision());
+                field.setPrimaryKey(pdColumn.getPrimaryKey());
+                field.setNotNull(pdColumn.getMandatory());
+                field.setHideInGraph(i>15);
+                //名称和注释相同的情况下,只保留名称
+                if(StringKit.nvl(field.getComment(),"").equalsIgnoreCase(field.getDefName())){
+                    field.setComment("");
+                }
+                te.getFields().add(field);
+            }
+            List<TableIndex> indexes = new ArrayList<>();
+            List<PDKey> pdKeys = pdTable.getKeys();
+            for(PDKey pdKey : pdKeys){
+                TableIndex index = new TableIndex();
+                index.setDefKey(pdKey.getCode());
+                index.setDefName(pdKey.getName());
+                index.setUnique(false);
+
+                List<PDColumn> pdkColumns = pdKey.getColumns();
+                for(PDColumn pdkColumn : pdkColumns){
+                    TableIndexColumnField idxField = new TableIndexColumnField();
+                    idxField.setFieldDefKey(pdkColumn.getCode());
+                    index.getFields().add(idxField);
+                }
+                indexes.add(index);
+            }
+            te.setIndexes(indexes);
+            te.fillFieldsCalcValue();
+            tableEntities.add(te);
+        }
+    }
+
+    private Map<String,String> dataTypeMap = new HashMap<String,String>(){{
+        put("VARCHAR","string");
+        put("NVARCHAR","string");
+        put("VARCHAR2","string");
+        put("NVARCHAR2","string");
+        put("NUMBER","double");
+        put("NUMERIC","double");
+        put("DECIMAL","double");
+        put("INTEGER","int");
+        put("INT","int");
+        put("DATE","date");
+        put("DATETIME","date");
+        put("TIMESTAMP","date");
+        put("BLOB","bytes");
+        put("VARBINARY","bytes");
+        put("BYTEA","bytes");
+        put("TEXT","largeText");
+        put("CLOB","largeText");
+    }};
+    private String matchDataType(String dataType){
+        String retType = dataTypeMap.get(dataType.toUpperCase());
+        return retType == null?"string":retType;
+    }
+    private void fillDomains(List<PDDomain> domainList,List<Domain> domains){
+        for(PDDomain pdDomain : domainList){
+            String dataType = pdDomain.getDataType();
+            String applyFor = matchDataType(dataType);
+
+            Domain domain = new Domain();
+            domain.setApplyFor(applyFor);
+            domain.setDefKey(pdDomain.getCode());
+            domain.setDefName(pdDomain.getName());
+            domain.setLen(pdDomain.getLength());
+            domain.setScale(pdDomain.getPrecision());
+            domain.setUiHint(new HashMap<>());
+
+            domains.add(domain);
+        }
+    }
+
+    public PDTable createTable(Node node, List<PDDomain> domains){
+        String id = getAttributeValue(node,"Id");
+        String objectId = getChildNodeValue(node,"a:ObjectID").strValue();
+        String name = getChildNodeValue(node,"a:Name").strValue("");
+        String code = getChildNodeValue(node,"a:Code").strValue("");
+        String comment = getChildNodeValue(node,"a:Comment").strValue("");
+        Date creationDate = getChildNodeValue(node,"a:CreationDate").dateValue();
+        String creator = getChildNodeValue(node,"a:Creator").strValue();
+        Date modificationDate = getChildNodeValue(node,"a:ModificationDate").dateValue();
+        String modifier = getChildNodeValue(node,"a:Modifier").strValue();
+        if(StringKit.isBlank(code) && StringKit.isBlank(name)){
+            return null;
+        }
+
+        PDTable table = new PDTable();
+        table.setId(id);
+        table.setObjectID(objectId);
+        table.setCode(code);
+        table.setName(name);
+        table.setComment(comment);
+        table.setCreationDate(creationDate);
+        table.setCreator(creator);
+        table.setModificationDate(modificationDate);
+        table.setModifier(modifier);
+        //当代码和名称一样,且注释不为空时,作下转换
+        if(code.equalsIgnoreCase(name) && StringKit.isNotBlank(comment)){
+            Pair<String,String> columnRemarks = ConnParseKit.parseNameAndComment(comment);
+            name = columnRemarks.getLeft();
+            comment = columnRemarks.getRight();
+            table.setName(name);
+            table.setComment(comment);
+        }
+
+        //处理列
+        List<Node> columnNodeList = node.selectNodes("c:Columns/o:Column");
+        for(Node columnNode : columnNodeList){
+            PDColumn column = createColumn(columnNode);
+            if(column == null){
+                continue;
+            }
+            table.getColumns().add(column);
+            //处理关联的数据域
+            Node domainNode = columnNode.selectSingleNode("c:Domain/o:PhysicalDomain");
+            String domainRef = getAttributeValue(domainNode,"Ref");
+            if(StringKit.isNotBlank(domainRef)){
+                for(PDDomain domain : domains){
+                    if(domainRef.equalsIgnoreCase(domain.getId())){
+                        column.setDomain(domain.getCode());
+                    }
+                }
+            }
+        }
+
+        //处理索引
+        List<Node> keyNodeList = node.selectNodes("c:Keys/o:Key");
+        for(Node keyNode : keyNodeList){
+            String keyId = getAttributeValue(keyNode,"Id");
+            String keyObjectId = getChildNodeValue(keyNode,"a:ObjectID").strValue();
+            String keyName = getChildNodeValue(keyNode,"a:Name").strValue("");
+            String keyCode = getChildNodeValue(keyNode,"a:Code").strValue("");
+            Date keyCreationDate = getChildNodeValue(keyNode,"a:CreationDate").dateValue();
+            String keyCreator = getChildNodeValue(keyNode,"a:Creator").strValue();
+            Date keyModificationDate = getChildNodeValue(keyNode,"a:ModificationDate").dateValue();
+            String keyModifier = getChildNodeValue(keyNode,"a:Modifier").strValue();
+            if(StringKit.isBlank(code) && StringKit.isBlank(name)){
+                continue;
+            }
+
+            PDKey key = new PDKey();
+            key.setId(keyId);
+            key.setObjectID(keyObjectId);
+            key.setCode(keyCode);
+            key.setName(keyName);
+            key.setCreationDate(keyCreationDate);
+            key.setCreator(keyCreator);
+            key.setModificationDate(keyModificationDate);
+            key.setModifier(keyModifier);
+
+            List<Node> keyColList = keyNode.selectNodes("c:Key.Columns/o:Column");
+            for(Node colNode : keyColList){
+                String colRef = getAttributeValue(colNode,"Ref");
+                for(PDColumn column : table.getColumns()){
+                    if(colRef.equalsIgnoreCase(column.getId())){
+                        key.getColumns().add(column);
+                    }
+                }
+            }
+            table.getKeys().add(key);
+        }
+
+        //处理是否主键
+        List<Node> pkNodeList = node.selectNodes("c:PrimaryKey/o:Key");
+        for(Node pkNode : pkNodeList){
+            String pkRef = getAttributeValue(pkNode,"Ref");
+            if(StringKit.isNotBlank(pkRef)){
+                for(PDKey key : table.getKeys()){
+                    if(pkRef.equalsIgnoreCase(key.getId())){
+                        for(PDColumn column : key.getColumns()){
+                            column.setPrimaryKey(true);
+                        }
+                    }
+                }
+            }
+        }
+        return table;
+    }
+
+    public PDColumn createColumn(Node node){
+        String id = getAttributeValue(node,"Id");
+        String objectId = getChildNodeValue(node,"a:ObjectID").strValue();
+        String code = getChildNodeValue(node,"a:Code").strValue("");
+        String name = getChildNodeValue(node,"a:Name").strValue("");
+        String comment = getChildNodeValue(node,"a:Comment").strValue("");
+        Date creationDate = getChildNodeValue(node,"a:CreationDate").dateValue();
+        String creator = getChildNodeValue(node,"a:Creator").strValue();
+        Date modificationDate = getChildNodeValue(node,"a:ModificationDate").dateValue();
+        String modifier = getChildNodeValue(node,"a:Modifier").strValue();
+        String dataType = getChildNodeValue(node,"a:DataType").strValue("");
+        Integer length = getChildNodeValue(node,"a:Length").intValue();
+        Integer precision = getChildNodeValue(node,"a:Precision").intValue();
+        if(StringKit.isBlank(code) && StringKit.isBlank(name)){
+            return null;
+        }
+
+
+        PDColumn column = new PDColumn();
+        column.setId(id);
+        column.setObjectID(objectId);
+        column.setCode(code);
+        column.setName(name);
+        column.setComment(comment);
+        column.setCreationDate(creationDate);
+        column.setCreator(creator);
+        column.setModificationDate(modificationDate);
+        column.setModifier(modifier);
+        column.setDataType(cleanDataType(dataType));
+        column.setLength(length);
+        column.setPrecision(precision);
+        //当代码和名称一样,且注释不为空时,作下转换
+        if(code.equalsIgnoreCase(name) && StringKit.isNotBlank(comment)){
+            Pair<String,String> columnRemarks = ConnParseKit.parseNameAndComment(comment);
+            name = columnRemarks.getLeft();
+            comment = columnRemarks.getRight();
+            column.setName(name);
+            column.setComment(comment);
+        }
+
+        return column;
+    }
+
+    public PDDomain createDomain(Node node){
+        String id = getAttributeValue(node,"Id");
+        String objectId = getChildNodeValue(node,"a:ObjectID").strValue();
+        String name = getChildNodeValue(node,"a:Name").strValue();
+        String code = getChildNodeValue(node,"a:Code").strValue();
+        Date creationDate = getChildNodeValue(node,"a:CreationDate").dateValue();
+        String creator = getChildNodeValue(node,"a:Creator").strValue();
+        Date modificationDate = getChildNodeValue(node,"a:ModificationDate").dateValue();
+        String modifier = getChildNodeValue(node,"a:Modifier").strValue();
+        String dataType = getChildNodeValue(node,"a:DataType").strValue();
+        Integer length = getChildNodeValue(node,"a:Length").intValue();
+        Integer precision = getChildNodeValue(node,"a:Precision").intValue();
+        if(StringKit.isBlank(code) && StringKit.isBlank(name)){
+            return null;
+        }
+
+        PDDomain domain = new PDDomain();
+        domain.setId(id);
+        domain.setObjectID(objectId);
+        domain.setCode(code);
+        domain.setName(name);
+        domain.setCreationDate(creationDate);
+        domain.setCreator(creator);
+        domain.setModificationDate(modificationDate);
+        domain.setModifier(modifier);
+        domain.setDataType(cleanDataType(dataType));
+        domain.setLength(length);
+        domain.setPrecision(precision);
+        return domain;
+    }
+
+    /**
+     * 取节点字串值
+     * @param node
+     * @param childNodeName
+     * @return
+     */
+    public ValueObject getChildNodeValue(Node node, String childNodeName){
+        Node childNode = node.selectSingleNode(childNodeName);
+        if(childNode != null && childNode instanceof Element){
+            Element element = (Element)childNode;
+            return ValueObject.valueOf(element.getStringValue());
+        }
+        return ValueObject.valueOf(null);
+    }
+
+    /**
+     * 取节点属性值
+     * @param node
+     * @param attributeName
+     * @return
+     */
+    public String getAttributeValue(Node node,String attributeName){
+        if(node != null && node instanceof Element){
+            Element element = (Element)node;
+            return element.attribute(attributeName).getValue();
+        }
+        return null;
+    }
+
+    public String cleanDataType(String dataType){
+        if(dataType.indexOf("(")>0 && dataType.indexOf(")")>0){
+            return dataType.substring(0,dataType.indexOf("("));
+        }
+        return dataType;
+    }
+}

+ 63 - 0
src/main/java/com/goer/common/command/impl/PingLoadDriverClassImpl.java

@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.command.impl;
+
+import com.goer.common.command.AbstractDBCommand;
+import com.goer.common.command.ExecResult;
+import com.goer.common.utils.fisok.raw.kit.JdbcKit;
+import com.goer.project.model.modelDbs.domain.ModelDbs;
+
+import java.sql.Connection;
+import java.util.Map;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/12
+ * @desc : 数据库驱动程序加载测试
+ */
+public class PingLoadDriverClassImpl extends AbstractDBCommand<ExecResult> {
+    @Override
+    public ExecResult exec(Map<String, String> params) {
+        super.init(params);
+        ExecResult ret = new ExecResult();
+
+        try {
+            Class.forName(driverClassName);
+            ret.setStatus(ExecResult.SUCCESS);
+        } catch (ClassNotFoundException e) {
+            logger.error("", e);
+            ret.setStatus(ExecResult.FAILED);
+            ret.setBody("驱动加载失败,驱动类不存在(ClassNotFoundException)!出错消息:" + e.getMessage());
+            return ret;
+        }
+
+        Connection conn = null;
+        try {
+            conn = createConnect();
+            ret.setStatus(ExecResult.SUCCESS);
+            ret.setBody("连接成功");
+        } catch (Exception e) {
+            ret.setStatus(ExecResult.FAILED);
+            ret.setBody("连接失败!出错消息:" + e.getMessage());
+            logger.error("", e);
+        } finally {
+            JdbcKit.close(conn);
+        }
+
+        return ret;
+    }
+
+}

+ 67 - 0
src/main/java/com/goer/common/command/kit/ConnParseKit.java

@@ -0,0 +1,67 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.command.kit;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/14
+ * @desc : 连接以及解析处理工具类
+ */
+public abstract class ConnParseKit {
+    private static Logger logger = LoggerFactory.getLogger(ConnParseKit.class);
+
+    /**
+     * 从注释文字中解析表的业务名(中文名)
+     *
+     * @param remarks
+     * @return Left为字段名,Right为字段注释
+     */
+    public static Pair parseNameAndComment(String remarks) {
+        String[] delimters = new String[]{" ", ",", ",", ";", "\t", "\n"};
+
+        //有括号的字段,不解析其中的注释了
+        if (remarks.indexOf("(") > 0
+                && remarks.indexOf(")") < 0
+                && remarks.indexOf("(") < remarks.indexOf(")")
+        ) {
+            return Pair.of(remarks, "");
+        }
+
+
+        Pair<String, String> pair = null;
+        for (int i = 0; i < delimters.length; i++) {
+            String delimter = delimters[i];
+            int idxDelimter = remarks.indexOf(delimter);
+            if (idxDelimter > 0) {
+                String left = remarks.substring(0, idxDelimter);
+                String right = remarks.substring(idxDelimter + 1);
+                pair = Pair.of(left, right);
+            }
+            if (pair != null) {
+                break;
+            }
+        }
+        if (pair == null) {
+            pair = Pair.of(remarks, "");
+        }
+        return pair;
+    }
+}

+ 405 - 0
src/main/java/com/goer/common/dialect/DBDialect.java

@@ -0,0 +1,405 @@
+package com.goer.common.dialect;
+
+import com.goer.common.chiner.model.ColumnField;
+import com.goer.common.chiner.model.TableEntity;
+import com.goer.common.chiner.model.TableIndex;
+import com.goer.common.chiner.model.TableIndexColumnField;
+import com.goer.common.command.kit.ConnParseKit;
+import com.goer.common.utils.fisok.raw.kit.JdbcKit;
+import com.goer.common.utils.fisok.raw.kit.StringKit;
+import org.apache.commons.lang3.tuple.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/14
+ * @desc : 数据库方言抽象类
+ */
+public class DBDialect {
+
+    protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * 获取数据库SchemaPattern
+     * @param conn
+     * @return
+     * @throws SQLException
+     */
+    public String getSchemaPattern(Connection conn) throws SQLException{
+        return null;
+    };
+
+    /**
+     * 获取数据库TableNamePattern
+     * @param conn
+     * @return
+     * @throws SQLException
+     */
+    public String getTableNamePattern(Connection conn) throws SQLException{
+        return null;
+    }
+
+
+    /**
+     * 将resultset,主键的resultset装到一个二元组中,并返回
+     * @param conn
+     * @param tableName
+     * @return
+     * @throws SQLException
+     */
+    public Pair getColumnAndPrimaryKeyResultSetPair(Connection conn,String tableName) throws SQLException {
+        DatabaseMetaData connMetaData = conn.getMetaData();
+        String schema = getSchemaPattern(conn);
+
+        ResultSet rs = connMetaData.getColumns(conn.getCatalog(), schema,tableName, "%");
+        ResultSet pkRs = connMetaData.getPrimaryKeys(conn.getCatalog(),schema,tableName);
+
+        Pair<ResultSet,ResultSet> pair = Pair.of(rs,pkRs);
+
+        return pair;
+    }
+
+    /**
+     * 根据结果集,创建表实体对象,仅填充表名,中文名,注释信息
+     * @param connection
+     * @param rs
+     * @return
+     */
+    public TableEntity createTableEntity(Connection connection, ResultSet rs) throws SQLException {
+        TableEntity entity = new TableEntity();
+        fillTableEntityNoColumn(entity, connection,rs);
+        if (StringKit.isNotBlank(entity.getDefKey())) {
+            return entity;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 传入一个空对象,填充表名,中文名,注释信息
+     * @param tableEntity
+     * @param rs
+     * @throws SQLException
+     */
+    public void fillTableEntityNoColumn(TableEntity tableEntity, Connection connection,ResultSet rs) throws SQLException {
+        String tableName = rs.getString("TABLE_NAME");
+        String remarks = StringKit.trim(rs.getString("REMARKS"));
+        String defKey = tableName;
+        String defName = remarks;
+        String comment = "";
+
+        //如果remark中有分号等分割符,则默认之后的就是注释说明文字
+        if(StringKit.isNotBlank(remarks)){
+            Pair<String, String> pair = ConnParseKit.parseNameAndComment(remarks);
+            defName = pair.getLeft();
+            comment = pair.getRight();
+        }
+        tableEntity.setDefKey(defKey);
+        tableEntity.setDefName(defName);
+        tableEntity.setComment(comment);
+
+    }
+
+    /**
+     * 传入表名,中文名,注释信息,获取字段明细,索引信息
+     * @param tableEntity
+     * @param conn
+     */
+    public void fillTableEntity(TableEntity tableEntity, Connection conn) throws SQLException {
+        String tableName = tableEntity.getDefKey();
+
+        ResultSet rs = null;
+//        Statement stmt = null;
+        ResultSet pkRs = null;
+//        Statement pkStmt = null;
+
+        try {
+            Pair<ResultSet,ResultSet> pair = getColumnAndPrimaryKeyResultSetPair(conn,tableName);
+            rs = pair.getLeft();
+            pkRs = pair.getRight();
+//            stmt = rs.getStatement();
+//            pkStmt = pkRs.getStatement();
+            Set<String> pkSet = new HashSet<String>();
+            while(pkRs.next()){
+                String columnName = pkRs.getString("COLUMN_NAME");
+                pkSet.add(columnName);
+            }
+
+            while(rs.next()){
+                ColumnField field = new ColumnField();
+                fillColumnField(field,conn,rs,pkSet);
+                tableEntity.getFields().add(field);
+            }
+            fillTableIndexes(tableEntity,conn);
+        } catch (SQLException e) {
+            logger.error("读取数据表"+tableName+"的字段明细出错",e);
+            throw new RuntimeException("读取数据表"+tableName+"的字段明细出错",e);
+        } finally {
+//            JdbcKit.close(stmt);
+            JdbcKit.close(rs);
+//            JdbcKit.close(pkStmt);
+            JdbcKit.close(pkRs);
+        }
+    }
+
+    /**
+     * 填充列数据
+     * TABLE_CAT String => 表类别(可为 null)
+     * TABLE_SCHEM String => 表模式(可为 null)
+     * TABLE_NAME String => 表名称
+     * COLUMN_NAME String => 列名称
+     * DATA_TYPE int => 来自 java.sql.Types 的 SQL 类型
+     * TYPE_NAME String => 数据源依赖的类型名称,对于 UDT,该类型名称是完全限定的
+     * COLUMN_SIZE int => 列的大小。
+     * BUFFER_LENGTH 未被使用。
+     * DECIMAL_DIGITS int => 小数部分的位数。对于 DECIMAL_DIGITS 不适用的数据类型,则返回 Null。
+     * NUM_PREC_RADIX int => 基数(通常为 10 或 2)
+     * NULLABLE int => 是否允许使用 NULL。
+     * columnNoNulls - 可能不允许使用 NULL 值
+     * columnNullable - 明确允许使用 NULL 值
+     * columnNullableUnknown - 不知道是否可使用 null
+     * REMARKS String => 描述列的注释(可为 null)
+     * COLUMN_DEF String => 该列的默认值,当值在单引号内时应被解释为一个字符串(可为 null)
+     * SQL_DATA_TYPE int => 未使用
+     * SQL_DATETIME_SUB int => 未使用
+     * CHAR_OCTET_LENGTH int => 对于 char 类型,该长度是列中的最大字节数
+     * ORDINAL_POSITION int => 表中的列的索引(从 1 开始)
+     * IS_NULLABLE String => ISO 规则用于确定列是否包括 null。
+     * YES --- 如果参数可以包括 NULL
+     * NO --- 如果参数不可以包括 NULL
+     * 空字符串 --- 如果不知道参数是否可以包括 null
+     * SCOPE_CATLOG String => 表的类别,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为 null)
+     * SCOPE_SCHEMA String => 表的模式,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为 null)
+     * SCOPE_TABLE String => 表名称,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为 null)
+     * SOURCE_DATA_TYPE short => 不同类型或用户生成 Ref 类型、来自 java.sql.Types 的 SQL 类型的源类型(如果 DATA_TYPE 不是 DISTINCT 或用户生成的 REF,则为 null)
+     * IS_AUTOINCREMENT String => 指示此列是否自动增加
+     * YES --- 如果该列自动增加
+     * NO --- 如果该列不自动增加
+     * 空字符串 --- 如果不能确定该列是否是自动增加参数
+     * COLUMN_SIZE 列表示给定列的指定列大小。对于数值数据,这是最大精度。对于字符数据,这是字符长度。对于日期时间数据类型,这是 String 表示形式的字符长度(假定允许的最大小数秒组件的精度)。对于二进制数据,这是字节长度。对于 ROWID 数据类型,这是字节长度。对于列大小不适用的数据类型,则返回 Null。
+     *
+     *
+     * 参数:
+     * catalog - 类别名称;它必须与存储在数据库中的类别名称匹配;该参数为 "" 表示获取没有类别的那些描述;为 null 则表示该类别名称不应该用于缩小搜索范围
+     * schemaPattern - 模式名称的模式;它必须与存储在数据库中的模式名称匹配;该参数为 "" 表示获取没有模式的那些描述;为 null 则表示该模式名称不应该用于缩小搜索范围
+     * tableNamePattern - 表名称模式;它必须与存储在数据库中的表名称匹配
+     * columnNamePattern - 列名称模式;它必须与存储在数据库中的列名称匹配
+     * @param field
+     * @param rs
+     * @throws SQLException
+     */
+    public void fillColumnField(ColumnField field,Connection conn, ResultSet rs, Set<String> pkSet) throws SQLException {
+
+        String colName = rs.getString("COLUMN_NAME");
+        String remarks = StringKit.trim(rs.getString("REMARKS"));
+        String typeName = rs.getString("TYPE_NAME");
+        int dataType = rs.getInt("DATA_TYPE");
+        int columnSize = rs.getInt("COLUMN_SIZE");
+        Integer decimalDigits = rs.getInt("DECIMAL_DIGITS");
+        String defaultValue = rs.getString("COLUMN_DEF");
+        String isNullable = rs.getString("IS_NULLABLE");
+        String isAutoincrement = "NO";
+        defaultValue = StringKit.nvl(parseDefaultValue(dataType,defaultValue),"");
+
+
+        String label = remarks;
+        String comment = null;
+        if(StringKit.isNotBlank(remarks)){
+            Pair<String,String> columnRemarks = ConnParseKit.parseNameAndComment(remarks);
+            label = columnRemarks.getLeft();
+            comment = columnRemarks.getRight();
+        }
+
+        field.setDefKey(colName);
+        field.setDefName(label);
+        field.setComment(comment);
+        field.setType(typeName);
+
+        if(columnSize > 0){
+            field.setLen(columnSize);
+        }
+        if(decimalDigits<=0){
+            field.setScale(null);
+        }else{
+            field.setScale(decimalDigits);
+        }
+        //不需要长度的数据类型,把数据类型清除掉,防止部分数据库解析出有长度的情况
+        if(withoutLenDataType(dataType)){
+            field.setLen(null);
+            field.setScale(null);
+        }
+
+        field.setPrimaryKey(pkSet.contains(colName));
+        field.setNotNull(!"YES".equalsIgnoreCase(isNullable));
+        field.setAutoIncrement(!"NO".equalsIgnoreCase(isAutoincrement));
+        field.setDefaultValue(defaultValue);
+    }
+
+    /**
+     * 不含长度的数据类型,这种数据类型不需要设置长度以及小数位
+     * @param dataType
+     * @return
+     */
+    protected boolean withoutLenDataType(int dataType) {
+        int[] array = {Types.DATE, Types.TIMESTAMP, Types.TIME,
+                Types.TIME_WITH_TIMEZONE,Types.TIMESTAMP_WITH_TIMEZONE,
+                Types.CLOB,Types.BLOB, Types.NCLOB,
+                Types.LONGVARCHAR,Types.LONGVARBINARY
+        };
+        for(int item : array){
+            if(item == dataType){
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public String parseDefaultValue(Integer dataType,String defaultValue){
+        if(StringKit.isNotBlank(defaultValue)){
+            if(defaultValue.indexOf("'::") > 0){
+                defaultValue = defaultValue.substring(0,defaultValue.indexOf("'::")+1);
+            }
+            //如果是被''圈住,说明是字串,不需要处理
+            if(defaultValue.startsWith("'") && defaultValue.endsWith("'")){
+            }else{
+                //如果全是数字,并且不以0开始,那么就是数字,不需要加双单引号
+//                if(defaultValue.matches("[0-9]+") && !defaultValue.startsWith("0")){
+                if(JdbcKit.isNumeric(dataType)){
+                }else{
+                    defaultValue = "'"+defaultValue+"'";
+                }
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * 填充数据表的索引
+     * @param tableEntity
+     * @param conn
+     * @throws SQLException
+     */
+    public void fillTableIndexes(TableEntity tableEntity, Connection conn) throws SQLException {
+        String table = tableEntity.getDefKey();
+        DatabaseMetaData dbMeta = conn.getMetaData();
+        ResultSet rs = dbMeta.getIndexInfo(null,null,table,false,false);
+
+        while (rs.next()) {
+            String tableName = rs.getString("TABLE_NAME");
+            String indexName = rs.getString("INDEX_NAME");
+            String columnName = rs.getString("COLUMN_NAME");
+            String nonUnique = rs.getString("NON_UNIQUE");
+            String ascOrDesc = rs.getString("ASC_OR_DESC");
+
+            if(!table.equalsIgnoreCase(tableName)){
+                continue;
+            }
+            if(StringKit.isBlank(indexName)){
+                continue;
+            }
+            if(StringKit.isBlank(columnName)){
+                continue;
+            }
+
+            TableIndex index = tableEntity.lookupIndex(indexName);
+            if(index == null){
+                index = new TableIndex();
+                index.setDefKey(indexName);
+                index.setUnique(!"1".equalsIgnoreCase(nonUnique));
+                tableEntity.getIndexes().add(index);
+            }
+
+            TableIndexColumnField ticf = index.lookupField(columnName);
+            if(ticf != null){
+                continue;
+            }
+            ticf = new TableIndexColumnField();
+            ticf.setFieldDefKey(columnName);
+            ticf.setAscOrDesc(ascOrDesc);
+            index.getFields().add(ticf);
+
+        }
+
+        JdbcKit.close(rs.getStatement());
+        JdbcKit.close(rs);
+    }
+
+    /**
+     * 取所有的数据表清单
+     * @param conn
+     * @return
+     */
+    public List<TableEntity> getAllTables(Connection conn) throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+//        String schemaPattern = null;
+        String schemaPattern = getSchemaPattern(conn);
+        String tableNamePattern = getTableNamePattern(conn);
+        String catalog = conn.getCatalog();
+
+        ResultSet rs = meta.getTables(catalog, schemaPattern, tableNamePattern, new String[]{"TABLE"});
+        List<TableEntity> tableEntities = new ArrayList<TableEntity>();
+        while (rs.next()) {
+            String tableName = rs.getString("TABLE_NAME");
+            /**
+             *  SQL Server系统保留表
+             *  trace_xe_action_map,trace_xe_event_map
+             */
+            if (!"PDMAN_DB_VERSION".equalsIgnoreCase(tableName)
+                    && !"trace_xe_action_map".equalsIgnoreCase(tableName)
+                    && !"trace_xe_event_map".equalsIgnoreCase(tableName)){
+                TableEntity entity = createTableEntity(conn,rs);
+                if(entity != null){
+                    tableEntities.add(entity);
+                }
+            }else{
+                continue;
+            }
+        }
+        return tableEntities;
+    }
+
+    /**
+     * 根据表名,创建数据表实体的字段及索引
+     * @param conn
+     * @param meta
+     * @param tableName
+     * @return
+     * @throws SQLException
+     */
+    public TableEntity createTableEntity(Connection conn,DatabaseMetaData meta,String tableName) throws SQLException {
+        ResultSet rs = null;
+        try{
+            String schemaPattern = getSchemaPattern(conn);
+//            String schemaPattern = "jence_user";
+            rs = meta.getTables(null, schemaPattern, tableName.toLowerCase(), new String[]{"TABLE"});
+            if(rs.next()) {
+                TableEntity tableEntity = createTableEntity(conn, rs);
+                fillTableEntity(tableEntity,conn);
+                JdbcKit.close(rs);
+                return tableEntity;
+            }else{
+                //如果全小写不行,就来试试全大写
+                rs = meta.getTables(null, schemaPattern, tableName.toUpperCase(), new String[]{"TABLE"});
+                if(rs.next()) {
+                    TableEntity tableEntity = createTableEntity(conn, rs);
+                    fillTableEntity(tableEntity,conn);
+                    return tableEntity;
+                }
+            }
+        }catch (SQLException e){
+            throw e;
+        }finally {
+            JdbcKit.close(rs);
+        }
+        return null;
+    }
+
+}

+ 55 - 0
src/main/java/com/goer/common/dialect/DBDialectMatcher.java

@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.dialect;
+
+import com.goer.common.dialect.DBDialect;
+import com.goer.common.dialect.impl.*;
+import com.goer.common.utils.fisok.sqloy.core.DBType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/14
+ * @desc :
+ */
+public class DBDialectMatcher {
+
+    private static Map<DBType,DBDialect> dbTypeMap = new HashMap<DBType,DBDialect>(){{
+        put(DBType.MYSQL,new DBDialectMySQL());
+        put(DBType.ORACLE,new DBDialectOracle());
+        put(DBType.POSTGRESQL,new DBDialectPostgreSQL());
+        put(DBType.DB2,new DBDialectDB2());
+        put(DBType.DM,new DBDialectDM());
+        put(DBType.SQL_SERVER,new DBDialectSQLServer());
+        put(DBType.KINGBASE,new DBDialectKingbase());
+        put(DBType.SQLITE,new DBDialectSQLite());
+    }};
+
+    /**
+     * 数据库方言解析类,默认的情况下,使用默认的
+     * @param dbType
+     * @return
+     */
+    public static DBDialect getDBDialect(DBType dbType){
+        DBDialect dbDialect = dbTypeMap.get(dbType);
+        if(dbDialect == null){
+            dbDialect = new DBDialect();
+        }
+        return dbDialect;
+    }
+}

+ 43 - 0
src/main/java/com/goer/common/dialect/impl/DBDialectDB2.java

@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.dialect.impl;
+
+import com.goer.common.dialect.DBDialect;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/19
+ * @desc : DB2数据库方言
+ */
+public class DBDialectDB2 extends DBDialect {
+    @Override
+    public String getSchemaPattern(Connection conn) throws SQLException {
+        return conn.getMetaData().getUserName().toUpperCase();
+//        return "jence_user";
+//        return null;
+    }
+
+    @Override
+    public String getTableNamePattern(Connection conn) throws SQLException {
+        return "%";
+    }
+
+}

+ 75 - 0
src/main/java/com/goer/common/dialect/impl/DBDialectDM.java

@@ -0,0 +1,75 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.dialect.impl;
+
+import com.goer.common.chiner.model.TableEntity;
+import com.goer.common.dialect.DBDialect;
+import com.goer.common.utils.fisok.raw.kit.StringKit;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/19
+ * @desc : 达梦数据库方言
+ */
+public class DBDialectDM extends DBDialect {
+    @Override
+    public String getSchemaPattern(Connection conn) throws SQLException {
+        String schemaPattern = conn.getMetaData().getUserName().toUpperCase();
+        if (StringKit.isNotBlank(schemaPattern)) {
+            schemaPattern = schemaPattern.toUpperCase();
+        }
+        return schemaPattern;
+    }
+
+    /**
+     * 取所有的数据表清单
+     * @param conn
+     * @return
+     */
+    public List<TableEntity> getAllTables(Connection conn) throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+//        String schemaPattern = null;
+        String schemaPattern = getSchemaPattern(conn);
+        String tableNamePattern = getTableNamePattern(conn);
+        String catalog = conn.getCatalog();
+
+        ResultSet rs = meta.getTables(catalog, schemaPattern, tableNamePattern, new String[]{"TABLE"});
+        List<TableEntity> tableEntities = new ArrayList<TableEntity>();
+        while (rs.next()) {
+            String tableName = rs.getString("TABLE_NAME");
+            if(tableName.startsWith("#")){
+                continue;
+            }
+            if (!tableName.equalsIgnoreCase("PDMAN_DB_VERSION")){
+                TableEntity entity = createTableEntity(conn,rs);
+                if(entity != null){
+                    tableEntities.add(entity);
+                }
+            }else{
+                continue;
+            }
+        }
+        return tableEntities;
+    }
+}

+ 68 - 0
src/main/java/com/goer/common/dialect/impl/DBDialectKingbase.java

@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.dialect.impl;
+
+import com.goer.common.chiner.model.TableEntity;
+import com.goer.common.dialect.DBDialect;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/08/19
+ * @desc : 人大金仓Kinbbase方言
+ */
+public class DBDialectKingbase extends DBDialect {
+    public List<TableEntity> getAllTables(Connection conn) throws SQLException {
+        DatabaseMetaData meta = conn.getMetaData();
+
+        String schemaPattern = getSchemaPattern(conn);
+        String tableNamePattern = getTableNamePattern(conn);
+        String catalog = conn.getCatalog();
+
+        ResultSet rs = meta.getTables(catalog, schemaPattern, tableNamePattern, new String[]{"TABLE"});
+        List<TableEntity> tableEntities = new ArrayList<TableEntity>();
+        while (rs.next()) {
+            String tableName = rs.getString("TABLE_NAME");
+            /**
+             *  SQL Server系统保留表
+             *  trace_xe_action_map,trace_xe_event_map
+             */
+            if (!tableName.equalsIgnoreCase("PDMAN_DB_VERSION")
+                    && !tableName.equalsIgnoreCase("sysmac_compartment")
+                    && !tableName.equalsIgnoreCase("sysmac_label")
+                    && !tableName.equalsIgnoreCase("sysmac_level")
+                    && !tableName.equalsIgnoreCase("sysmac_obj")
+                    && !tableName.equalsIgnoreCase("sysmac_policy")
+                    && !tableName.equalsIgnoreCase("sysmac_policy_enforcement")
+                    && !tableName.equalsIgnoreCase("sysmac_user")
+                    && !tableName.equalsIgnoreCase("dual")){
+                TableEntity entity = createTableEntity(conn,rs);
+                if(entity != null){
+                    tableEntities.add(entity);
+                }
+            }else{
+                continue;
+            }
+        }
+        return tableEntities;
+    }
+}

+ 65 - 0
src/main/java/com/goer/common/dialect/impl/DBDialectMySQL.java

@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.dialect.impl;
+
+import com.goer.common.chiner.model.ColumnField;
+import com.goer.common.dialect.DBDialect;
+
+import java.sql.*;
+import java.util.Set;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/14
+ * @desc : MySQL数据库方言
+ */
+public class DBDialectMySQL extends DBDialect {
+
+    @Override
+    public String getSchemaPattern(Connection conn) throws SQLException {
+        //原本应该取dbName,但是目前没有找到好的办法从URL中解析出来
+        //schemaPattern = dbname;
+        return null;
+    }
+
+    @Override
+    public void fillColumnField(ColumnField field, Connection conn, ResultSet rs, Set<String> pkSet) throws SQLException {
+        super.fillColumnField(field, conn, rs, pkSet);
+        int dataType = rs.getInt("DATA_TYPE");
+        if (isInteger(dataType)) {
+            int columnSize = rs.getInt("COLUMN_SIZE")+1;
+            field.setLen(columnSize);
+        }
+        String isAutoincrement = rs.getString("IS_AUTOINCREMENT");
+        field.setAutoIncrement(!"NO".equalsIgnoreCase(isAutoincrement));
+    }
+
+    /**
+     * MySQL的整数长度比实际要少一位
+     * @param dataType
+     * @return
+     */
+    private static boolean isInteger(int dataType) {
+//        int[] array = {Types.NUMERIC, Types.DECIMAL, Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT, Types.REAL, Types.FLOAT, Types.DOUBLE};
+        int[] array = {Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT};
+        for(int item : array){
+            if(item == dataType){
+                return true;
+            }
+        }
+        return false;
+    }
+}

+ 44 - 0
src/main/java/com/goer/common/dialect/impl/DBDialectOracle.java

@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.dialect.impl;
+
+import com.goer.common.dialect.DBDialect;
+import com.goer.common.utils.fisok.raw.kit.StringKit;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Set;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/14
+ * @desc : ORACLE数据库方言
+ */
+public class DBDialectOracle extends DBDialect {
+
+    @Override
+    public String getSchemaPattern(Connection conn) throws SQLException {
+        String schemaPattern = conn.getMetaData().getUserName().toUpperCase();
+        if (StringKit.isNotBlank(schemaPattern)) {
+            schemaPattern = schemaPattern.toUpperCase();
+        }
+        return schemaPattern;
+    }
+
+
+}

+ 29 - 0
src/main/java/com/goer/common/dialect/impl/DBDialectPostgreSQL.java

@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.dialect.impl;
+
+
+import com.goer.common.dialect.DBDialect;
+
+import java.sql.*;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/7/20
+ * @desc : PostgreSQL方言
+ */
+public class DBDialectPostgreSQL extends DBDialect {
+}

+ 191 - 0
src/main/java/com/goer/common/dialect/impl/DBDialectSQLServer.java

@@ -0,0 +1,191 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.dialect.impl;
+
+import com.goer.common.chiner.model.ColumnField;
+import com.goer.common.chiner.model.TableEntity;
+import com.goer.common.command.kit.ConnParseKit;
+import com.goer.common.dialect.DBDialect;
+import com.goer.common.utils.fisok.raw.kit.JdbcKit;
+import com.goer.common.utils.fisok.raw.kit.StringKit;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.sql.*;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/6/14
+ * @desc : SQLServer数据库方言
+ */
+public class DBDialectSQLServer extends DBDialect {
+
+    private String querySQL = "SELECT\n" +
+            "\ttable_code =\n" +
+            "CASE\n" +
+            "\t\tWHEN a.colorder= 1 THEN\n" +
+            "\t\td.name ELSE ''\n" +
+            "\tEND,\n" +
+            "\ttable_comment =\n" +
+            "CASE\n" +
+            "\tWHEN a.colorder= 1 THEN\n" +
+//            "\tISNULL( f.value, '' ) ELSE ''\n" +
+            "\tCONVERT(nvarchar(1000), f.value) ELSE ''\n" +
+            "\tEND,\n" +
+            "\tcolumn_index = a.colorder,\n" +
+            "\tcolumn_name = a.name,\n" +
+            "\tcolumn_is_identity =\n" +
+            "CASE\n" +
+            "\tWHEN COLUMNPROPERTY( a.id, a.name, 'IsIdentity' ) = 1 THEN\n" +
+            "\t'Y' ELSE ''\n" +
+            "\tEND,\n" +
+            "\tcolumn_is_primary_key =\n" +
+            "CASE\n" +
+            "\tWHEN EXISTS (\n" +
+            "\tSELECT\n" +
+            "\t\t1\n" +
+            "\tFROM\n" +
+            "\t\tsysobjects\n" +
+            "\tWHERE\n" +
+            "\t\txtype = 'PK'\n" +
+            "\t\tAND name IN ( SELECT name FROM sysindexes WHERE indid IN ( SELECT indid FROM sysindexkeys WHERE id = a.id AND colid = a.colid ) )\n" +
+            "\t\t) THEN\n" +
+            "\t\t'Y' ELSE ''\n" +
+            "\tEND,\n" +
+            "\tcolumn_data_type = b.name,\n" +
+            "\tcolumn_data_bytes = a.length,\n" +
+            "\tcolumn_data_length = COLUMNPROPERTY( a.id, a.name, 'PRECISION' ),\n" +
+            "\tcolumn_data_scale = ISNULL( COLUMNPROPERTY( a.id, a.name, 'Scale' ), 0 ),\n" +
+            "\tcolumn_data_is_required =\n" +
+            "CASE\n" +
+            "\t\tWHEN a.isnullable= 1 THEN\n" +
+            "\t\t'Y' ELSE ''\n" +
+            "\tEND,\n" +
+            "\tcolumn_default_value = ISNULL( e.text, '' ),\n" +
+//            "\tcolumn_comment = ISNULL( g.[value], '' )\n" +
+            "\tcolumn_comment = CONVERT(nvarchar(1000), ISNULL( g.[value], '' ))\n" +
+            "FROM\n" +
+            "\tsyscolumns a\n" +
+            "\tLEFT JOIN systypes b ON a.xusertype= b.xusertype\n" +
+            "\tINNER JOIN sysobjects d ON a.id= d.id\n" +
+            "\tAND d.xtype= 'U'\n" +
+            "\tAND d.name<> 'dtproperties'\n" +
+            "\tLEFT JOIN syscomments e ON a.cdefault= e.id\n" +
+            "\tLEFT JOIN sys.extended_properties g ON a.id= g.major_id\n" +
+            "\tAND a.colid= g.minor_id\n" +
+            "\tLEFT JOIN sys.extended_properties f ON d.id= f.major_id\n" +
+            "\tAND f.minor_id= 0\n" +
+            "where   d.name=?\n" +
+            "ORDER BY\n" +
+            "\ta.id,\n" +
+            "\ta.colorder;";
+
+    @Override
+    public String getTableNamePattern(Connection conn) throws SQLException {
+        return "%";
+    }
+
+    /**
+     * 将resultset,主键的resultset装到一个二元组中,并返回
+     * @param conn
+     * @param tableName
+     * @return
+     * @throws SQLException
+     */
+    @Override
+    public Pair getColumnAndPrimaryKeyResultSetPair(Connection conn, String tableName) throws SQLException {
+        DatabaseMetaData connMetaData = conn.getMetaData();
+        String schema = getSchemaPattern(conn);
+
+//        ResultSet rs = connMetaData.getColumns(conn.getCatalog(), schema,tableName, "%");
+//        ResultSet pkRs = connMetaData.getPrimaryKeys(conn.getCatalog(),schema,tableName);
+        ResultSet rs = connMetaData.getColumns(null,null,tableName,null);
+        ResultSet pkRs = connMetaData.getPrimaryKeys(null,null,tableName);
+
+        Pair<ResultSet,ResultSet> pair = Pair.of(rs,pkRs);
+
+        return pair;
+    }
+
+
+    @Override
+    public void fillTableEntityNoColumn(TableEntity tableEntity, Connection conn, ResultSet rs) throws SQLException {
+        super.fillTableEntityNoColumn(tableEntity,conn,rs);
+        ResultSet nrs = getResultSet(conn,tableEntity.getDefKey());
+        if(nrs.next()){
+            String remarks = nrs.getString("table_comment");
+            String defName = remarks;
+            String comment = "";
+
+            //如果remark中有分号等分割符,则默认之后的就是注释说明文字
+            if(StringKit.isNotBlank(remarks)){
+                Pair<String, String> pair = ConnParseKit.parseNameAndComment(remarks);
+                defName = pair.getLeft();
+                comment = pair.getRight();
+            }
+            tableEntity.setDefName(defName);
+            tableEntity.setComment(comment);
+        }
+        JdbcKit.close(nrs);
+    }
+
+    @Override
+    public void fillTableEntity(TableEntity tableEntity, Connection conn) throws SQLException {
+        super.fillTableEntity(tableEntity, conn);
+
+        ResultSet nrs = getResultSet(conn,tableEntity.getDefKey());
+        while(nrs.next()){
+            String columnName = nrs.getString("column_name");
+            String columnIsPrimaryKey = nrs.getString("column_is_primary_key");
+            String columnDataType = nrs.getString("column_data_type");
+            String columnDataLength = nrs.getString("column_data_length");
+            String columnDataScale = nrs.getString("column_data_scale");
+            String columnDataIsRequired = nrs.getString("column_data_is_required");
+            String columnDefaultValue = nrs.getString("column_default_value");
+            String columnComment = nrs.getString("column_comment");
+            ColumnField field = tableEntity.lookupField(columnName);
+            if(field != null){
+                String defName = columnComment;
+                String comment = "";
+
+                //如果remark中有分号等分割符,则默认之后的就是注释说明文字
+                if(StringKit.isNotBlank(columnComment)){
+                    Pair<String, String> pair = ConnParseKit.parseNameAndComment(columnComment);
+                    defName = pair.getLeft();
+                    comment = pair.getRight();
+                }
+                field.setDefName(defName);
+                field.setComment(comment);
+                field.setDefaultValue(columnDefaultValue);
+            }
+
+        }
+
+        JdbcKit.close(nrs);
+    }
+
+
+
+
+
+    private ResultSet getResultSet(Connection conn,String tableName) throws SQLException {
+        PreparedStatement pstmt = null;
+        ResultSet rs = null;
+        pstmt = conn.prepareStatement(querySQL);
+        pstmt.setString(1,tableName);
+        rs = pstmt.executeQuery();
+        return rs;
+    }
+}

+ 101 - 0
src/main/java/com/goer/common/dialect/impl/DBDialectSQLite.java

@@ -0,0 +1,101 @@
+/*
+ * Copyright 2019-2029 FISOK(www.fisok.cn).
+ *
+ * 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.goer.common.dialect.impl;
+
+import com.goer.common.chiner.model.ColumnField;
+import com.goer.common.dialect.DBDialect;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author : 杨松<yangsong158@qq.com>
+ * @date : 2021/11/06
+ * @desc : MySQL数据库方言
+ */
+public class DBDialectSQLite extends DBDialect {
+    private static Pattern NUMBER_PATTERN = Pattern.compile("(\\d+)");
+
+    public String getSchemaPattern(Connection conn) throws SQLException {
+        //原本应该取dbName,但是目前没有找到好的办法从URL中解析出来
+        //schemaPattern = dbname;
+        return null;
+    }
+
+    public void fillColumnField(ColumnField field, Connection conn, ResultSet rs, Set<String> pkSet) throws SQLException {
+        super.fillColumnField(field, conn, rs, pkSet);
+        int dataType = rs.getInt("DATA_TYPE");
+        String dataTypeName = rs.getString("TYPE_NAME");
+        String isAutoincrement = rs.getString("IS_AUTOINCREMENT");
+        int columnSize = rs.getInt("COLUMN_SIZE");
+        field.setAutoIncrement(!"NO".equalsIgnoreCase(isAutoincrement));
+
+        if(NUMBER_PATTERN.matcher(dataTypeName).find()){
+            DataType dataTypeX = parseDataType(dataTypeName);
+            field.setType(dataTypeX.type);
+            field.setLen(dataTypeX.length);
+        }
+        //20000的长度,是被多余解析出来的,不使用
+        if(columnSize >= 2000000000){
+            field.setLen(null);
+            field.setScale(null);
+        }
+        //非数字,则不需要scale
+        if(!isNumber(dataType)){
+           field.setScale(null);
+        }
+
+    }
+
+    private DataType parseDataType(String dataTypeName){
+        DataType dataType = new DataType();
+
+        Matcher matcher = NUMBER_PATTERN.matcher(dataTypeName);
+        if(matcher.find()){
+            int idx = dataTypeName.indexOf("(");
+            dataType.type = dataTypeName.substring(0,idx);
+            dataType.length = Integer.parseInt(matcher.group(0));
+        }
+        return dataType;
+    }
+
+    /**
+     * MySQL的整数长度比实际要少一位
+     * @param dataType
+     * @return
+     */
+    private static boolean isNumber(int dataType) {
+        int[] array = {Types.NUMERIC, Types.DECIMAL, Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT, Types.REAL, Types.FLOAT, Types.DOUBLE};
+        for(int item : array){
+            if(item == dataType){
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static class DataType{
+        private String type;
+        private Integer length;
+    }
+
+
+}

+ 68 - 0
src/main/java/com/goer/common/utils/fisok/raw/RawConsts.java

@@ -0,0 +1,68 @@
+package com.goer.common.utils.fisok.raw;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc : RAW模块的常量
+ */
+public class RawConsts {
+    /** 空的<code>byte</code>数组。 */
+    public static final byte[] EMPTY_BYTE_ARRAY        = new byte[0];
+    public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
+
+    /** 空的<code>short</code>数组。 */
+    public static final short[] EMPTY_SHORT_ARRAY        = new short[0];
+    public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];
+
+    /** 空的<code>int</code>数组。 */
+    public static final int[]     EMPTY_INT_ARRAY            = new int[0];
+    public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];
+
+    /** 空的<code>long</code>数组。 */
+    public static final long[] EMPTY_LONG_ARRAY        = new long[0];
+    public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];
+
+    /** 空的<code>float</code>数组。 */
+    public static final float[] EMPTY_FLOAT_ARRAY        = new float[0];
+    public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];
+
+    /** 空的<code>double</code>数组。 */
+    public static final double[] EMPTY_DOUBLE_ARRAY        = new double[0];
+    public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
+
+    /** 空的<code>char</code>数组。 */
+    public static final char[]      EMPTY_CHAR_ARRAY             = new char[0];
+    public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];
+
+    /** 空的<code>boolean</code>数组。 */
+    public static final boolean[] EMPTY_BOOLEAN_ARRAY        = new boolean[0];
+    public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];
+
+    // object arrays
+
+    /** 空的<code>Object</code>数组。 */
+    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+
+    /** 空的<code>Class</code>数组。 */
+    public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0];
+
+    /** 空的<code>String</code>数组。 */
+    public static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+    // =============================================================
+    //  对象常量
+    // =============================================================
+
+    // 0-valued primitive wrappers
+    public static final Byte      BYTE_ZERO   = new Byte((byte) 0);
+    public static final Short     SHORT_ZERO  = new Short((short) 0);
+    public static final Integer   INT_ZERO    = new Integer(0);
+    public static final Long      LONG_ZERO   = new Long(0L);
+    public static final Float     FLOAT_ZERO  = new Float(0);
+    public static final Double    DOUBLE_ZERO = new Double(0);
+    public static final Character CHAR_NULL   = new Character('\0');
+    public static final Boolean   BOOL_FALSE  = Boolean.FALSE;
+
+    /** 空字符串。 */
+    public static final String EMPTY_STRING = "";
+}

+ 26 - 0
src/main/java/com/goer/common/utils/fisok/raw/holder/DateHolder.java

@@ -0,0 +1,26 @@
+package com.goer.common.utils.fisok.raw.holder;
+
+import java.util.Date;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc : 日期保持器,把当前系统时间绑定到线程上
+ */
+public abstract class DateHolder {
+    private static final ThreadLocal<Date> dateHolder = new ThreadLocal<Date>();
+    public static Date getDate(){
+        Date retDate = dateHolder.get();
+        if(retDate == null) {
+            retDate = new Date();
+        }
+        return retDate;
+    }
+    public static void setDate(Date date){
+        dateHolder.set(date);
+    }
+
+    public static void clear() {
+        dateHolder.remove();
+    }
+}

+ 80 - 0
src/main/java/com/goer/common/utils/fisok/raw/io/ByteInputStream.java

@@ -0,0 +1,80 @@
+package com.goer.common.utils.fisok.raw.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc : 二进制输出流
+ */
+public class ByteInputStream extends InputStream {
+    /**
+     * Our byte buffer
+     */
+    protected byte[] buf = null;
+
+    /**
+     * Number of bytes that we can read from the buffer
+     */
+    protected int count = 0;
+
+    /**
+     * Number of bytes that have been read from the buffer
+     */
+    protected int pos = 0;
+
+    public ByteInputStream(byte[] buf, int count) {
+        this.buf = buf;
+        this.count = count;
+    }
+
+    @Override
+    public final int available() {
+        return count - pos;
+    }
+
+    @Override
+    public final int read() {
+        return (pos < count) ? (buf[pos++] & 0xff) : -1;
+    }
+
+    @Override
+    public final int read(byte[] b, int off, int len) {
+        if (pos >= count) {
+            return -1;
+        }
+
+        if ((pos + len) > count) {
+            len = (count - pos);
+        }
+
+        System.arraycopy(buf, pos, b, off, len);
+        pos += len;
+        return len;
+    }
+
+    @Override
+    public final long skip(long n) {
+        if ((pos + n) > count) {
+            n = count - pos;
+        }
+        if (n < 0) {
+            return 0;
+        }
+        pos += n;
+        return n;
+    }
+
+    @Override
+    public void close() throws IOException {
+        super.close();
+        buf = null;
+        count = 0;
+    }
+
+    @Override
+    public synchronized void reset() {
+        pos = 0;
+    }
+}

+ 82 - 0
src/main/java/com/goer/common/utils/fisok/raw/io/ByteOutputStream.java

@@ -0,0 +1,82 @@
+package com.goer.common.utils.fisok.raw.io;
+
+import java.io.OutputStream;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc : 二进制输出流
+ */
+public class ByteOutputStream extends OutputStream {
+    /**
+     * Buffer and size
+     */
+    protected byte[] buf = null;
+    protected int size = 0;
+
+    /**
+     * Constructs a stream with buffer capacity size 5K
+     */
+    public ByteOutputStream() {
+        this(5 * 1024);
+    }
+
+    /**
+     * Constructs a stream with the given initial size
+     */
+    public ByteOutputStream(int initSize) {
+        this.size = 0;
+        this.buf = new byte[initSize];
+    }
+
+    /**
+     * Ensures that we have a large enough buffer for the given size.
+     */
+    private void verifyBufferSize(int sz) {
+        if (sz > buf.length) {
+            byte[] old = buf;
+            buf = new byte[Math.max(sz, 2 * buf.length)];
+            System.arraycopy(old, 0, buf, 0, old.length);
+            old = null;
+        }
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    @Override
+    public final void write(byte b[]) {
+        verifyBufferSize(size + b.length);
+        System.arraycopy(b, 0, buf, size, b.length);
+        size += b.length;
+    }
+
+    @Override
+    public final void write(byte b[], int off, int len) {
+        verifyBufferSize(size + len);
+        System.arraycopy(b, off, buf, size, len);
+        size += len;
+    }
+
+    @Override
+    public final void write(int b) {
+        verifyBufferSize(size + 1);
+        buf[size++] = (byte) b;
+    }
+
+    public void reset() {
+        size = 0;
+    }
+
+    public ByteInputStream createInputStream() {
+        return new ByteInputStream(buf, size);
+    }
+
+
+    public final byte[] toBytes() {
+        byte newbuf[] = new byte[size];
+        System.arraycopy(buf, 0, newbuf, 0, size);
+        return newbuf;
+    }
+}

+ 655 - 0
src/main/java/com/goer/common/utils/fisok/raw/kit/DateKit.java

@@ -0,0 +1,655 @@
+package com.goer.common.utils.fisok.raw.kit;
+
+import com.goer.common.utils.fisok.raw.holder.DateHolder;
+import org.joda.time.DateTime;
+import org.joda.time.Interval;
+import org.joda.time.Period;
+import org.joda.time.PeriodType;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.temporal.TemporalAdjusters;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc : 日期处理
+ */
+public abstract class DateKit {
+    public static final String DATE_TIME_MS_FORMAT="yyyy-MM-dd HH:mm:ss.SSS";
+    public static final String DATE_TIME_FORMAT="yyyy-MM-dd HH:mm:ss";
+    public static final String DATE_FORMAT="yyyy-MM-dd";
+    public static final String TIME_FORMAT="HH:mm:ss";
+
+    public static final String X_DATE_TIME_MS_FORMAT="yyyyMMdd HH:mm:ss.SSS";
+    public static final String X_DATE_TIME_FORMAT="yyyyMMdd HH:mm:ss";
+    public static final String X_DATE_FORMAT="yyyyMMdd";
+
+
+    public static Date now(){
+        Date now = DateHolder.getDate();
+        if(now == null){
+            now = new Date();
+        }
+        return now;
+    }
+
+    /**
+     * 当前日期的字串值
+     * @return  如: 2020-08-01
+     */
+    public static String strNowDate(){
+        return format(now(),DATE_FORMAT);
+    }
+
+    /**
+     * 当前日期的日期+时间值
+     * @return 如  2020-08-01 08:34:16
+     */
+    public static String strNowDateTime(){
+        return format(now(),DATE_TIME_FORMAT);
+    }
+
+    /**
+     * 当前时间值
+     * @return 如 08:34:16
+     */
+    public static String strNowTime(){
+        return format(now(),TIME_FORMAT);
+    }
+
+    /**
+     * @deprecated 使用xparse
+     * @param str
+     * @return
+     */
+    public static Date parse(String str){
+        String fixedStr = StringKit.nvl(str,"");
+        //如果是数字字串,则直接转下
+        if(fixedStr.matches("\\d+")){
+            return parse(Long.parseLong(str));
+        }
+        if(fixedStr.indexOf("/")>0){
+            fixedStr = fixedStr.replaceAll("/+","-");
+        }
+        fixedStr = fixedStr.replaceAll("-+","-");
+
+        return parseDate(fixedStr, DATE_TIME_MS_FORMAT, DATE_TIME_FORMAT, DATE_FORMAT);
+    }
+
+    public static Date xparse(String str){
+        String fixedStr = StringKit.nvl(str,"");
+        //如果是数字字串,则直接转下
+        if(fixedStr.matches("\\d+")){
+            return parse(Long.parseLong(str));
+        }
+        fixedStr = fixedStr.replaceAll("/+","");
+        fixedStr = fixedStr.replaceAll("-+","");
+
+        return parseDate(fixedStr, X_DATE_TIME_MS_FORMAT, X_DATE_TIME_FORMAT, X_DATE_FORMAT);
+    }
+
+    private static Date parseDate(String fixedStr, String dateTimeMsFormat, String dateTimeFormat, String dateFormat) {
+        try{
+            DateTimeFormatter format = DateTimeFormat.forPattern(dateTimeMsFormat);
+            return DateTime.parse(fixedStr,format).toDate();
+        }catch(IllegalArgumentException e){
+            try{
+                DateTimeFormatter format = DateTimeFormat.forPattern(dateTimeFormat);
+                return DateTime.parse(fixedStr,format).toDate();
+            }catch(IllegalArgumentException e1){
+                DateTimeFormatter format = DateTimeFormat.forPattern(dateFormat);
+                return DateTime.parse(fixedStr,format).toDate();
+            }
+        }
+    }
+
+    public static Date parse(Long value){
+        return new Date(value);
+    }
+
+    public static int getYear(Date date){
+        DateTime dateTime = new DateTime(date);
+        return dateTime.getYear();
+    }
+
+    public static int getMonth(Date date){
+        DateTime dateTime = new DateTime(date);
+        return dateTime.getMonthOfYear();
+    }
+
+    public static int getDay(Date date){
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        return cal.get(Calendar.DATE);
+    }
+
+    public static int getHour(Date date){
+        DateTime dateTime = new DateTime(date);
+        return dateTime.getHourOfDay();
+    }
+
+    public static int getMinute(Date date){
+        DateTime dateTime = new DateTime(date);
+        return dateTime.getMinuteOfHour();
+    }
+
+    public static int getDayOfMonth(Date date){
+        DateTime dateTime = new DateTime(date);
+        return dateTime.getDayOfMonth();
+    }
+
+    public static int getDayOfWeek(Date date){
+        DateTime dateTime = new DateTime(date);
+        return dateTime.getDayOfWeek();
+    }
+
+    public static int getYearOfCentury(Date date){
+        DateTime dateTime = new DateTime(date);
+        return dateTime.getYearOfCentury();
+    }
+
+    public static String format(Date date){
+//        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_TIME_MS_FORMAT);
+        return format(date,DATE_TIME_FORMAT);
+    }
+
+    public static String format(Date date, String format) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
+        return dateFormat.format(date);
+    }
+
+    /**
+     * 取两个日期间隔的天数
+     *
+     * @param date1 date1
+     * @param date2 date2
+     * @return int
+     */
+    public static int getRangeDays(Date date1, Date date2){
+        DateTime begin = new DateTime(date1);
+        DateTime end = new DateTime(date2);
+        Period period = new Period(begin,end, PeriodType.days());
+        return period.getDays();
+    }
+    /**
+     * 取两个日期间隔的月数
+     *
+     * @param date1 date11
+     * @param date2 date2
+     * @return int
+     */
+    public static int getRangeMonths(Date date1, Date date2){
+        DateTime begin = new DateTime(date1);
+        DateTime end = new DateTime(date2);
+        Period period = new Period(begin,end, PeriodType.months());
+        return period.getMonths();
+    }
+
+    /**
+     * 取两个日期间隔的年数
+     *
+     * @param date1 date1
+     * @param date2 date2
+     * @return int
+     */
+    public static int getRangeYears(Date date1, Date date2){
+        DateTime begin = new DateTime(date1);
+        DateTime end = new DateTime(date2);
+        Period period = new Period(begin,end, PeriodType.years());
+        return period.getYears();
+    }
+
+    /**
+     * 取两个日期间隔的秒数
+     * @param date1
+     * @param date2
+     * @return
+     */
+    public static int getRangeSeconds(Date date1, Date date2){
+        DateTime begin = new DateTime(date1);
+        DateTime end = new DateTime(date2);
+        Period period = new Period(begin,end, PeriodType.seconds());
+        return period.getSeconds();
+    }
+
+    /**
+     * 取两个日期间隔的毫秒数
+     * @param date1
+     * @param date2
+     * @return
+     */
+    public static int getRangeMillis(Date date1, Date date2){
+        DateTime begin = new DateTime(date1);
+        DateTime end = new DateTime(date2);
+        Period period = new Period(begin,end, PeriodType.millis());
+        return period.getMillis();
+    }
+
+    /**
+     * 判断两个日期是否是同一天
+     *
+     * @param startDate startDate
+     * @param endDate endDate
+     * @return boolean
+     */
+    public static boolean isSameDay(Date startDate, Date endDate) {
+        if (getRangeDays(startDate, endDate) == 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static Date plusYears(Date startDate, int plusValue) {
+        DateTime oStartDate = new DateTime(startDate);
+        DateTime oEndDate = oStartDate.plusMonths(plusValue*12);
+        return oEndDate.toDate();
+    }
+    public static Date plusMonths(Date startDate, int plusValue) {
+        DateTime oStartDate = new DateTime(startDate);
+        DateTime oEndDate = oStartDate.plusMonths(plusValue);
+        return oEndDate.toDate();
+    }
+    public static Date plusDays(Date startDate, int plusValue) {
+        DateTime oStartDate = new DateTime(startDate);
+        DateTime oEndDate = oStartDate.plusDays(plusValue);
+        return oEndDate.toDate();
+    }
+    public static Date minusDays(Date startDate, int plusValue) {
+        DateTime oStartDate = new DateTime(startDate);
+        DateTime oEndDate = oStartDate.minusDays(plusValue);
+        return oEndDate.toDate();
+    }
+    public static Date minusYears(Date startDate, int plusValue) {
+        DateTime oStartDate = new DateTime(startDate);
+        DateTime oEndDate = oStartDate.minusYears(plusValue);
+        return oEndDate.toDate();
+    }
+
+    /**
+     * 只保留日期的年月日
+     * @param date
+     * @return
+     */
+    public static Date getOnlyYMD(Date date){
+        String strDate = DateKit.format(date,DATE_FORMAT);
+        return DateKit.parse(strDate);
+    }
+
+    /**
+     * 指定时间是否在指定区间内
+     *
+     * @param date date
+     * @param startDate startDate
+     * @param endDate endDate
+     * @return boolean
+     */
+    public static boolean inRange(Date date,Date startDate,Date endDate){
+        DateTime oDate = new DateTime(date);
+        DateTime oStartDate = new DateTime(startDate);
+        DateTime oEndDate = new DateTime(endDate);
+        Interval interval = new Interval(oStartDate,oEndDate);
+        return interval.contains(oDate);
+    }
+
+    /**
+     * 两个日期之间是否相关整月,如1月1号 至 3月1号为true,
+     *
+     * @param startDate startDate
+     * @param endDate endDate
+     * @return boolean
+     */
+    public static boolean rangIsFullMonth(Date startDate, Date endDate){
+        int rangMonths = getRangeMonths(startDate,endDate);
+        Date oEndDate = plusMonths(startDate, rangMonths);
+        return isSameDay(endDate, oEndDate);
+    }
+
+    /**
+     * 指定日期区间是否在另一个日期区间内
+     *
+     * @param innerStartDate 内层日期区间开始日期
+     * @param innerEndDate 内层日期区间结束日期
+     * @param outerStartDate 外层日期区间开始日期
+     * @param outerEndDate 外层日期区间结束日期
+     * @param containsEnd 是否算尾期
+     * @return boolean
+     */
+    public static boolean inRange(Date innerStartDate,Date innerEndDate,Date outerStartDate,Date outerEndDate,boolean containsEnd){
+        if(containsEnd){
+            return inRange(innerStartDate,outerStartDate,outerEndDate) && (inRange(innerEndDate,outerStartDate,outerEndDate)|| compareLimitToDay(innerEndDate,outerEndDate) == 0);
+        }else{
+            return inRange(innerStartDate,outerStartDate,outerEndDate) && (inRange(innerEndDate,outerStartDate,outerEndDate));
+        }
+    }
+
+    /**
+     * 指定日期区间是否在另一个日期区间内
+     *
+     * @param innerStartDate 内层日期区间开始日期
+     * @param innerEndDate 内层日期区间结束日期
+     * @param outerStartDate 外层日期区间开始日期
+     * @param outerEndDate 外层日期区间结束日期
+     * @return boolean
+     */
+    public static boolean inRange(Date innerStartDate,Date innerEndDate,Date outerStartDate,Date outerEndDate){
+        return inRange(innerStartDate, innerEndDate,outerStartDate, outerEndDate,true);
+    }
+
+    /**
+     * 两个日期比较(到天)如果date1>date2返回1,date1=date2返回0,date1<date2返回-1
+     *
+     * @param date1 date1
+     * @param date2 date2
+     * @return int
+     */
+    public static int compareLimitToDay(Date date1,Date date2){
+        DateTime startDate = new DateTime(date1);
+        DateTime endDate = new DateTime(date2);
+        int year1 = startDate.getYear();
+        int year2 = endDate.getYear();
+        if(year1>year2){
+            return 1;
+        }else if(year1<year2){
+            return -1;
+        }else {
+            int days1 = startDate.getDayOfYear();
+            int days2 = endDate.getDayOfYear();
+            if(days1 > days2){
+                return 1;
+            }else if(days1 < days2){
+                return -1;
+            }else{
+                return 0;
+            }
+        }
+    }
+
+    /**
+     * 获取指定日期当月的天数
+     *
+     * @param date date
+     * @return int
+     */
+    public static int getMonthDays(Date date){
+        DateTime oDate = new DateTime(date);
+        Integer days = oDate.dayOfMonth().getMaximumValue();
+        return days;
+    }
+
+    /**
+     * 判断日期date是否在referDate之后
+     *
+     * @param referDate 前一个日期
+     * @param date 比较的后一个日期
+     * @param containEquals 如果是同一天,是否包含
+     * @return boolean
+     */
+    public static boolean isAfter(Date referDate,Date date,boolean containEquals){
+        int r = compareLimitToDay(date,referDate);
+        if(r == 1){
+            return true;
+        }else if(r == 0){
+            if(containEquals) {
+                return true;
+            } else {
+                return false;
+            }
+        }else{
+            return false;
+        }
+    }
+
+    /**
+     * 判断日期date是否在referDate之后,相等返会false
+     *
+     * @param referDate referDate
+     * @param date date
+     * @return boolean
+     */
+    public static boolean isAfter(Date referDate,Date date){
+        return isAfter(referDate,date,false);
+    }
+
+    /**
+     * 获取指定年的天数
+     *
+     * @param date date
+     * @return int
+     */
+    public static int getYearDays(Date date){
+        DateTime oDate = new DateTime(date);
+        Integer days = oDate.dayOfYear().getMaximumValue();
+        return days;
+    }
+
+    /**
+     * 获取指定月份的最后一天
+     *
+     * @param year  year
+     * @param month month
+     * @return date
+     */
+    public static Date getLastDayOfMonth(int year,int month){
+        LocalDate localDate = LocalDate.of(year, month,1);
+        LocalDate now = localDate.with(TemporalAdjusters.lastDayOfMonth());
+        Date.from(now.atStartOfDay(ZoneId.systemDefault()).plusDays(1L).minusNanos(1L).toInstant());
+        return localDate2Date(now);
+    }
+
+    public static LocalDate date2LocalDate(Date date){
+        Instant instant = date.toInstant();
+        ZoneId zone = ZoneId.systemDefault();
+        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
+        LocalDate localDate = localDateTime.toLocalDate();
+        return localDate;
+    }
+
+    public static LocalDateTime date2LocalDateTime(Date date){
+        Instant instant = date.toInstant();
+        ZoneId zone = ZoneId.systemDefault();
+        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
+        return localDateTime;
+    }
+
+    public static Date localDate2Date(LocalDate localDate){
+        ZoneId zone = ZoneId.systemDefault();
+        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
+        Date date = Date.from(instant);
+        return date;
+    }
+
+    public static Date localDateTime2Date(LocalDateTime localDateTime){
+        ZoneId zone = ZoneId.systemDefault();
+        Instant instant = localDateTime.atZone(zone).toInstant();
+        Date date = Date.from(instant);
+        return date;
+    }
+
+    public java.time.Period between(Date beginDate,Date endDate){
+        LocalDate begin = date2LocalDate(beginDate);
+        LocalDate end = date2LocalDate(endDate);
+        java.time.Period period = java.time.Period.between(begin,end);
+        return period;
+    }
+
+
+
+    /**
+     * 获取本周的开始时间
+     *
+     * @param curDate curDate
+     * @return date
+     */
+    public static Date getMondayOfWeek(Date curDate) {
+        Calendar cal = Calendar.getInstance();
+        if (null != curDate) {
+            cal.setTime(curDate);
+        }
+        cal.setTime(curDate);
+        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
+        if (dayOfWeek == 1) {
+            dayOfWeek += 7;
+        }
+        cal.add(Calendar.DATE, 2 - dayOfWeek);
+        return getDayStartTime(cal.getTime());
+    }
+
+    /**
+     * 获取本周的结束时间
+     *
+     * @param curDate curDate
+     * @return date
+     */
+    public static Date getSundayOfWeek(Date curDate) {
+        Calendar cal = Calendar.getInstance();
+        if (null != curDate) {
+            cal.setTime(curDate);
+        }
+        cal.setTime(getMondayOfWeek(curDate));
+        cal.add(Calendar.DAY_OF_WEEK, 6);
+        Date weekEndSta = cal.getTime();
+        return getDayEndTime(weekEndSta);
+    }
+
+    /**
+     * 获取本月的开始时间
+     *
+     * @param date date
+     * @return date
+     */
+    public static Date getFirstDayOfMonth(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        if (null != date) {
+            calendar.setTime(date);
+        }
+        calendar.set(DateKit.getYear(date), DateKit.getMonth(date) - 1, 1);
+        return getDayStartTime(calendar.getTime());
+    }
+
+    /**
+     * 获取本月的结束时间
+     *
+     * @param date date
+     * @return date
+     */
+    public static Date getLastDayOfMonth(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        if (null != date) {
+            calendar.setTime(date);
+        }
+        calendar.set(DateKit.getYear(date), DateKit.getMonth(date) - 1, 1);
+        int day = calendar.getActualMaximum(5);
+        calendar.set(DateKit.getYear(date), DateKit.getMonth(date) - 1, day);
+        return getDayEndTime(calendar.getTime());
+    }
+
+    /**
+     * 获取某个日期的开始时间
+     *
+     * @param date date
+     * @return date
+     */
+    private static Date getDayStartTime(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        if (null != date) {
+            calendar.setTime(date);
+        }
+        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
+                calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return new Timestamp(calendar.getTimeInMillis());
+    }
+
+
+    /**
+     * 获取某个日期的结束时间
+     *
+     * @param date date
+     * @return date
+     */
+    private static Date getDayEndTime(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        if (null != date) {
+            calendar.setTime(date);
+        }
+        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
+                calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
+        calendar.set(Calendar.MILLISECOND, 999);
+        return new Timestamp(calendar.getTimeInMillis());
+    }
+
+
+
+    /**
+     * 获取某年某月的第一天日期
+     *
+     * @param year  year
+     * @param month month
+     * @return date
+     */
+    public static Date getStartMonthDate(int year, int month) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(year, month - 1, 1);
+        return getDayStartTime(calendar.getTime());
+    }
+
+    /**
+     * 获取某年某月的最后一天日期
+     *
+     * @param year  year
+     * @param month month
+     * @return date
+     */
+    public static Date getEndMonthDate(int year, int month) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(year, month - 1, 1);
+        int day = calendar.getActualMaximum(5);
+        calendar.set(year, month - 1, day);
+        return getDayEndTime(calendar.getTime());
+    }
+
+    /**
+     * 获取本年的开始时间
+     *
+     * @param date date
+     * @return date
+     */
+    public static Date getBeginDayOfYear(Date date) {
+        Calendar cal = Calendar.getInstance();
+        if (null != date) {
+            cal.setTime(date);
+        }
+        cal.set(Calendar.YEAR, DateKit.getYear(date));
+        cal.set(Calendar.MONTH, Calendar.JANUARY);
+        cal.set(Calendar.DATE, 1);
+        return getDayStartTime(cal.getTime());
+    }
+
+    /**
+     * 获取本年的结束时间
+     *
+     * @param date date
+     * @return date
+     */
+    public static Date getEndDayOfYear(Date date) {
+        Calendar cal = Calendar.getInstance();
+        if (null != date) {
+            cal.setTime(date);
+        }
+        cal.set(Calendar.YEAR, DateKit.getYear(date));
+        cal.set(Calendar.MONTH, Calendar.DECEMBER);
+        cal.set(Calendar.DATE, 31);
+        return getDayEndTime(cal.getTime());
+    }
+
+}

+ 657 - 0
src/main/java/com/goer/common/utils/fisok/raw/kit/FileKit.java

@@ -0,0 +1,657 @@
+package com.goer.common.utils.fisok.raw.kit;
+
+import com.goer.common.utils.fisok.raw.lang.RawException;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.LineIterator;
+import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.math.BigInteger;
+import java.net.URL;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.text.DecimalFormat;
+import java.text.MessageFormat;
+import java.text.NumberFormat;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.Checksum;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc :
+ */
+public abstract class FileKit {
+    private FileUtils fileUtils = new FileUtils();
+
+    private static DecimalFormat decimalFormat=(DecimalFormat) NumberFormat.getInstance();
+    static{
+        decimalFormat.setMaximumFractionDigits(2);
+    }
+
+    private static Logger logger = LoggerFactory.getLogger(FileKit.class);
+
+    /**
+     * 把文件路径处理成为标准文件路径,都用"/"作为路径分割符
+     *
+     * @param path path
+     * @return string
+     */
+    public static String standardFilePath(String path){
+        if(path!=null){
+            return path.replaceAll("\\\\", "/");
+        }else{
+            return path;
+        }
+    }
+
+    /**
+     * 如果文件不存在,则创建新文件
+     *
+     * @param file file
+     * @throws IOException IOException
+     * @return File
+     */
+    public static File touchFile(String file) throws IOException {
+        return touchFile(new File(file));
+    }
+    /**
+     * 如果文件不存在,则创建新文件
+     *
+     * @param file file
+     * @throws IOException IOException
+     * @return File
+     */
+    public static File touchFile(File file) throws IOException {
+        return touchFile(file,false);
+    }
+
+    /**
+     * 如果文件不存在,则创建新文件
+     *
+     * @param file file
+     * @param cleanFile cleanFile
+     * @throws IOException IOException
+     * @return File
+     */
+    public static File touchFile(File file,boolean cleanFile) throws IOException {
+        if(cleanFile&&file.exists()) {
+            FileKit.deleteFile(file);
+        }
+        if(!file.exists()){
+            File parentFile = file.getParentFile();
+            if(!parentFile.exists()){
+                parentFile.mkdirs();
+            }
+            file.createNewFile();
+        }
+        return file;
+    }
+
+    public static long getFileSize(File file){
+        FileChannel channel = null;
+        if(file.exists() && file.isFile()){
+            FileInputStream inputStream = null;
+            try {
+                inputStream = new FileInputStream(file);
+                channel = inputStream.getChannel();
+                return channel.size();
+            } catch (FileNotFoundException e) {
+                throw new RawException("读取文件大小出错,文件:[{0}]不存在",file.getAbsolutePath());
+            } catch (IOException e) {
+                throw new RuntimeException("读取文件出错");
+            }finally{
+                IOKit.close(inputStream);
+                IOKit.close(channel);
+            }
+        }
+        return 0L;
+    }
+
+    public static boolean deleteFile(File file){
+        String fileFullPath;
+        try {
+            fileFullPath = file.getCanonicalPath();
+        } catch (IOException e) {
+            fileFullPath = e.getMessage();
+        }
+
+        boolean r = file.delete();
+        logger.trace(MessageFormat.format("文件删除,【{0}】,删除结果【{1}】",fileFullPath,r));
+        return r;
+    }
+
+    public static InputStream openInputStream(File file) throws IOException{
+        InputStream inputStream = null;
+
+        try {
+            inputStream = new FileInputStream(file);
+        } catch (FileNotFoundException e) {
+            throw e;
+        }
+
+        return inputStream;
+    }
+
+    public static OutputStream openOutputStream(File file,boolean autoCreate) throws IOException{
+        OutputStream outputStream = null;
+
+        if(autoCreate&&!file.exists()){
+            File parent = file.getParentFile();
+            if(!parent.exists()) {
+                parent.mkdirs();
+            }
+            file.createNewFile();
+        }
+        try {
+            outputStream = new FileOutputStream(file);
+        } catch (FileNotFoundException e) {
+            throw e;
+        }
+
+        return outputStream;
+    }
+
+    public static OutputStream openOutputStream(File file) throws IOException{
+        return openOutputStream(file,true);
+    }
+
+    /**
+     * 文件复制
+     *
+     * @param src src
+     * @param dsc dsc
+     * @param autoCreateDscDir autoCreateDscDir
+     * @throws IOException IOException
+     */
+    public static void copy(File src,File dsc,boolean autoCreateDscDir) throws IOException{
+        FileInputStream fis = null;
+        FileOutputStream fos = null;
+        FileChannel fcIn = null;
+        FileChannel fcOut = null;
+
+        try {
+            logger.trace(MessageFormat.format("文件复制,【{0}】-->【{1}】", src.getCanonicalPath(),dsc.getCanonicalPath()));
+            if(autoCreateDscDir){
+                File parentFile = dsc.getParentFile();
+                if(!parentFile.exists()){
+                    parentFile.mkdirs();
+                }
+            }
+            fis = new FileInputStream(src);
+            fos = new FileOutputStream(dsc);
+            fcIn = fis.getChannel();
+            fcOut = fos.getChannel();
+
+            fcIn.transferTo(0, fcIn.size(), fcOut);
+        } catch (FileNotFoundException e) {
+            throw e;
+        } catch (IOException e) {
+            throw e;
+        }finally{
+            IOKit.close(fis);
+            IOKit.close(fcIn);
+            IOKit.close(fos);
+            IOKit.close(fcOut);
+        }
+    }
+
+    public  static String convertSizeText(Long size) {
+        if (size == null || size == 0) {
+            return "0K";
+        }
+        String text = "";
+        Double size1 = size.doubleValue();
+        text = decimalFormat.format(size1) + "B";
+        int mulNumber = 1024;
+        if (size1 > mulNumber) {
+            size1 = size1 / mulNumber;
+            text = decimalFormat.format(size1) + "K";
+        }
+        if (size1 > mulNumber) {
+            size1 = size1 / mulNumber;
+            text = decimalFormat.format(size1) + "M";
+        }
+        if (size1 > mulNumber) {
+            size1 = size1 / mulNumber;
+            text = decimalFormat.format(size1) + "G";
+        }
+        return text;
+    }
+
+    /**
+     * 获取文件的扩展名
+     *
+     * @param file file
+     * @return String
+     */
+    public static String getSuffix(String file){
+        String suffix = "";
+        if(StringUtils.isBlank(file)) {
+            return suffix;
+        }
+        String[] ss = file.split("\\.");
+        if(ss.length>1){
+            suffix = ss[ss.length-1];
+        }
+        return suffix;
+    }
+
+    public static String getFileName(String file,boolean includeExtension){
+        return getFileName(new File(file),includeExtension);
+    }
+    public static String getFileName(File file,boolean includeExtension){
+        String fileName = file.getName();
+        if(!includeExtension&&fileName.lastIndexOf(".")>=0){
+            return fileName.substring(0,fileName.lastIndexOf("."));
+        }else{
+            return fileName;
+        }
+    }
+
+    public static File getFile(File directory, String... names) {
+        return FileUtils.getFile(directory, names);
+    }
+
+    public static File getFile(String... names) {
+        return FileUtils.getFile(names);
+    }
+
+    public static String getTempDirectoryPath() {
+        return FileUtils.getTempDirectoryPath();
+    }
+
+    public static File getTempDirectory() {
+        return FileUtils.getTempDirectory();
+    }
+
+    public static String getUserDirectoryPath() {
+        return FileUtils.getUserDirectoryPath();
+    }
+
+    public static File getUserDirectory() {
+        return FileUtils.getUserDirectory();
+    }
+
+    public static String byteCountToDisplaySize(BigInteger size) {
+        return FileUtils.byteCountToDisplaySize(size);
+    }
+
+    public static String byteCountToDisplaySize(long size) {
+        return FileUtils.byteCountToDisplaySize(size);
+    }
+
+    public static void touch(File file) throws IOException {
+        FileUtils.touch(file);
+    }
+
+    public static File[] convertFileCollectionToFileArray(Collection<File> files) {
+        return FileUtils.convertFileCollectionToFileArray(files);
+    }
+
+    public static Collection<File> listFiles(File directory, IOFileFilter fileFilter, IOFileFilter dirFilter) {
+        return FileUtils.listFiles(directory, fileFilter, dirFilter);
+    }
+
+    public static Collection<File> listFilesAndDirs(File directory, IOFileFilter fileFilter, IOFileFilter dirFilter) {
+        return FileUtils.listFilesAndDirs(directory, fileFilter, dirFilter);
+    }
+
+    public static Iterator<File> iterateFiles(File directory, IOFileFilter fileFilter, IOFileFilter dirFilter) {
+        return FileUtils.iterateFiles(directory, fileFilter, dirFilter);
+    }
+
+    public static Iterator<File> iterateFilesAndDirs(File directory, IOFileFilter fileFilter, IOFileFilter dirFilter) {
+        return FileUtils.iterateFilesAndDirs(directory, fileFilter, dirFilter);
+    }
+
+    public static Collection<File> listFiles(File directory, String[] extensions, boolean recursive) {
+        return FileUtils.listFiles(directory, extensions, recursive);
+    }
+
+    public static Iterator<File> iterateFiles(File directory, String[] extensions, boolean recursive) {
+        return FileUtils.iterateFiles(directory, extensions, recursive);
+    }
+
+    public static boolean contentEquals(File file1, File file2) throws IOException {
+        return FileUtils.contentEquals(file1, file2);
+    }
+
+    public static boolean contentEqualsIgnoreEOL(File file1, File file2, String charsetName) throws IOException {
+        return FileUtils.contentEqualsIgnoreEOL(file1, file2, charsetName);
+    }
+
+    public static File toFile(URL url) {
+        return FileUtils.toFile(url);
+    }
+
+    public static File[] toFiles(URL[] urls) {
+        return FileUtils.toFiles(urls);
+    }
+
+    public static URL[] toURLs(File[] files) throws IOException {
+        return FileUtils.toURLs(files);
+    }
+
+    public static void copyFileToDirectory(File srcFile, File destDir) throws IOException {
+        FileUtils.copyFileToDirectory(srcFile, destDir);
+    }
+
+    public static void copyFileToDirectory(File srcFile, File destDir, boolean preserveFileDate) throws IOException {
+        FileUtils.copyFileToDirectory(srcFile, destDir, preserveFileDate);
+    }
+
+    public static void copyFile(File srcFile, File destFile) throws IOException {
+        FileUtils.copyFile(srcFile, destFile);
+    }
+
+    public static void copyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException {
+        FileUtils.copyFile(srcFile, destFile, preserveFileDate);
+    }
+
+    public static long copyFile(File input, OutputStream output) throws IOException {
+        return FileUtils.copyFile(input, output);
+    }
+
+    public static void copyDirectoryToDirectory(File srcDir, File destDir) throws IOException {
+        FileUtils.copyDirectoryToDirectory(srcDir, destDir);
+    }
+
+    public static void copyDirectory(File srcDir, File destDir) throws IOException {
+        FileUtils.copyDirectory(srcDir, destDir);
+    }
+
+    public static void copyDirectory(File srcDir, File destDir, boolean preserveFileDate) throws IOException {
+        FileUtils.copyDirectory(srcDir, destDir, preserveFileDate);
+    }
+
+    public static void copyDirectory(File srcDir, File destDir, FileFilter filter) throws IOException {
+        FileUtils.copyDirectory(srcDir, destDir, filter);
+    }
+
+    public static void copyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate) throws IOException {
+        FileUtils.copyDirectory(srcDir, destDir, filter, preserveFileDate);
+    }
+
+    public static void copyURLToFile(URL source, File destination) throws IOException {
+        FileUtils.copyURLToFile(source, destination);
+    }
+
+    public static void copyURLToFile(URL source, File destination, int connectionTimeout, int readTimeout) throws IOException {
+        FileUtils.copyURLToFile(source, destination, connectionTimeout, readTimeout);
+    }
+
+    public static void copyInputStreamToFile(InputStream source, File destination) throws IOException {
+        FileUtils.copyInputStreamToFile(source, destination);
+    }
+
+    public static void copyToFile(InputStream source, File destination) throws IOException {
+        FileUtils.copyToFile(source, destination);
+    }
+
+    public static void deleteDirectory(File directory) throws IOException {
+        FileUtils.deleteDirectory(directory);
+    }
+
+    public static boolean deleteQuietly(File file) {
+        return FileUtils.deleteQuietly(file);
+    }
+
+    public static boolean directoryContains(File directory, File child) throws IOException {
+        return FileUtils.directoryContains(directory, child);
+    }
+
+    public static void cleanDirectory(File directory) throws IOException {
+        FileUtils.cleanDirectory(directory);
+    }
+
+    public static boolean waitFor(File file, int seconds) {
+        return FileUtils.waitFor(file, seconds);
+    }
+
+    public static String readFileToString(File file, Charset encoding) throws IOException {
+        return FileUtils.readFileToString(file, encoding);
+    }
+
+    public static String readFileToString(File file, String encoding) throws IOException {
+        return FileUtils.readFileToString(file, encoding);
+    }
+
+    @Deprecated
+    public static String readFileToString(File file) throws IOException {
+        return FileUtils.readFileToString(file);
+    }
+
+    public static byte[] readFileToByteArray(File file) throws IOException {
+        return FileUtils.readFileToByteArray(file);
+    }
+
+    public static List<String> readLines(File file, Charset encoding) throws IOException {
+        return FileUtils.readLines(file, encoding);
+    }
+
+    public static List<String> readLines(File file, String encoding) throws IOException {
+        return FileUtils.readLines(file, encoding);
+    }
+
+    @Deprecated
+    public static List<String> readLines(File file) throws IOException {
+        return FileUtils.readLines(file);
+    }
+
+    public static LineIterator lineIterator(File file, String encoding) throws IOException {
+        return FileUtils.lineIterator(file, encoding);
+    }
+
+    public static LineIterator lineIterator(File file) throws IOException {
+        return FileUtils.lineIterator(file);
+    }
+
+    public static void writeStringToFile(File file, String data, Charset encoding) throws IOException {
+        FileUtils.writeStringToFile(file, data, encoding);
+    }
+
+    public static void writeStringToFile(File file, String data, String encoding) throws IOException {
+        FileUtils.writeStringToFile(file, data, encoding);
+    }
+
+    public static void writeStringToFile(File file, String data, Charset encoding, boolean append) throws IOException {
+        FileUtils.writeStringToFile(file, data, encoding, append);
+    }
+
+    public static void writeStringToFile(File file, String data, String encoding, boolean append) throws IOException {
+        FileUtils.writeStringToFile(file, data, encoding, append);
+    }
+
+    @Deprecated
+    public static void writeStringToFile(File file, String data) throws IOException {
+        FileUtils.writeStringToFile(file, data);
+    }
+
+    @Deprecated
+    public static void writeStringToFile(File file, String data, boolean append) throws IOException {
+        FileUtils.writeStringToFile(file, data, append);
+    }
+
+    @Deprecated
+    public static void write(File file, CharSequence data) throws IOException {
+        FileUtils.write(file, data);
+    }
+
+    @Deprecated
+    public static void write(File file, CharSequence data, boolean append) throws IOException {
+        FileUtils.write(file, data, append);
+    }
+
+    public static void write(File file, CharSequence data, Charset encoding) throws IOException {
+        FileUtils.write(file, data, encoding);
+    }
+
+    public static void write(File file, CharSequence data, String encoding) throws IOException {
+        FileUtils.write(file, data, encoding);
+    }
+
+    public static void write(File file, CharSequence data, Charset encoding, boolean append) throws IOException {
+        FileUtils.write(file, data, encoding, append);
+    }
+
+    public static void write(File file, CharSequence data, String encoding, boolean append) throws IOException {
+        FileUtils.write(file, data, encoding, append);
+    }
+
+    public static void writeByteArrayToFile(File file, byte[] data) throws IOException {
+        FileUtils.writeByteArrayToFile(file, data);
+    }
+
+    public static void writeByteArrayToFile(File file, byte[] data, boolean append) throws IOException {
+        FileUtils.writeByteArrayToFile(file, data, append);
+    }
+
+    public static void writeByteArrayToFile(File file, byte[] data, int off, int len) throws IOException {
+        FileUtils.writeByteArrayToFile(file, data, off, len);
+    }
+
+    public static void writeByteArrayToFile(File file, byte[] data, int off, int len, boolean append) throws IOException {
+        FileUtils.writeByteArrayToFile(file, data, off, len, append);
+    }
+
+    public static void writeLines(File file, String encoding, Collection<?> lines) throws IOException {
+        FileUtils.writeLines(file, encoding, lines);
+    }
+
+    public static void writeLines(File file, String encoding, Collection<?> lines, boolean append) throws IOException {
+        FileUtils.writeLines(file, encoding, lines, append);
+    }
+
+    public static void writeLines(File file, Collection<?> lines) throws IOException {
+        FileUtils.writeLines(file, lines);
+    }
+
+    public static void writeLines(File file, Collection<?> lines, boolean append) throws IOException {
+        FileUtils.writeLines(file, lines, append);
+    }
+
+    public static void writeLines(File file, String encoding, Collection<?> lines, String lineEnding) throws IOException {
+        FileUtils.writeLines(file, encoding, lines, lineEnding);
+    }
+
+    public static void writeLines(File file, String encoding, Collection<?> lines, String lineEnding, boolean append) throws IOException {
+        FileUtils.writeLines(file, encoding, lines, lineEnding, append);
+    }
+
+    public static void writeLines(File file, Collection<?> lines, String lineEnding) throws IOException {
+        FileUtils.writeLines(file, lines, lineEnding);
+    }
+
+    public static void writeLines(File file, Collection<?> lines, String lineEnding, boolean append) throws IOException {
+        FileUtils.writeLines(file, lines, lineEnding, append);
+    }
+
+    public static void forceDelete(File file) throws IOException {
+        FileUtils.forceDelete(file);
+    }
+
+    public static void forceDeleteOnExit(File file) throws IOException {
+        FileUtils.forceDeleteOnExit(file);
+    }
+
+    public static void forceMkdir(File directory) throws IOException {
+        FileUtils.forceMkdir(directory);
+    }
+
+    public static void forceMkdirParent(File file) throws IOException {
+        FileUtils.forceMkdirParent(file);
+    }
+
+    public static long sizeOf(File file) {
+        return FileUtils.sizeOf(file);
+    }
+
+    public static BigInteger sizeOfAsBigInteger(File file) {
+        return FileUtils.sizeOfAsBigInteger(file);
+    }
+
+    public static long sizeOfDirectory(File directory) {
+        return FileUtils.sizeOfDirectory(directory);
+    }
+
+    public static BigInteger sizeOfDirectoryAsBigInteger(File directory) {
+        return FileUtils.sizeOfDirectoryAsBigInteger(directory);
+    }
+
+    public static boolean isFileNewer(File file, File reference) {
+        return FileUtils.isFileNewer(file, reference);
+    }
+
+    public static boolean isFileNewer(File file, Date date) {
+        return FileUtils.isFileNewer(file, date);
+    }
+
+    public static boolean isFileNewer(File file, long timeMillis) {
+        return FileUtils.isFileNewer(file, timeMillis);
+    }
+
+    public static boolean isFileOlder(File file, File reference) {
+        return FileUtils.isFileOlder(file, reference);
+    }
+
+    public static boolean isFileOlder(File file, Date date) {
+        return FileUtils.isFileOlder(file, date);
+    }
+
+    public static boolean isFileOlder(File file, long timeMillis) {
+        return FileUtils.isFileOlder(file, timeMillis);
+    }
+
+    public static long checksumCRC32(File file) throws IOException {
+        return FileUtils.checksumCRC32(file);
+    }
+
+    public static Checksum checksum(File file, Checksum checksum) throws IOException {
+        return FileUtils.checksum(file, checksum);
+    }
+
+    public static void moveDirectory(File srcDir, File destDir) throws IOException {
+        FileUtils.moveDirectory(srcDir, destDir);
+    }
+
+    public static void moveDirectoryToDirectory(File src, File destDir, boolean createDestDir) throws IOException {
+        FileUtils.moveDirectoryToDirectory(src, destDir, createDestDir);
+    }
+
+    public static void moveFile(File srcFile, File destFile) throws IOException {
+        FileUtils.moveFile(srcFile, destFile);
+    }
+
+    public static void moveFileToDirectory(File srcFile, File destDir, boolean createDestDir) throws IOException {
+        FileUtils.moveFileToDirectory(srcFile, destDir, createDestDir);
+    }
+
+    public static void moveToDirectory(File src, File destDir, boolean createDestDir) throws IOException {
+        FileUtils.moveToDirectory(src, destDir, createDestDir);
+    }
+
+    public static boolean isSymlink(File file) throws IOException {
+        return FileUtils.isSymlink(file);
+    }
+
+    /**
+     * 文件复制
+     * @param inputStream
+     * @param dscFile
+     * @throws IOException
+     */
+    public static void transferTo(InputStream inputStream,File dscFile,boolean autoCreateDscDir) throws IOException {
+        if(autoCreateDscDir&&!dscFile.exists()){
+            touchFile(dscFile,true);
+        }
+        FileOutputStream outputStream = new FileOutputStream(dscFile);
+        IOKit.copy(inputStream,outputStream);
+    }
+}

+ 187 - 0
src/main/java/com/goer/common/utils/fisok/raw/kit/IOKit.java

@@ -0,0 +1,187 @@
+package com.goer.common.utils.fisok.raw.kit;
+
+import com.goer.common.utils.fisok.raw.io.ByteInputStream;
+import com.goer.common.utils.fisok.raw.io.ByteOutputStream;
+import com.goer.common.utils.fisok.raw.lang.RawException;
+import org.apache.commons.io.IOUtils;
+
+import java.io.*;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc :
+ */
+public abstract class IOKit extends IOUtils {
+    public static void close(Closeable stream) {
+        try {
+            if (stream != null) {
+                stream.close();
+            }
+        } catch (IOException e) {
+            new RawException("close {0} error", stream.getClass().getName());
+        }
+    }
+
+    public static void close(AutoCloseable stream) {
+        try {
+            if (stream != null) {
+                stream.close();
+            }
+        } catch (Exception e) {
+            new RawException("close {0} error", stream.getClass().getName());
+        }
+    }
+
+    /**
+     * 把流转为字符数组缓冲区
+     *
+     * @param inputStream inputStream
+     * @return ByteOutputStream
+     * @throws IOException IOException
+     */
+    public static ByteOutputStream convertToByteArrayBuffer(InputStream inputStream) throws IOException {
+        ByteOutputStream byteBuffer = new ByteOutputStream();
+
+        int bufferSize = 1024 * 4;
+        byte[] buffer = new byte[bufferSize];
+        int len = 0;
+        while ((len = inputStream.read(buffer)) != -1) {
+            byteBuffer.write(buffer, 0, len);
+        }
+        return byteBuffer;
+    }
+
+    /**
+     * 将输入流中的数据写入字节数组
+     *
+     * @param inputStream inputStream
+     * @param isClose     isClose
+     * @return byte
+     * @throws IOException IOException
+     */
+    @SuppressWarnings("deprecation")
+    public static byte[] convertToBytes(InputStream inputStream, boolean isClose) throws IOException {
+        ByteOutputStream byteBuffer = convertToByteArrayBuffer(inputStream);
+        if (isClose) {
+            IOKit.close(inputStream);
+        }
+//        return byteBuffer.toByteArray();
+        return byteBuffer.toBytes();
+    }
+
+    /**
+     * 把流转为二进制
+     *
+     * @param inputStream inputStream
+     * @return byte
+     * @throws IOException IOException
+     */
+    public static byte[] convertToBytes(InputStream inputStream) throws IOException {
+        return convertToBytes(inputStream, false);
+    }
+
+    /**
+     * 转成二进制流
+     *
+     * @param inputStream inputStream
+     * @return ByteInputStream
+     * @throws IOException IOException
+     */
+    public static ByteInputStream convertToByteArrayInputStream(InputStream inputStream) throws IOException {
+        ByteOutputStream byteBuffer = convertToByteArrayBuffer(inputStream);
+        return byteBuffer.createInputStream();
+    }
+
+    /**
+     * 把二进制转为输入流
+     *
+     * @param bytes bytes
+     * @return InputStream
+     */
+    public static InputStream convertToInputStream(byte[] bytes) {
+        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+        return bis;
+    }
+
+    /**
+     * 文件流复制
+     *
+     * @param inputStream
+     * @param outputStream
+     * @throws IOException
+     */
+    public static void transferTo(InputStream inputStream, OutputStream outputStream) throws IOException {
+        IOKit.copy(inputStream, outputStream);
+    }
+
+
+    /**
+     * 根据流推测字符集
+     * @param inputStream
+     * @return
+     */
+    public static String getCharset(InputStream inputStream) {
+        //默认GBK
+        String charset = "GBK";
+        byte[] first3Bytes = new byte[3];
+        try (BufferedInputStream bis = new BufferedInputStream(inputStream)) {
+            bis.mark(0);
+            int read = bis.read(first3Bytes, 0, 3);
+            // 文件编码为 ANSI
+            if (read == -1) {
+                return charset;
+            }
+            // 文件编码为 Unicode
+            if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {
+                return "UTF-16LE";
+            }
+            // 文件编码为 Unicode big endian
+            if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) {
+                return "UTF-16BE";
+            }
+            // 文件编码为 UTF-8
+            if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF) {
+                return "UTF-8";
+            }
+            bis.reset();
+
+            int loc = 0;
+            while ((read = bis.read()) != -1) {
+                loc++;
+                if (read >= 0xF0) {
+                    break;
+                }
+                // 单独出现BF以下的,也算是GBK
+                if (0x80 <= read && read <= 0xBF) {
+                    break;
+                }
+                if (0xC0 <= read && read <= 0xDF) {
+                    read = bis.read();
+                    // 双字节 (0xC0 - 0xDF)
+                    if (0x80 <= read && read <= 0xBF) {
+                        // (0x80
+                        // - 0xBF),也可能在GB编码内
+                        continue;
+                    }
+                    break;
+                }
+                // 也有可能出错,但是几率较小
+                if (0xE0 <= read && read <= 0xEF) {
+                    read = bis.read();
+                    if (0x80 <= read && read <= 0xBF) {
+                        read = bis.read();
+                        if (0x80 <= read && read <= 0xBF) {
+                            charset = "UTF-8";
+                        }
+                    }
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            throw new RawException("计算inputStream的字符集出错",e);
+        }
+        return charset;
+    }
+
+}

+ 85 - 0
src/main/java/com/goer/common/utils/fisok/raw/kit/JSONKit.java

@@ -0,0 +1,85 @@
+package com.goer.common.utils.fisok.raw.kit;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc :
+ */
+public abstract class JSONKit {
+
+    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    static{
+        SimpleDateFormat sdf = new SimpleDateFormat(DateKit.DATE_TIME_MS_FORMAT);
+        OBJECT_MAPPER.setDateFormat(sdf);
+        //增加对localdate的支持
+        OBJECT_MAPPER.registerModule(new JavaTimeModule());
+    }
+
+    static {
+        // configure feature
+        OBJECT_MAPPER.disable(FAIL_ON_UNKNOWN_PROPERTIES);
+    }
+
+
+    public static synchronized String toJsonString(Object object,boolean prettify){
+        if(prettify){
+            OBJECT_MAPPER.enable(SerializationFeature.INDENT_OUTPUT);
+        }
+        try {
+            return OBJECT_MAPPER.writeValueAsString(object);
+        } catch (JsonProcessingException ex) {
+            throw new RuntimeException("convert object to json string error", ex);
+        } finally {
+            if(prettify){
+                OBJECT_MAPPER.disable(SerializationFeature.INDENT_OUTPUT);
+            }
+        }
+
+    }
+    public static String toJsonString(Object object){
+        try {
+            return OBJECT_MAPPER.writeValueAsString(object);
+        } catch (JsonProcessingException ex) {
+            throw new RuntimeException("convert object to json string error", ex);
+        }
+    }
+
+
+    public static <T>T jsonToBean(String text,Class<T> classType){
+        try {
+            return OBJECT_MAPPER.readValue(text, classType);
+        }catch (IOException ex) {
+            throw new RuntimeException("convert json string to object error", ex);
+        }
+    }
+
+    public static Map<String,Object> jsonToMap(String text){
+        try {
+            return OBJECT_MAPPER.readValue(text, LinkedHashMap.class);
+        }catch (IOException ex) {
+            throw new RuntimeException("convert json string to object error", ex);
+        }
+    }
+
+    public static <T> List<T> jsonToBeanList(String text, Class<T> classType){
+        try {
+            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory()
+                    .constructCollectionType(List.class, classType));
+        } catch (IOException ex) {
+            throw new RuntimeException("convert json string to list object error", ex);
+        }
+    }
+}

+ 93 - 0
src/main/java/com/goer/common/utils/fisok/raw/kit/JdbcKit.java

@@ -0,0 +1,93 @@
+package com.goer.common.utils.fisok.raw.kit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Properties;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc :
+ */
+public abstract class JdbcKit {
+    private static Logger logger = LoggerFactory.getLogger(JdbcKit.class);
+
+    public static void close(AutoCloseable closeable){
+        try {
+            if(closeable!=null){
+                closeable.close();
+            }
+        } catch (Exception e) {
+            logger.error("关闭出错",e);
+        }
+    }
+
+//    public static Connection getConnection(String driverClassName, String url, String username, String password){
+//        try {
+//            Class.forName(driverClassName);
+//        } catch (ClassNotFoundException e) {
+//            logger.error("",e);
+//            throw new RuntimeException("驱动加载失败,驱动类不存在(ClassNotFoundException)!出错消息:"+e.getMessage(),e);
+//        }
+//
+//        Connection conn = null;
+//        Properties props = new Properties();
+//        props.put("user", StringKit.nvl(username,""));
+//        props.put("password", StringKit.nvl(password,""));
+//
+//        conn = getConnection(driverClassName,url,props);
+//        return conn;
+//    }
+
+    public static Connection getConnection(String driverClassName,String url, Properties props){
+        try {
+            Class.forName(driverClassName);
+        } catch (ClassNotFoundException e) {
+            logger.error("",e);
+            throw new RuntimeException("驱动加载失败,驱动类不存在(ClassNotFoundException)!出错消息:"+e.getMessage(),e);
+        }
+        Connection conn = null;
+        try {
+            props.put("remarksReporting", "true");        //获取Oracle元数据 REMARKS信息
+            props.put("useInformationSchema", "true");    //获取MySQL元数据 REMARKS信息
+            conn = DriverManager.getConnection(url, props);
+        } catch (SQLException e) {
+            logger.error("",e);
+            throw new RuntimeException("连接失败!出错消息:"+e.getMessage(),e);
+        }
+        return conn;
+    }
+
+
+    public static boolean isNumeric(int sqlType) {
+        return Types.BIT == sqlType
+                || Types.BIGINT == sqlType
+                || Types.DECIMAL == sqlType
+                || Types.DOUBLE == sqlType
+                || Types.FLOAT == sqlType
+                || Types.INTEGER == sqlType
+                || Types.NUMERIC == sqlType
+                || Types.REAL == sqlType
+                || Types.SMALLINT == sqlType
+                || Types.TINYINT == sqlType;
+    }
+
+    public static boolean isDate(int sqlType) {
+        return Types.DATE == sqlType
+                || Types.TIME == sqlType
+                || Types.TIME_WITH_TIMEZONE == sqlType
+                || Types.TIMESTAMP_WITH_TIMEZONE == sqlType
+                || Types.TIMESTAMP == sqlType ;
+    }
+    public static boolean isShortString(int sqlType) {
+        return Types.VARCHAR == sqlType
+                || Types.CHAR == sqlType;
+//                || Types.LONGNVARCHAR == sqlType
+//                || Types.LONGVARCHAR == sqlType;
+    }
+}

+ 467 - 0
src/main/java/com/goer/common/utils/fisok/raw/kit/StringKit.java

@@ -0,0 +1,467 @@
+package com.goer.common.utils.fisok.raw.kit;
+
+import com.goer.common.utils.fisok.raw.RawConsts;
+import org.apache.commons.lang3.CharUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc : 字串操作
+ */
+public abstract class StringKit extends StringUtils {
+    /**
+     * 空串
+     *
+     * @param s  字串
+     * @param s1 字串为空时,返回的字串
+     * @return String
+     */
+    public static String nvl(Object s, String s1) {
+        String ss = "";
+        if (s instanceof String) {
+            ss = (String) s;
+        } else if (s == null) {
+            return s1;
+        } else {
+            ss = String.valueOf(s);
+        }
+
+        if (StringUtils.isEmpty(ss)) {
+            return s1;
+        }
+        return ss;
+    }
+
+    /**
+     * 模拟实现Oracle的decode函数
+     * decodeKeyValue("k1","k1","v1","s0") 返回 v1
+     * decodeKeyValue("k9","k1","v1","s0") 返回 s0
+     * decodeKeyValue("k2","k1","v1","k2","v2","s0") 返回 v2
+     * @param expression
+     * @param args
+     * @return
+     */
+    public static String decodeKeyValue(String expression,String ... args){
+        if(args == null || args.length == 0){
+            throw new IllegalArgumentException("调用StringKit.decodeKeyValue方法,参数为空");
+        }
+        if(args.length % 2 != 1){
+            throw new IllegalArgumentException("调用StringKit.decodeKeyValue方法,参数个数必需为奇数个");
+        }
+        for(int i=0;i<args.length;i+=2){
+            if(args[i].equals(expression)){
+                return args[i+1];
+            }
+        }
+        return args[args.length-1];//找不到,返回最后一个参数
+    }
+
+    /**
+     * 连接字串
+     *
+     * @param strList   strList
+     * @param delimiter delimiter
+     * @return string
+     */
+    public static String join(String[] strList, String delimiter) {
+        return join(Arrays.asList(strList), delimiter);
+    }
+
+    public static String join(final CharSequence... elements) {
+        return join8(elements, "");
+    }
+
+    /**
+     * JAVA8的字串连接
+     *
+     * @param array    array
+     * @param separator separator
+     * @return string
+     */
+    public static String join8(final CharSequence[] array, final String separator) {
+        StringJoiner joiner = new StringJoiner(separator);
+        for (CharSequence object : array) {
+            joiner.add(object);
+        }
+        return joiner.toString();
+    }
+
+    public static String trim(String str) {
+        return str == null ? null : str.trim();
+    }
+
+    public static String ltrim(String str) {
+        return str == null ? null : str.replaceAll("^\\\\s+", "");
+    }
+
+    public static String rtrim(String str) {
+        return str == null ? null : str.replaceAll("\\\\s+$", "");
+    }
+
+    public static String clearSpace(String str) {
+        return str == null ? null : str.replaceAll("\\\\s+", "");
+    }
+
+    public static boolean equals(String str1, String str2) {
+        return str1 == null ? str2 == null : str1.equals(str2);
+    }
+
+    public static String[] toStringArray(Collection<String> collection) {
+        if (collection == null) {
+            return null;
+        }
+        return collection.toArray(new String[collection.size()]);
+    }
+
+    // ==========================================================================
+    // Perl风格的chomp和chop函数。
+    // ==========================================================================
+
+    /**
+     * 删除字符串末尾的换行符。如果字符串不以换行结尾,则什么也不做。
+     * <p>
+     * 换行符有三种情形:&quot;<code>\n</code>&quot;、&quot;<code>\r</code>&quot;、&quot;
+     * <code>\r\n</code>&quot;。
+     * <p/>
+     * <pre>
+     * chomp(null)          = null
+     * chomp("")            = ""
+     * chomp("abc \r")      = "abc "
+     * chomp("abc\n")       = "abc"
+     * chomp("abc\r\n")     = "abc"
+     * chomp("abc\r\n\r\n") = "abc\r\n"
+     * chomp("abc\n\r")     = "abc\n"
+     * chomp("abc\n\rabc")  = "abc\n\rabc"
+     * chomp("\r")          = ""
+     * chomp("\n")          = ""
+     * chomp("\r\n")        = ""
+     * </pre>
+     * <p/>
+     * </p>
+     *
+     * @param str 要处理的字符串
+     * @return 不以换行结尾的字符串,如果原始字串为<code>null</code>,则返回<code>null</code>
+     */
+    public static String chomp(String str) {
+        if (str == null || str.length() == 0) {
+            return str;
+        }
+
+        if (str.length() == 1) {
+            char ch = str.charAt(0);
+
+            if (ch == '\r' || ch == '\n') {
+                return RawConsts.EMPTY_STRING;
+            } else {
+                return str;
+            }
+        }
+
+        int lastIdx = str.length() - 1;
+        char last = str.charAt(lastIdx);
+
+        if (last == '\n') {
+            if (str.charAt(lastIdx - 1) == '\r') {
+                lastIdx--;
+            }
+        } else if (last == '\r') {
+        } else {
+            lastIdx++;
+        }
+
+        return str.substring(0, lastIdx);
+    }
+
+    /**
+     * 删除最后一个字符。
+     * <p>
+     * 如果字符串以<code>\r\n</code>结尾,则同时删除它们。
+     * <p/>
+     * <pre>
+     * chop(null)          = null
+     * chop("")            = ""
+     * chop("abc \r")      = "abc "
+     * chop("abc\n")       = "abc"
+     * chop("abc\r\n")     = "abc"
+     * chop("abc")         = "ab"
+     * chop("abc\nabc")    = "abc\nab"
+     * chop("a")           = ""
+     * chop("\r")          = ""
+     * chop("\n")          = ""
+     * chop("\r\n")        = ""
+     * </pre>
+     * <p/>
+     * </p>
+     *
+     * @param str 要处理的字符串
+     * @return 删除最后一个字符的字符串,如果原始字符串为<code>null</code>,则返回<code>null</code>
+     */
+    public static String chop(String str) {
+        if (str == null) {
+            return null;
+        }
+
+        int strLen = str.length();
+
+        if (strLen < 2) {
+            return RawConsts.EMPTY_STRING;
+        }
+
+        int lastIdx = strLen - 1;
+        String ret = str.substring(0, lastIdx);
+        char last = str.charAt(lastIdx);
+
+        if (last == '\n') {
+            if (ret.charAt(lastIdx - 1) == '\r') {
+                return ret.substring(0, lastIdx - 1);
+            }
+        }
+
+        return ret;
+    }
+
+    public static String format(String tpl, Object... args) {
+        return MessageFormat.format(tpl, args);
+    }
+
+    /**
+     * 把驼峰转为下划线,并且全大写,例如:PersonName转为PERSON_NAME
+     *
+     * @param property property
+     * @return String
+     */
+    public static String camelToUnderline(String property) {
+        return camelTo(property,"_");
+    }
+
+    /**
+     * 把驼峰转为下划线,并且全大写,例如:PersonName转为PERSON_NAME
+     *
+     * @param property property
+     * @return String
+     */
+    public static String camelTo(String property,String delimiter) {
+//        return CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, str);
+
+//        String[] strs = splitByCharacterTypeCamelCase(str);
+//        List<String> strArray = Arrays
+//                .stream(strs)
+//                .map(s -> s.toUpperCase())
+//                .collect(Collectors.toList());
+//        return join(strArray,"_");
+
+        if (StringKit.isBlank(property)) {
+            return property;
+        }
+
+        char[] chars = property.toCharArray();
+        StringBuffer sb = new StringBuffer();
+        for (char c : chars) {
+            if (CharUtils.isAsciiAlphaUpper(c)) {
+                sb.append(delimiter + StringUtils.lowerCase(CharUtils.toString(c)));
+            } else {
+                sb.append(c);
+            }
+        }
+        String ret = sb.toString();
+
+        //处理可能出现的多个下划线
+        ret = ret.replaceAll(delimiter+"+", delimiter);
+        ret = removeStart(ret, delimiter);
+        ret = removeEnd(ret, delimiter);
+        ret = ret.toUpperCase();
+
+        return ret;
+
+    }
+
+    /**
+     * 把下划线转为驼峰,例如:PERSON_NAME转为PersonName
+     *
+     * @param str str
+     * @return String
+     */
+    public static String underlineToCamel(String str) {
+        return toCamel("_",str);
+    }
+
+    /**
+     * 把指定分割线转为驼峰,例如:PERSON-NAME转为PersonName
+     * @param delimiter 分割符
+     * @param str
+     * @return
+     */
+    public static String toCamel(String delimiter,String str) {
+//        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, str);
+//        List<String> strArray = Arrays
+//                .stream(strs)
+//                .map(s -> lowerCase(s))
+//                .map(s -> capitalize(s))
+//                .collect(Collectors.toList());
+        if (StringKit.isBlank(str)) {
+            return str;
+        }
+
+        String[] strs = split(str, delimiter);
+        for (int i = 0; i < strs.length; i++) {
+            strs[i] = lowerCase(strs[i]);
+            if (i > 0) {
+                strs[i] = capitalize(strs[i]);
+            }
+        }
+        return join(strs);
+    }
+
+
+    /**
+     * 使用变量填充字串模板 ${name}你好,{name:李雷}
+     *
+     * @param tpl  tpl
+     * @param vars vars
+     * @return String
+     */
+    public static String fillTpl(String tpl, Map<String, String> vars) {
+        Set<Map.Entry<String, String>> sets = vars.entrySet();
+        for (Map.Entry<String, String> entry : sets) {
+            String regex = "\\$\\{" + entry.getKey() + "\\}";
+            Pattern pattern = Pattern.compile(regex);
+            Matcher matcher = pattern.matcher(tpl);
+            tpl = matcher.replaceAll(entry.getValue());
+        }
+        return tpl;
+    }
+
+    public static String uuid() {
+        return uuid("");
+    }
+
+    public static String uuid(String delimiter) {
+        String uuid = UUID.randomUUID().toString();	//获取UUID并转化为String对象
+        uuid = uuid.replace("-", delimiter);				//因为UUID本身为32位只是生成时多了“-”,所以将它们去点就可
+        return uuid;
+    }
+
+    public static String maxLenLimit(String str,int len){
+        if(StringKit.isBlank(str)) {
+            return str;
+        }
+        if(str.length()>len) {
+            return str.substring(0,len);
+        } else {
+            return str;
+        }
+    }
+
+    /**
+     * 中文转unicode字符
+     * @param cnStr
+     * @return
+     */
+    public static String chineseToUnicode(final String cnStr) {
+
+        try {
+            StringBuffer out = new StringBuffer("");
+            //直接获取字符串的unicode二进制
+            byte[] bytes = cnStr.getBytes("unicode");
+            //然后将其byte转换成对应的16进制表示即可
+            for (int i = 0; i < bytes.length - 1; i += 2) {
+                out.append("\\u");
+                String str = Integer.toHexString(bytes[i + 1] & 0xff);
+                for (int j = str.length(); j < 2; j++) {
+                    out.append("0");
+                }
+                String str1 = Integer.toHexString(bytes[i] & 0xff);
+                out.append(str1);
+                out.append(str);
+            }
+            return out.toString();
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * unicode转中文字符
+     * @param unicodeStr
+     * @return
+     */
+    public static String unicodeToChinese(final String unicodeStr) {
+        Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
+        Matcher matcher = pattern.matcher(unicodeStr);
+        String cnStr = unicodeStr;
+        char ch;
+        while (matcher.find()) {
+            //group
+            String group = matcher.group(2);
+            //ch:'李四'
+            ch = (char) Integer.parseInt(group, 16);
+            //group1
+            String group1 = matcher.group(1);
+            cnStr = cnStr.replace(group1, ch + "");
+        }
+        return cnStr.replace("\\", "").trim();
+    }
+
+    private static String HEX_STR =  "0123456789ABCDEF";
+    /**
+     *
+     * @param bytes
+     * @return 将二进制转换为十六进制字符输出
+     */
+    public static String bytesToHex(byte[] bytes){
+
+        String result = "";
+        String hex = "";
+        for(int i=0;i<bytes.length;i++){
+            //字节高4位
+            hex = String.valueOf(HEX_STR.charAt((bytes[i]&0xF0)>>4));
+            //字节低4位
+            hex += String.valueOf(HEX_STR.charAt(bytes[i]&0x0F));
+            result +=hex+" ";
+        }
+        return result;
+    }
+    /**
+     *
+     * @param hexString
+     * @return 将十六进制转换为字节数组
+     */
+    public static byte[] hexToBytes(String hexString){
+        //hexString的长度对2取整,作为bytes的长度
+        int len = hexString.length()/2;
+        byte[] bytes = new byte[len];
+        byte high = 0;//字节高四位
+        byte low = 0;//字节低四位
+
+        for(int i=0;i<len;i++){
+            //右移四位得到高位
+            high = (byte)((HEX_STR.indexOf(hexString.charAt(2*i)))<<4);
+            low = (byte) HEX_STR.indexOf(hexString.charAt(2*i+1));
+            bytes[i] = (byte) (high|low);//高地位做或运算
+        }
+        return bytes;
+    }
+
+    /**
+     * 判断是否为数字
+     * @param str
+     * @return
+     */
+    public static boolean isNumeric(String str) {
+        try {
+            new BigDecimal(str).toString();
+        } catch (Exception e) {
+            return false;//异常 说明包含非数字。
+        }
+        return true;
+    }
+
+}

+ 432 - 0
src/main/java/com/goer/common/utils/fisok/raw/kit/ValidateKit.java

@@ -0,0 +1,432 @@
+package com.goer.common.utils.fisok.raw.kit;
+
+import com.goer.common.utils.fisok.raw.lang.RawException;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+
+import java.text.MessageFormat;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc :
+ */
+public abstract class ValidateKit {
+
+    private static final String DEFAULT_NOT_NAN_EX_MESSAGE = "The validated value is not a number";
+    private static final String DEFAULT_FINITE_EX_MESSAGE = "The value is invalid: {0,number,#.#}";
+    private static final String DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE = "The value {0} is not in the specified exclusive range of {1} to {2}";
+    private static final String DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE = "The value {0} is not in the specified inclusive range of {1} to {2}";
+    private static final String DEFAULT_MATCHES_PATTERN_EX = "The string {0} does not match the pattern {1}";
+    private static final String DEFAULT_IS_NULL_EX_MESSAGE = "The validated object is null";
+    private static final String DEFAULT_IS_TRUE_EX_MESSAGE = "The validated expression is false";
+    private static final String DEFAULT_NO_NULL_ELEMENTS_ARRAY_EX_MESSAGE = "The validated array contains null element at index: {0,number}";
+    private static final String DEFAULT_NO_NULL_ELEMENTS_COLLECTION_EX_MESSAGE = "The validated collection contains null element at index: {0,number}";
+    private static final String DEFAULT_NOT_BLANK_EX_MESSAGE = "The validated character sequence is blank";
+    private static final String DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE = "The validated array is empty";
+    private static final String DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE = "The validated character sequence is empty";
+    private static final String DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE = "The validated collection is empty";
+    private static final String DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE = "The validated map is empty";
+    private static final String DEFAULT_VALID_INDEX_ARRAY_EX_MESSAGE = "The validated array index is invalid: {0,number}";
+    private static final String DEFAULT_VALID_INDEX_CHAR_SEQUENCE_EX_MESSAGE = "The validated character sequence index is invalid: {0,number}";
+    private static final String DEFAULT_VALID_INDEX_COLLECTION_EX_MESSAGE = "The validated collection index is invalid: {0,number}";
+    private static final String DEFAULT_VALID_STATE_EX_MESSAGE = "The validated state is false";
+    private static final String DEFAULT_IS_ASSIGNABLE_EX_MESSAGE = "Cannot assign a {0} to a {1}";
+    private static final String DEFAULT_IS_INSTANCE_OF_EX_MESSAGE = "Expected type: {0}, actual: {1}";
+
+    public static void isTrue(final boolean expression, final String message, final long value) {
+        if (expression == false) {
+            throw new IllegalArgumentException(format(message, Long.valueOf(value)));
+        }
+    }
+
+    public static void isTrue(final boolean expression, final String message, final double value) {
+        if (expression == false) {
+            throw new IllegalArgumentException(format(message, Double.valueOf(value)));
+        }
+    }
+
+
+    public static void isTrue(final boolean expression, final String message, final Object... values) {
+        if (expression == false) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+    }
+
+
+    public static void isTrue(final boolean expression) {
+        if (expression == false) {
+            throw new IllegalArgumentException(DEFAULT_IS_TRUE_EX_MESSAGE);
+        }
+    }
+
+    public static void isFalse(final boolean expression, final String message, final Object... values) {
+        if (expression == true) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+    }
+
+    public static void isFalse(final boolean expression) {
+        if (expression == true) {
+            throw new IllegalArgumentException(DEFAULT_IS_TRUE_EX_MESSAGE);
+        }
+    }
+
+
+    public static <T> T notNull(final T object) {
+        return notNull(object, DEFAULT_IS_NULL_EX_MESSAGE);
+    }
+
+
+    public static <T> T notNull(final T object, final String message, final Object... values) {
+        if (object == null) {
+            throw new NullPointerException(format(message, values));
+        }
+        return object;
+    }
+
+
+    public static <T> T[] notEmpty(final T[] array, final String message, final Object... values) {
+        if (array == null) {
+            throw new NullPointerException(format(message, values));
+        }
+        if (array.length == 0) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+        return array;
+    }
+
+
+    public static <T> T[] notEmpty(final T[] array) {
+        return notEmpty(array, DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE);
+    }
+
+
+    public static <T extends Collection<?>> T notEmpty(final T collection, final String message, final Object... values) {
+        if (collection == null) {
+            throw new NullPointerException(format(message, values));
+        }
+        if (collection.isEmpty()) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+        return collection;
+    }
+
+
+    public static <T extends Collection<?>> T notEmpty(final T collection) {
+        return notEmpty(collection, DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE);
+    }
+
+
+    public static <T extends Map<?, ?>> T notEmpty(final T map, final String message, final Object... values) {
+        if (map == null) {
+            throw new NullPointerException(format(message, values));
+        }
+        if (map.isEmpty()) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+        return map;
+    }
+
+
+    public static <T extends Map<?, ?>> T notEmpty(final T map) {
+        return notEmpty(map, DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE);
+    }
+
+
+    public static <T extends CharSequence> T notEmpty(final T chars, final String message, final Object... values) {
+        if (chars == null) {
+            throw new NullPointerException(format(message, values));
+        }
+        if (chars.length() == 0) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+        return chars;
+    }
+
+
+    public static <T extends CharSequence> T notEmpty(final T chars) {
+        return notEmpty(chars, DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE);
+    }
+
+
+    public static <T extends CharSequence> T notBlank(final T chars, final String message, final Object... values) {
+        if (chars == null) {
+            throw new NullPointerException(format(message, values));
+        }
+        if (StringUtils.isBlank(chars)) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+        return chars;
+    }
+
+
+    public static <T extends CharSequence> T notBlank(final T chars) {
+        return notBlank(chars, DEFAULT_NOT_BLANK_EX_MESSAGE);
+    }
+
+
+    public static <T> T[] noNullElements(final T[] array, final String message, final Object... values) {
+        Validate.notNull(array);
+        for (int i = 0; i < array.length; i++) {
+            if (array[i] == null) {
+                final Object[] values2 = ArrayUtils.add(values, Integer.valueOf(i));
+                throw new IllegalArgumentException(format(message, values2));
+            }
+        }
+        return array;
+    }
+
+
+    public static <T> T[] noNullElements(final T[] array) {
+        return noNullElements(array, DEFAULT_NO_NULL_ELEMENTS_ARRAY_EX_MESSAGE);
+    }
+
+
+    public static <T extends Iterable<?>> T noNullElements(final T iterable, final String message, final Object... values) {
+        Validate.notNull(iterable);
+        int i = 0;
+        for (final Iterator<?> it = iterable.iterator(); it.hasNext(); i++) {
+            if (it.next() == null) {
+                final Object[] values2 = ArrayUtils.addAll(values, Integer.valueOf(i));
+                throw new IllegalArgumentException(format(message, values2));
+            }
+        }
+        return iterable;
+    }
+
+
+    public static <T extends Iterable<?>> T noNullElements(final T iterable) {
+        return noNullElements(iterable, DEFAULT_NO_NULL_ELEMENTS_COLLECTION_EX_MESSAGE);
+    }
+
+
+    public static <T> T[] validIndex(final T[] array, final int index, final String message, final Object... values) {
+        Validate.notNull(array);
+        if (index < 0 || index >= array.length) {
+            throw new IndexOutOfBoundsException(format(message, values));
+        }
+        return array;
+    }
+
+
+    public static <T> T[] validIndex(final T[] array, final int index) {
+        return validIndex(array, index, DEFAULT_VALID_INDEX_ARRAY_EX_MESSAGE, Integer.valueOf(index));
+    }
+
+
+    public static <T extends Collection<?>> T validIndex(final T collection, final int index, final String message, final Object... values) {
+        Validate.notNull(collection);
+        if (index < 0 || index >= collection.size()) {
+            throw new IndexOutOfBoundsException(format(message, values));
+        }
+        return collection;
+    }
+
+
+    public static <T extends Collection<?>> T validIndex(final T collection, final int index) {
+        return validIndex(collection, index, DEFAULT_VALID_INDEX_COLLECTION_EX_MESSAGE, Integer.valueOf(index));
+    }
+
+
+    public static <T extends CharSequence> T validIndex(final T chars, final int index, final String message, final Object... values) {
+        Validate.notNull(chars);
+        if (index < 0 || index >= chars.length()) {
+            throw new IndexOutOfBoundsException(format(message, values));
+        }
+        return chars;
+    }
+
+
+    public static <T extends CharSequence> T validIndex(final T chars, final int index) {
+        return validIndex(chars, index, DEFAULT_VALID_INDEX_CHAR_SEQUENCE_EX_MESSAGE, Integer.valueOf(index));
+    }
+
+
+    public static void validState(final boolean expression) {
+        if (expression == false) {
+            throw new IllegalStateException(DEFAULT_VALID_STATE_EX_MESSAGE);
+        }
+    }
+
+
+    public static void validState(final boolean expression, final String message, final Object... values) {
+        if (expression == false) {
+            throw new IllegalStateException(format(message, values));
+        }
+    }
+
+
+    public static void matchesPattern(final CharSequence input, final String pattern) {
+        if (Pattern.matches(pattern, input) == false) {
+            throw new IllegalArgumentException(format(DEFAULT_MATCHES_PATTERN_EX, input, pattern));
+        }
+    }
+
+
+    public static void matchesPattern(final CharSequence input, final String pattern, final String message, final Object... values) {
+        if (Pattern.matches(pattern, input) == false) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+    }
+
+
+    public static void notNaN(final double value) {
+        notNaN(value, DEFAULT_NOT_NAN_EX_MESSAGE);
+    }
+
+
+    public static void notNaN(final double value, final String message, final Object... values) {
+        if (Double.isNaN(value)) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+    }
+
+
+    public static void finite(final double value) {
+        finite(value, DEFAULT_FINITE_EX_MESSAGE, value);
+    }
+
+
+    public static void finite(final double value, final String message, final Object... values) {
+        if (Double.isNaN(value) || Double.isInfinite(value)) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+    }
+
+
+    public static <T> void inclusiveBetween(final T start, final T end, final Comparable<T> value) {
+        if (value.compareTo(start) < 0 || value.compareTo(end) > 0) {
+            throw new IllegalArgumentException(format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
+        }
+    }
+
+
+    public static <T> void inclusiveBetween(final T start, final T end, final Comparable<T> value, final String message, final Object... values) {
+        if (value.compareTo(start) < 0 || value.compareTo(end) > 0) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+    }
+
+
+    @SuppressWarnings("boxing")
+    public static void inclusiveBetween(final long start, final long end, final long value) {
+        if (value < start || value > end) {
+            throw new IllegalArgumentException(format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
+        }
+    }
+
+
+    public static void inclusiveBetween(final long start, final long end, final long value, final String message) {
+        if (value < start || value > end) {
+            throw new IllegalArgumentException(format(message));
+        }
+    }
+
+
+    @SuppressWarnings("boxing")
+    public static void inclusiveBetween(final double start, final double end, final double value) {
+        if (value < start || value > end) {
+            throw new IllegalArgumentException(format(DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
+        }
+    }
+
+
+    public static void inclusiveBetween(final double start, final double end, final double value, final String message) {
+        if (value < start || value > end) {
+            throw new IllegalArgumentException(format(message));
+        }
+    }
+
+
+    public static <T> void exclusiveBetween(final T start, final T end, final Comparable<T> value) {
+        if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) {
+            throw new IllegalArgumentException(format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
+        }
+    }
+
+
+    public static <T> void exclusiveBetween(final T start, final T end, final Comparable<T> value, final String message, final Object... values) {
+        if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+    }
+
+
+    @SuppressWarnings("boxing")
+    public static void exclusiveBetween(final long start, final long end, final long value) {
+        if (value <= start || value >= end) {
+            throw new IllegalArgumentException(format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
+        }
+    }
+
+
+    public static void exclusiveBetween(final long start, final long end, final long value, final String message) {
+        if (value <= start || value >= end) {
+            throw new IllegalArgumentException(format(message));
+        }
+    }
+
+
+    @SuppressWarnings("boxing")
+    public static void exclusiveBetween(final double start, final double end, final double value) {
+        if (value <= start || value >= end) {
+            throw new IllegalArgumentException(format(DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE, value, start, end));
+        }
+    }
+
+
+    public static void exclusiveBetween(final double start, final double end, final double value, final String message) {
+        if (value <= start || value >= end) {
+            throw new IllegalArgumentException(format(message));
+        }
+    }
+
+    public static void isInstanceOf(final Class<?> type, final Object obj) {
+        if (type.isInstance(obj) == false) {
+            throw new IllegalArgumentException(format(DEFAULT_IS_INSTANCE_OF_EX_MESSAGE, type.getName(),
+                    obj == null ? "null" : obj.getClass().getName()));
+        }
+    }
+
+
+    public static void isInstanceOf(final Class<?> type, final Object obj, final String message, final Object... values) {
+        if (type.isInstance(obj) == false) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+    }
+
+
+    public static void isAssignableFrom(final Class<?> superType, final Class<?> type) {
+        if (superType.isAssignableFrom(type) == false) {
+            throw new IllegalArgumentException(format(DEFAULT_IS_ASSIGNABLE_EX_MESSAGE, type == null ? "null" : type.getName(),
+                    superType.getName()));
+        }
+    }
+
+
+    public static void isAssignableFrom(final Class<?> superType, final Class<?> type, final String message, final Object... values) {
+        if (superType.isAssignableFrom(type) == false) {
+            throw new IllegalArgumentException(format(message, values));
+        }
+    }
+
+    public static void isNotExist(Object object,final String message, final Object... values){
+        if(object==null){
+            throw new RawException(message,values);
+        }
+    }
+
+    private static String format(String pattern,Object... args){
+        return MessageFormat.format(pattern,args);
+    }
+    private static String format(String pattern){
+        return pattern;
+    }
+
+}

+ 54 - 0
src/main/java/com/goer/common/utils/fisok/raw/lang/RawException.java

@@ -0,0 +1,54 @@
+package com.goer.common.utils.fisok.raw.lang;
+
+import java.text.MessageFormat;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc :
+ */
+public class RawException extends RuntimeException{
+
+    private static final long serialVersionUID = -2049467256019982005L;
+    private String code = "0";
+
+
+    public RawException() {
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public RawException(String message) {
+        super(message);
+    }
+
+    public RawException(String messageFormat, Object ...objects) {
+        this(MessageFormat.format(messageFormat, objects));
+    }
+    public RawException(Throwable cause, String messageFormat, Object ...objects) {
+        this(MessageFormat.format(messageFormat, objects),cause);
+    }
+
+    public RawException(Throwable cause, String message) {
+        super(message, cause);
+    }
+
+    public RawException(Throwable cause) {
+        super(cause);
+    }
+
+
+    public RawException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public RawException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+}

+ 387 - 0
src/main/java/com/goer/common/utils/fisok/raw/lang/ValueObject.java

@@ -0,0 +1,387 @@
+package com.goer.common.utils.fisok.raw.lang;
+
+import com.goer.common.utils.fisok.raw.kit.DateKit;
+import com.goer.common.utils.fisok.raw.kit.StringKit;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc :
+ */
+public class ValueObject {
+    private Object value;
+    private ValueType type;
+    private static Pattern NUMBER_PATTERN = Pattern.compile("^(\\-|\\+)?\\d+(\\.\\d+)?$");
+    private static DecimalFormat NUMBER_FORMAT = new DecimalFormat("#.################################");
+    private Map<String,Object> properties = new HashMap<String,Object>();
+
+    public enum ValueType {
+        String, Boolean, Number,Double,Integer, Long,Date, Object, Null,Array,List
+    }
+
+    public void setValueType(ValueType type) {
+        this.type = type;
+    }
+
+    public ValueType getValueType() {
+        return type;
+    }
+
+    public static ValueObject valueOf(Object value) {
+        return new ValueObject(value);
+    }
+
+    public ValueObject() {
+        setValue(null);
+    }
+    public ValueObject(Object value) {
+        setValue(value);
+    }
+
+    public void setNull(){
+        setValue(null);
+    }
+
+    public void setValue(Object value){
+        if(value instanceof ValueObject){
+            value = ((ValueObject)value).value();
+        }
+        if(type==null){
+            if (value == null) {
+                this.type = ValueType.Null;
+            } else if (value instanceof String) {
+                this.type = ValueType.String;
+            } else if (value instanceof Number) {
+                this.type = ValueType.Number;
+            } else if (value instanceof Date) {
+                this.type = ValueType.Date;
+            } else if(value instanceof List) {
+                this.type = ValueType.List;
+            } else if(value.getClass().isArray()) {
+                this.type = ValueType.Array;
+            } else {
+                this.type = ValueType.Object;
+            }
+        }
+        this.value = value;
+    }
+
+    public Object value() {
+        return this.value;
+    }
+
+    public Object getValue() {
+        return this.value;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T objectVal(Class<T> classType) {
+        return (T) value;
+    }
+
+    public Number numberValue() {
+        if(value == null) {
+            return null;
+        }
+        if (type == ValueType.Number) {
+            return (Number) value;
+        }else if (type == ValueType.Double) {
+            return (Double) value;
+        }else if (type == ValueType.Integer) {
+            return (Integer) value;
+        } else if (type == ValueType.Long) {
+            return (Long) value;
+        }  else if (type == ValueType.String && NUMBER_PATTERN.matcher((String) value).matches()) {
+//            return Double.parseDouble((String) value);
+            return new BigDecimal((String) value);
+        } else {
+            throw new RuntimeException("value [" + value + "] is not a digital format");
+        }
+    }
+
+    public boolean isNumberic(){
+        return value instanceof Number;
+    }
+
+    public Long longValue() {
+        Number number = numberValue();
+        return number != null ? number.longValue() : null;
+    }
+
+    public Long longValue(Long defaultValue) {
+        if(numberValue()==null) {
+            return defaultValue;
+        }
+        return longValue();
+    }
+
+    public Integer intValue() {
+        Number number = numberValue();
+        return number != null ? number.intValue() : null;
+    }
+    public Integer intValue(Integer defaultValue) {
+        if(numberValue()==null) {
+            return defaultValue;
+        }
+        return intValue();
+    }
+
+    public Double doubleValue() {
+        Number number = numberValue();
+        return number != null ? number.doubleValue() : null;
+    }
+    public Double doubleValue(Double defaultValue) {
+        if(numberValue()==null) {
+            return defaultValue;
+        }
+        return doubleValue();
+    }
+
+    public String strValue() {
+        return strValue(null);
+    }
+    public String strValue(String defaultValue) {
+        if(value == null) {
+            return defaultValue;
+        }
+
+        try{
+            if (type == ValueType.Number) {
+                return NUMBER_FORMAT.format(numberValue());
+            } else if (type == ValueType.String) {
+                return String.valueOf(value);
+            } else if (type == ValueType.Date) {
+                return (new SimpleDateFormat(DateKit.DATE_TIME_FORMAT)).format(dateValue());
+            } else if (type == ValueType.Null) {
+                return defaultValue;
+            } else {
+                return value.toString();
+            }
+        }catch (Exception e){
+            return String.valueOf(value);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    public Date dateValue() {
+        if (type == ValueType.Number) {
+            return DateKit.parse(longValue());
+        } else if (type == ValueType.String) {
+            String strValue = strValue();
+            //如果是数字类型的,就按数字类型转
+            if(strValue.matches("\\d+")){
+                return DateKit.parse(longValue());
+            }else{
+                return DateKit.parse(strValue());
+            }
+        } else if (type == ValueType.Date) {
+            return (Date) value;
+        } else if (type == ValueType.Null) {
+            return null;
+        } else {
+            try{
+                return DateKit.parse(strValue());
+            }catch (Exception e){
+                throw new RuntimeException("value [" + value + "] is not a date format");
+            }
+        }
+    }
+
+    public Boolean boolValue() {
+        if (type == ValueType.String) {
+            return Boolean.parseBoolean(strValue());
+        } else if (type == ValueType.Boolean) {
+            return (Boolean) value;
+        } else if (type == ValueType.Null) {
+            return null;
+        } else {
+            try{
+                return Boolean.parseBoolean(strValue());
+            }catch (Exception e){
+                throw new RuntimeException("value [" + value + "] is not a boolean format");
+            }
+        }
+    }
+
+    public Boolean boolValue(Boolean defaultValue){
+        if(boolValue()==null) {
+            return defaultValue;
+        }
+        return boolValue();
+    }
+
+    public Object[] objectArray(){
+        Object[] values = null;
+        if(value==null) {
+            return values;
+        }
+        if(value.getClass().isArray()){
+            return (Object[])value;
+        }else if(value instanceof List){
+            @SuppressWarnings("rawtypes")
+            List<?> vList = (List)value;
+            values = new Object[vList.size()];
+            for(int i=0;i<vList.size();i++){
+                values[i] = vList.get(i);
+            }
+        }else{
+            values = new Object[]{value};
+        }
+        return values;
+    }
+
+    public Number[] numberArray(){
+        Object[] values = objectArray();
+        if(values==null||values.length==0) {
+            return null;
+        }
+        Number[] ret = new Number[values.length];
+        for(int i=0;i<values.length;i++){
+            ValueObject vo = new ValueObject(values[i]);
+            ret[i] = vo.numberValue();
+        }
+        return ret;
+    }
+
+    public Long[] longArray() {
+        Number[] numbers = numberArray();
+        Long[] ret = new Long[numbers.length];
+        for(int i=0;i<numbers.length;i++){
+            ret[i] = numbers[i].longValue();
+        }
+        return ret;
+    }
+
+    public Integer[] intArray() {
+        Number[] numbers = numberArray();
+        Integer[] ret = new Integer[numbers.length];
+        for(int i=0;i<numbers.length;i++){
+            ret[i] = numbers[i].intValue();
+        }
+        return ret;
+    }
+
+    public Double[] doubleArray() {
+        Number[] numbers = numberArray();
+        Double[] ret = new Double[numbers.length];
+        for(int i=0;i<numbers.length;i++){
+            ret[i] = numbers[i].doubleValue();
+        }
+        return ret;
+    }
+
+    public String[] strArray() {
+        Object[] values = objectArray();
+        if(values==null||values.length==0) {
+            return null;
+        }
+        String[] ret = new String[values.length];
+        for(int i=0;i<values.length;i++){
+            ValueObject vo = new ValueObject(values[i]);
+            ret[i] = vo.strValue();
+        }
+        return ret;
+    }
+
+    public Date[] dateArray() {
+        Object[] values = objectArray();
+        if(values==null||values.length==0) {
+            return null;
+        }
+        Date[] ret = new Date[values.length];
+        for(int i=0;i<values.length;i++){
+            ValueObject vo = new ValueObject(values[i]);
+            ret[i] = vo.dateValue();
+        }
+        return ret;
+    }
+
+    public Boolean[] boolArray() {
+        Object[] values = objectArray();
+        if(values==null||values.length==0) {
+            return null;
+        }
+        Boolean[] ret = new Boolean[values.length];
+        for(int i=0;i<values.length;i++){
+            ValueObject vo = new ValueObject(values[i]);
+            ret[i] = vo.boolValue();
+        }
+        return ret;
+    }
+
+    /**
+     * 值是否为NULL
+     *
+     * @return boolean
+     */
+    public boolean isNull() {
+        return value == null;
+    }
+
+    /**
+     * 值对象是否为没有内容,例如空字串,空集合等情况
+     *
+     * @return boolean
+     */
+    @SuppressWarnings("rawtypes")
+    public boolean isEmpty() {
+        if (isNull()) {
+            return true;
+        }
+        if (value.getClass().isArray()) {
+            return ((Object[]) value).length == 0;
+        } else if (value instanceof Collection) {
+            return ((Collection) value).size() == 0;
+        }
+        return false;
+    }
+
+    public boolean isBlank(){
+        if (isNull()) {
+            return true;
+        }
+        return StringKit.isBlank(strValue());
+    }
+
+    public boolean isArray(){
+        if(value==null) {
+            return false;
+        }
+        return value.getClass().isArray();
+    }
+
+    @Override
+    public String toString() {
+        if(isArray()){
+            StringBuffer stringBuffer = new StringBuffer("{");
+            Object[] values = objectArray();
+            for(int i=0;i<values.length;i++){
+                stringBuffer.append(values[i]).append(",");
+            }
+            if(stringBuffer.charAt(stringBuffer.length()-1) == ','){
+                stringBuffer.deleteCharAt(stringBuffer.length()-1);
+            }
+            stringBuffer.append("}");
+            return stringBuffer.toString();
+        }else{
+            if (value != null) {
+                return strValue();
+            } else {
+                return null;
+            }
+        }
+    }
+
+    public void setProperty(String name,Object value){
+        properties.put(name,value);
+    }
+    public Object getProperty(String name){
+        return properties.get(name);
+    }
+}

+ 72 - 0
src/main/java/com/goer/common/utils/fisok/sqloy/core/DBType.java

@@ -0,0 +1,72 @@
+package com.goer.common.utils.fisok.sqloy.core;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc : 数据库类型集合
+ */
+public enum DBType {
+    JTDS("odps", ""),
+    HSQL("hsql", ""),
+    DB2("db2", ""),
+    POSTGRESQL("postgresql", "PostgreSQL"),
+    SYBASE("sybase", ""),
+    SQL_SERVER("sqlserver", ""),
+    ORACLE("oracle", ""),
+    ALI_ORACLE("AliOracle", ""),
+    MYSQL("mysql", ""),
+    MARIADB("mariadb", ""),
+    DERBY("derby", ""),
+    HBASE("hbase", ""),
+    HIVE("hive", ""),
+    H2("h2", ""),
+    DM("dm", "达梦数据库"),
+    KINGBASE("kingbase", ""),
+    GBASE("gbase", ""),
+    XUGU("xugu", ""),
+    OCEANBASE("oceanbase", ""),
+    INFORMIX("informix", ""),
+    ODPS("odps", "阿里云odps"),
+    TERADATA("teradata", ""),
+    LOG4JDBC("log4jdbc", "Log4JDBC"),
+    PHOENIX("phoenix", ""),
+    ENTERPRISEDB("edb", ""),
+    KYLIN("kylin", ""),
+    SQLITE("sqlite", ""),
+    ALIYUN_ADS("aliyun_ads", ""),
+    ALIYUN_DRDS("aliyun_drds", ""),
+    PRESTO("presto", ""),
+    ELASTIC_SEARCH("elastic_search", ""),
+    CLICKHOUSE("clickhouse", "");
+
+    private String name;
+    private String comment;
+
+    DBType(String name) {
+        this.name = name;
+    }
+
+    DBType(String name, String comment) {
+        this.name = name;
+        this.comment = comment;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public static DBType getDBTypeByName(String name){
+        DBType[] dbTypes = DBType.values();
+        for(DBType dbType : dbTypes){
+            if(name.equalsIgnoreCase(dbType.name)){
+                return dbType;
+            }
+        }
+        throw new IllegalArgumentException(name + "for DBType.name not exists");
+    }
+
+}

+ 87 - 0
src/main/java/com/goer/common/utils/fisok/sqloy/kit/DBTypeKit.java

@@ -0,0 +1,87 @@
+package com.goer.common.utils.fisok.sqloy.kit;
+
+import com.alibaba.druid.util.JdbcUtils;
+import com.aliyun.odps.jdbc.OdpsDatabaseMetaData;
+import com.goer.common.utils.fisok.raw.kit.JdbcKit;
+import com.goer.common.utils.fisok.raw.kit.StringKit;
+import com.goer.common.utils.fisok.sqloy.core.DBType;
+import com.kingbase8.jdbc.KbDatabaseMetaData;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+/**
+ * @author : goer
+ * @date : 2022/1/25
+ * @desc :
+ */
+public abstract class DBTypeKit {
+
+    /**
+     * 根据连接信息推断数据库类型
+     * @param connection
+     * @return
+     */
+    public static DBType getDBType(Connection connection) throws SQLException {
+        String dbType = getDBTypeStr(connection);
+        return DBType.getDBTypeByName(dbType.toUpperCase());
+    }
+
+    public static DBType getDBType(DatabaseMetaData metaData) throws SQLException {
+        String dbType = getDBTypeStr(metaData);
+        return DBType.getDBTypeByName(dbType.toUpperCase());
+    }
+
+    /**
+     * 根据数据源推断数据库类型(类型描述字串)
+     * @param dataSource
+     * @return
+     */
+    public static String getDBTypeStr(DataSource dataSource){
+        Connection connection = null;
+        try {
+            connection = dataSource.getConnection();
+            return getDBTypeStr(connection);
+        } catch (SQLException e) {
+            JdbcKit.close(connection);
+            throw new RuntimeException("从datasource中获取数据库类型DBType出错",e);
+        } finally {
+            JdbcKit.close(connection);
+        }
+    }
+
+    /**
+     * 根据连接信息推断数据库类型(类型描述字串)
+     * @param connection
+     * @return
+     */
+    public static String getDBTypeStr(Connection connection) throws SQLException {
+        DatabaseMetaData dbMeta = connection.getMetaData();
+        return getDBTypeStr(dbMeta);
+    }
+
+    /**
+     * 根据连接信息推断数据库类型(类型描述字串)
+     * @param metaData
+     * @return
+     */
+    public static String getDBTypeStr(DatabaseMetaData metaData){
+        try {
+            String driver = metaData.getDriverName();
+            String url = metaData.getURL();
+            String dbType = JdbcUtils.getDbType(url,driver);
+
+            //增加人大金仓支持
+            if(StringKit.isBlank(dbType) && metaData instanceof KbDatabaseMetaData){
+                dbType = "kingbase";
+            }else if(StringKit.isBlank(dbType) && metaData instanceof OdpsDatabaseMetaData){
+                dbType = "odps";
+            }
+            return dbType;
+        } catch (SQLException e) {
+            throw new RuntimeException("从connection中获取数据库类型MetaData出错",e);
+        }
+    }
+}

+ 35 - 0
src/main/java/com/goer/project/model/modelDbs/controller/ModelDbsController.java

@@ -1,7 +1,13 @@
 package com.goer.project.model.modelDbs.controller;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
+import com.goer.common.command.AbstractDBCommand;
+import com.goer.common.command.ExecResult;
+import com.goer.common.command.impl.DBReverseGetAllTablesListImpl;
+import com.goer.common.command.impl.PingLoadDriverClassImpl;
 import com.goer.project.model.modelProject.domain.ModelProject;
 import com.goer.project.model.modelProject.service.IModelProjectService;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
@@ -147,4 +153,33 @@ public class ModelDbsController extends BaseController
         modelDbs.setUpdateBy(getLoginName());
         return toAjax(modelDbsService.setDefaultDb(modelDbs));
     }
+
+    /**
+     * 测试
+     */
+    @Log(title = "模型对象数据库测试", businessType = BusinessType.UPDATE)
+    @RequiresPermissions("model:modelDbs:edit")
+    @PostMapping("/pingLoadDriver")
+    @ResponseBody
+    public AjaxResult pingLoadDriver(ModelDbs modelDbs)
+    {
+        if(modelDbs.getId() != null && modelDbs.getId() != 0L) {
+            modelDbs = modelDbsService.selectModelDbsById(modelDbs.getId());
+        }
+        ExecResult ret = new ExecResult(ExecResult.FAILED,"未知错误");
+        PingLoadDriverClassImpl ping = new PingLoadDriverClassImpl();
+        Map<String, String> argsMap = new HashMap<String, String>();
+        argsMap.put(AbstractDBCommand.KEY_DRIVER_CLASS_NAME,modelDbs.getDriverClassName());
+        argsMap.put(AbstractDBCommand.KEY_URL,modelDbs.getUrl());
+        argsMap.put(AbstractDBCommand.KEY_USERNAME,modelDbs.getUserName());
+        argsMap.put(AbstractDBCommand.KEY_PASSWORD,modelDbs.getPassword());
+        ret = ping.exec(argsMap);
+
+        modelDbs.setUpdateBy(getLoginName());
+        if(ExecResult.SUCCESS.equals(ret.getStatus())) {
+            return AjaxResult.success(ret.getBody().toString());
+        } else {
+            return AjaxResult.error(ret.getBody().toString());
+        }
+    }
 }

+ 8 - 0
src/main/java/com/goer/project/model/modelDbs/mapper/ModelDbsMapper.java

@@ -22,6 +22,14 @@ public interface ModelDbsMapper
     public ModelDbs selectModelDbsById(Long id);
 
     /**
+     * 查询模型对象默认数据库配置
+     *
+     * @param projectId 模型对象主键
+     * @return 模型对象数据库配置
+     */
+    public ModelDbs selectDefaultDbByProjectId(Long projectId);
+
+    /**
      * 查询模型对象数据库配置列表
      * 
      * @param modelDbs 模型对象数据库配置

+ 8 - 0
src/main/java/com/goer/project/model/modelDbs/service/IModelDbsService.java

@@ -20,6 +20,14 @@ public interface IModelDbsService
     public ModelDbs selectModelDbsById(Long id);
 
     /**
+     * 查询模型对象默认数据库配置
+     *
+     * @param projectId 模型对象主键
+     * @return 模型对象数据库配置
+     */
+    public ModelDbs selectDefaultDbByProjectId(Long projectId);
+
+    /**
      * 查询模型对象数据库配置列表
      * 
      * @param modelDbs 模型对象数据库配置

+ 11 - 0
src/main/java/com/goer/project/model/modelDbs/service/impl/ModelDbsServiceImpl.java

@@ -34,6 +34,17 @@ public class ModelDbsServiceImpl implements IModelDbsService
     }
 
     /**
+     * 查询模型对象默认数据库配置
+     *
+     * @param projectId 模型对象主键
+     * @return 模型对象数据库配置
+     */
+    @Override
+    public ModelDbs selectDefaultDbByProjectId(Long projectId) {
+        return modelDbsMapper.selectDefaultDbByProjectId(projectId);
+    }
+
+    /**
      * 查询模型对象数据库配置列表
      * 
      * @param modelDbs 模型对象数据库配置

+ 100 - 4
src/main/java/com/goer/project/model/modelEntity/controller/ModelEntityController.java

@@ -1,12 +1,16 @@
 package com.goer.project.model.modelEntity.controller;
 
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 
+import com.goer.common.chiner.model.TableEntity;
+import com.goer.common.command.AbstractDBCommand;
+import com.goer.common.command.ExecResult;
+import com.goer.common.command.impl.DBReverseGetAllTablesListImpl;
+import com.goer.common.command.impl.PingLoadDriverClassImpl;
+import com.goer.project.model.modelDbs.domain.ModelDbs;
+import com.goer.project.model.modelDbs.service.IModelDbsService;
 import com.goer.project.model.modelProject.domain.ModelProject;
 import com.goer.project.model.modelProject.service.IModelProjectService;
-import com.goer.project.model.modelVersionChanges.domain.ModelVersionChanges;
-import com.goer.project.model.modelVersionChanges.service.IModelVersionChangesService;
 import lombok.SneakyThrows;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -40,6 +44,9 @@ public class ModelEntityController extends BaseController
     @Autowired
     private IModelEntityService modelEntityService;
 
+    @Autowired
+    private IModelDbsService modelDbsService;
+
     @RequiresPermissions("model:modelEntity:view")
     @GetMapping()
     public String modelEntity(@RequestParam(name = "projectId", required = false, defaultValue = "0") Long projectId,
@@ -174,4 +181,93 @@ public class ModelEntityController extends BaseController
         modelEntity.setUpdateTime(new Date());
         return toAjax(modelEntityService.sort(modelEntity));
     }
+
+    @PostMapping("/importTableCheck")
+    @ResponseBody
+    public AjaxResult importTableCheck(ModelEntity modelEntity) {
+        ModelDbs modelDbs = modelDbsService.selectDefaultDbByProjectId(modelEntity.getProjectId());
+        if(modelDbs == null) {
+            return AjaxResult.error("未配置默认数据库");
+        }
+        ExecResult ret = new ExecResult(ExecResult.FAILED,"未知错误");
+        PingLoadDriverClassImpl ping = new PingLoadDriverClassImpl();
+        Map<String, String> argsMap = new HashMap<String, String>();
+        argsMap.put(AbstractDBCommand.KEY_DRIVER_CLASS_NAME,modelDbs.getDriverClassName());
+        argsMap.put(AbstractDBCommand.KEY_URL,modelDbs.getUrl());
+        argsMap.put(AbstractDBCommand.KEY_USERNAME,modelDbs.getUserName());
+        argsMap.put(AbstractDBCommand.KEY_PASSWORD,modelDbs.getPassword());
+        ret = ping.exec(argsMap);
+
+        if(!ExecResult.SUCCESS.equals(ret.getStatus())) {
+            return AjaxResult.error("配置的默认数据库连接失败。");
+        }
+        return AjaxResult.success();
+    }
+
+    /**
+     * 从数据库导入
+     */
+    @RequiresPermissions("model:modelEntity:import")
+    @GetMapping("/importTable/{projectId}")
+    public String importTable(@PathVariable("projectId") Long projectId, ModelMap mmap)
+    {
+        ModelProject modelProject = modelProjectService.selectModelProjectById(projectId);
+        mmap.put("modelProject", modelProject);
+//        ModelDbs modelDbs = modelDbsService.selectDefaultDbByProjectId(projectId);
+//        mmap.put("modelDbs", modelDbs);
+        return prefix + "/importTable";
+    }
+
+    /**
+     * 查询数据库列表
+     */
+    @RequiresPermissions("model:modelEntity:list")
+    @PostMapping("/db/list")
+    @ResponseBody
+    public TableDataInfo dataList(ModelEntity modelEntity){
+        ModelDbs modelDbs = modelDbsService.selectDefaultDbByProjectId(modelEntity.getProjectId());
+        DBReverseGetAllTablesListImpl reverse = new DBReverseGetAllTablesListImpl();
+        Map<String, String> argsMap = new HashMap<String, String>();
+        argsMap.put(AbstractDBCommand.KEY_DRIVER_CLASS_NAME,modelDbs.getDriverClassName());
+        argsMap.put(AbstractDBCommand.KEY_URL,modelDbs.getUrl());
+        argsMap.put(AbstractDBCommand.KEY_USERNAME,modelDbs.getUserName());
+        argsMap.put(AbstractDBCommand.KEY_PASSWORD,modelDbs.getPassword());
+        ExecResult ret = reverse.exec(argsMap);
+        List<TableEntity> listTable = (List<TableEntity>)ret.getBody();
+
+        modelEntity.setVersionId(0L);
+        List<ModelEntity> listEntity = modelEntityService.selectModelEntityList(modelEntity);
+        List<ModelEntity> retList = new ArrayList<>();
+        for(TableEntity t : listTable) {
+            boolean existFlag = false;
+            for(ModelEntity m : listEntity) {
+                if(t.getDefKey().equalsIgnoreCase(m.getEntityCode())) {
+                    existFlag = true;
+                    break;
+                }
+            }
+            if(!existFlag) {
+                ModelEntity ne = new ModelEntity();
+                ne.setEntityCode(t.getDefKey());
+                ne.setEntityName(t.getDefName());
+                retList.add(ne);
+            }
+        }
+        return getDataTable(retList);
+    }
+
+    /**
+     * 从数据库导入
+     */
+    @RequiresPermissions("model:modelEntity:import")
+    @Log(title = "从数据库导入", businessType = BusinessType.IMPORT)
+    @PostMapping("/importTable")
+    @ResponseBody
+    public AjaxResult importTableSave(ModelEntity modelEntity)
+    {
+        modelEntity.setCreateBy(getLoginName());
+        modelEntity.setCreateTime(new Date());
+
+        return toAjax(modelEntityService.importTable(modelEntity));
+    }
 }

+ 4 - 0
src/main/java/com/goer/project/model/modelEntity/service/IModelEntityService.java

@@ -1,6 +1,8 @@
 package com.goer.project.model.modelEntity.service;
 
 import java.util.List;
+
+import com.goer.common.chiner.model.TableEntity;
 import com.goer.project.model.modelEntity.domain.ModelEntity;
 
 /**
@@ -66,4 +68,6 @@ public interface IModelEntityService
      * @return
      */
     public int sort(ModelEntity modelEntity);
+
+    public int importTable(ModelEntity modelEntity);
 }

+ 136 - 0
src/main/java/com/goer/project/model/modelEntity/service/impl/ModelEntityServiceImpl.java

@@ -1,8 +1,25 @@
 package com.goer.project.model.modelEntity.service.impl;
 
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
+import com.alibaba.fastjson.JSON;
+import com.goer.common.chiner.model.ColumnField;
+import com.goer.common.chiner.model.TableEntity;
+import com.goer.common.command.AbstractDBCommand;
+import com.goer.common.command.ExecResult;
+import com.goer.common.command.impl.DBReverseGetTableDDLImpl;
 import com.goer.common.utils.DateUtils;
+import com.goer.common.utils.fisok.raw.kit.JSONKit;
+import com.goer.project.model.dataType.domain.DataType;
+import com.goer.project.model.dataType.mapper.DataTypeMapper;
+import com.goer.project.model.modelDbs.domain.ModelDbs;
+import com.goer.project.model.modelDbs.mapper.ModelDbsMapper;
 import com.goer.project.model.modelField.domain.ModelField;
+import com.goer.project.model.modelField.mapper.ModelFieldMapper;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.goer.project.model.modelEntity.mapper.ModelEntityMapper;
@@ -16,11 +33,18 @@ import com.goer.common.utils.text.Convert;
  * @author goer
  * @date 2022-01-17
  */
+@Slf4j
 @Service
 public class ModelEntityServiceImpl implements IModelEntityService 
 {
     @Autowired
     private ModelEntityMapper modelEntityMapper;
+    @Autowired
+    private ModelFieldMapper modelFieldMapper;
+    @Autowired
+    private ModelDbsMapper modelDbsMapper;
+    @Autowired
+    private DataTypeMapper dataTypeMapper;
 
     /**
      * 查询数据
@@ -131,4 +155,116 @@ public class ModelEntityServiceImpl implements IModelEntityService
         }
         return result;
     }
+
+    /**
+     * 逆向解析数据库导入
+     *
+     * @param modelEntity
+     * @return
+     */
+    @Override
+    public int importTable(ModelEntity modelEntity) {
+        int ret = 0;
+        DataType dataType = new DataType();
+        dataType.setProjectId(modelEntity.getProjectId());
+        dataType.setVersionId(0L);
+
+
+        ModelDbs modelDbs = modelDbsMapper.selectDefaultDbByProjectId(modelEntity.getProjectId());
+
+        DBReverseGetTableDDLImpl db = new DBReverseGetTableDDLImpl();
+        Map<String, String> argsMap = new HashMap<String, String>();
+        argsMap.put(AbstractDBCommand.KEY_DRIVER_CLASS_NAME,modelDbs.getDriverClassName());
+        argsMap.put(AbstractDBCommand.KEY_URL,modelDbs.getUrl());
+        argsMap.put(AbstractDBCommand.KEY_USERNAME,modelDbs.getUserName());
+        argsMap.put(AbstractDBCommand.KEY_PASSWORD,modelDbs.getPassword());
+        argsMap.put("tables",modelEntity.getEntityCode());
+        ExecResult er = db.exec(argsMap);
+
+        log.debug(JSONKit.toJsonString(er,true));
+
+        List<TableEntity> listTable = (List<TableEntity>)er.getBody();
+        for(TableEntity te : listTable) {
+            ModelEntity ne = new ModelEntity();
+            ne.setEntityCode(te.getDefKey());
+            ne.setEntityName(te.getDefName());
+            ne.setRemark(te.getComment());
+            ne.setProjectId(modelEntity.getProjectId());
+            ne.setVersionId(0L);
+            ne.setCreateBy(modelEntity.getCreateBy());
+            ne.setCreateTime(modelEntity.getCreateTime());
+
+            int sort = modelEntityMapper.selectMaxEntitySort(ne);
+            ne.setEntitySort(sort);
+
+            ret = ret + modelEntityMapper.insertModelEntity(ne);
+
+            List<ColumnField> listField = te.getFields();
+            for(ColumnField cf : listField) {
+//                "rowNo" : 1,
+//                "defKey" : "id",
+//                "defName" : "编号",
+//                "comment" : "",
+//                "domain" : "",
+//                "type" : "BIGINT",
+//                "len" : 20,
+//                "scale" : null,
+//                "primaryKey" : true,
+//                "notNull" : true,
+//                "autoIncrement" : true,
+//                "defaultValue" : "",
+//                "hideInGraph" : false,
+//                "typeFullName" : "BIGINT(20)",
+//                "primaryKeyName" : "√",
+//                "notNullName" : "√",
+//                "autoIncrementName" : "√",
+//                "refDict" : ""
+                ModelField mf = new ModelField();
+                mf.setVersionId(0L);
+                mf.setProjectId(modelEntity.getProjectId());
+                mf.setEntityId(ne.getId());
+                mf.setFieldName(cf.getDefName());
+                mf.setFieldCode(cf.getDefKey());
+                mf.setFieldType(cf.getTypeFullName());
+
+                //
+                dataType.setMysqlCode(cf.getTypeFullName());
+                List<DataType> dataTypes = dataTypeMapper.selectDataTypeList(dataType);
+                if(dataTypes == null || dataTypes.size() <= 0) {
+                    DataType ndt = new DataType();
+                    ndt.setProjectId(dataType.getProjectId());
+                    ndt.setVersionId(0L);
+                    ndt.setDataTypeName(cf.getTypeFullName());
+                    ndt.setDataTypeCode(cf.getTypeFullName());
+                    ndt.setMysqlCode(cf.getTypeFullName());
+
+                    int sortDt = dataTypeMapper.selectMaxDataSort(dataType);
+                    ndt.setDataSort(sortDt);
+                    ndt.setCreateTime(DateUtils.getNowDate());
+                    ndt.setCreateBy(modelEntity.getCreateBy());
+                    dataTypeMapper.insertDataType(ndt);
+                }
+
+                mf.setFieldPk("N");
+                if(cf.getPrimaryKey()) {
+                    mf.setFieldPk("Y");
+                }
+                mf.setNotNull("N");
+                if(cf.getNotNull()) {
+                    mf.setNotNull("Y");
+                }
+                mf.setAutoIncrement("N");
+                if(cf.getAutoIncrement()) {
+                    mf.setAutoIncrement("Y");
+                }
+                mf.setDefaultValue(cf.getDefaultValue());
+                mf.setFieldSort(cf.getRowNo());
+                mf.setCreateBy(modelEntity.getCreateBy());
+                mf.setCreateTime(modelEntity.getCreateTime());
+                ret = ret + modelFieldMapper.insertModelField(mf);
+            }
+        }
+
+        return ret;
+    }
 }

+ 6 - 1
src/main/resources/mybatis/model/ModelDbsMapper.xml

@@ -40,7 +40,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectModelDbsVo"/>
         where id = #{id}
     </select>
-        
+
+    <select id="selectDefaultDbByProjectId" parameterType="Long" resultMap="ModelDbsResult">
+        <include refid="selectModelDbsVo"/>
+        where project_id = #{projectId} and default_db='Y'
+    </select>
+
     <insert id="insertModelDbs" parameterType="ModelDbs" useGeneratedKeys="true" keyProperty="id">
         insert into t_model_dbs
         <trim prefix="(" suffix=")" suffixOverrides=",">

+ 46 - 5
src/main/resources/templates/model/modelDbs/add.html

@@ -10,34 +10,43 @@
             <div class="form-group">
                 <label class="col-sm-3 control-label is-required">数据库名称:</label>
                 <div class="col-sm-8">
-                    <input name="dbName" class="form-control" type="text" required>
+                    <input id="dbName" name="dbName" class="form-control" type="text" required>
                 </div>
             </div>
             <div class="form-group">
                 <label class="col-sm-3 control-label is-required">driverClass:</label>
                 <div class="col-sm-8">
-                    <input name="driverClassName" class="form-control" type="text" required>
+                    <input id="driverClassName" name="driverClassName" class="form-control" type="text" required>
                 </div>
             </div>
             <div class="form-group">
                 <label class="col-sm-3 control-label is-required">URL:</label>
                 <div class="col-sm-8">
-                    <textarea name="url" class="form-control" required></textarea>
+                    <textarea id="url" name="url" class="form-control" required></textarea>
                 </div>
             </div>
             <div class="form-group">    
                 <label class="col-sm-3 control-label is-required">用户名:</label>
                 <div class="col-sm-8">
-                    <input name="userName" class="form-control" type="text" required>
+                    <input id="userName" name="userName" class="form-control" type="text" required>
                 </div>
             </div>
             <div class="form-group">    
                 <label class="col-sm-3 control-label is-required">密码:</label>
                 <div class="col-sm-8">
-                    <input name="password" class="form-control" type="text" required>
+                    <input id="password" name="password" class="form-control" type="text" required>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label"></label>
+                <div class="col-sm-8">
+                    <a class="btn btn-warning" onclick="pingLoadDriver()">
+                        <i class="fa fa-link"></i> 连接测试
+                    </a>
                 </div>
             </div>
         </form>
+
     </div>
     <th:block th:include="include :: footer" />
     <script th:inline="javascript">
@@ -51,6 +60,38 @@
                 $.operate.save(prefix + "/add", $('#form-modelDbs-add').serialize());
             }
         }
+
+        function pingLoadDriver() {
+            if ($.validate.form()) {
+                // $.operate.post(prefix + "/pingLoadDriver", $('#form-modelDbs-add').serialize());
+
+                var config = {
+                    url: prefix + "/pingLoadDriver",
+                    type: "post",
+                    dataType: "json",
+                    data: {
+                        "driverClassName": $("#driverClassName").val(),
+                        "url": $("#url").val(),
+                        "userName": $("#userName").val(),
+                        "password": $("#password").val()
+                    },
+                    beforeSend: function () {
+                        $.modal.loading("正在处理中,请稍候...");
+                    },
+                    success: function(result) {
+                        if (result.code == web_status.SUCCESS) {
+                            $.modal.alertSuccess(result.msg)
+                        }  else if (result.code == web_status.WARNING) {
+                            $.modal.alertWarning(result.msg)
+                        }  else {
+                            $.modal.alertError(result.msg);
+                        }
+                        $.modal.closeLoading();
+                    }
+                };
+                $.ajax(config);
+            }
+        }
     </script>
 </body>
 </html>

+ 46 - 5
src/main/resources/templates/model/modelDbs/edit.html

@@ -10,31 +10,39 @@
             <div class="form-group">    
                 <label class="col-sm-3 control-label is-required">数据库名称:</label>
                 <div class="col-sm-8">
-                    <input name="dbName" th:field="*{dbName}" class="form-control" type="text" required>
+                    <input id="dbName" name="dbName" th:field="*{dbName}" class="form-control" type="text" required>
                 </div>
             </div>
             <div class="form-group">    
                 <label class="col-sm-3 control-label is-required">driverClass:</label>
                 <div class="col-sm-8">
-                    <input name="driverClassName" th:field="*{driverClassName}" class="form-control" type="text" required>
+                    <input id="driverClassName" name="driverClassName" th:field="*{driverClassName}" class="form-control" type="text" required>
                 </div>
             </div>
             <div class="form-group">
                 <label class="col-sm-3 control-label is-required">URL:</label>
                 <div class="col-sm-8">
-                    <textarea name="url" class="form-control" required>[[*{url}]]</textarea>
+                    <textarea id="url" name="url" class="form-control" required>[[*{url}]]</textarea>
                 </div>
             </div>
             <div class="form-group">    
                 <label class="col-sm-3 control-label is-required">用户名:</label>
                 <div class="col-sm-8">
-                    <input name="userName" th:field="*{userName}" class="form-control" type="text" required>
+                    <input id="userName" name="userName" th:field="*{userName}" class="form-control" type="text" required>
                 </div>
             </div>
             <div class="form-group">    
                 <label class="col-sm-3 control-label is-required">密码:</label>
                 <div class="col-sm-8">
-                    <input name="password" th:field="*{password}" class="form-control" type="text" required>
+                    <input id="password" name="password" th:field="*{password}" class="form-control" type="text" required>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="col-sm-3 control-label"></label>
+                <div class="col-sm-8">
+                    <a class="btn btn-warning" onclick="pingLoadDriver()">
+                        <i class="fa fa-link"></i> 连接测试
+                    </a>
                 </div>
             </div>
         </form>
@@ -51,6 +59,39 @@
                 $.operate.save(prefix + "/edit", $('#form-modelDbs-edit').serialize());
             }
         }
+
+
+        function pingLoadDriver() {
+            if ($.validate.form()) {
+                // $.operate.post(prefix + "/pingLoadDriver", $('#form-modelDbs-add').serialize());
+
+                var config = {
+                    url: prefix + "/pingLoadDriver",
+                    type: "post",
+                    dataType: "json",
+                    data: {
+                        "driverClassName": $("#driverClassName").val(),
+                        "url": $("#url").val(),
+                        "userName": $("#userName").val(),
+                        "password": $("#password").val()
+                    },
+                    beforeSend: function () {
+                        $.modal.loading("正在处理中,请稍候...");
+                    },
+                    success: function(result) {
+                        if (result.code == web_status.SUCCESS) {
+                            $.modal.alertSuccess(result.msg)
+                        }  else if (result.code == web_status.WARNING) {
+                            $.modal.alertWarning(result.msg)
+                        }  else {
+                            $.modal.alertError(result.msg);
+                        }
+                        $.modal.closeLoading();
+                    }
+                };
+                $.ajax(config);
+            }
+        }
     </script>
 </body>
 </html>

+ 28 - 2
src/main/resources/templates/model/modelDbs/modelDbs.html

@@ -138,8 +138,9 @@
                     align: 'left',
                     formatter: function(value, row, index) {
                         var actions = [];
-                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
-                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
+                        actions.push('<a class="btn btn-warning btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="pingLoadDriver(\'' + row.id + '\')"><i class="fa fa-link"></i> 连接测试 </a> ');
+                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i> 编辑 </a> ');
+                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i> 删除 </a>');
                         return actions.join('');
                     }
                 }]
@@ -174,6 +175,31 @@
                 $.operate.post(prefix + "/setDefaultDb", { "id": id, "projectId":projectId, "defaultDb":"Y"});
             });
         }
+
+        function pingLoadDriver(id) {
+            var config = {
+                url: prefix + "/pingLoadDriver",
+                type: "post",
+                dataType: "json",
+                data: {
+                    "id": id
+                },
+                beforeSend: function () {
+                    $.modal.loading("正在处理中,请稍候...");
+                },
+                success: function(result) {
+                    if (result.code == web_status.SUCCESS) {
+                        $.modal.alertSuccess(result.msg)
+                    }  else if (result.code == web_status.WARNING) {
+                        $.modal.alertWarning(result.msg)
+                    }  else {
+                        $.modal.alertError(result.msg);
+                    }
+                    $.modal.closeLoading();
+                }
+            };
+            $.ajax(config);
+        }
     </script>
 </body>
 </html>

+ 93 - 0
src/main/resources/templates/model/modelEntity/importTable.html

@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('导入表结构')" />
+</head>
+<body class="gray-bg">
+    <div class="container-div">
+		<div class="row">
+			<form id="gen-form">
+				<input type="hidden" id="projectId" name="projectId" th:value="${modelProject.id}">
+<!--				<div class="col-sm-12 search-collapse">-->
+<!--					<div class="select-list">-->
+<!--						<ul>-->
+<!--							<li>-->
+<!--								表名称:<input type="text" name="entityName"/>-->
+<!--							</li>-->
+<!--							<li>-->
+<!--								表逻辑名:<input type="text" name="entityCode"/>-->
+<!--							</li>-->
+<!--							<li>-->
+<!--								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>-->
+<!--								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>-->
+<!--							</li>-->
+<!--						</ul>-->
+<!--					</div>-->
+<!--				</div>-->
+			</form>
+		    <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "model/modelEntity";
+	
+		$(function() {
+		    var options = {
+		        url: prefix + "/db/list",
+				pagination: false,
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        clickToSelect: true,
+		        rememberSelected: true,
+		        uniqueId: "entityCode",
+		        columns: [{
+		        	field: 'state',
+		            checkbox: true
+		        },
+		        {
+                    title: "序号",
+                    formatter: function (value, row, index) {
+                 	    return $.table.serialNumber(index);
+                    }
+                },
+		        {
+		            field: 'entityName',
+		            title: '表名称',
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+		        {
+		            field: 'entityCode',
+		            title: '表逻辑名',
+		            formatter: function(value, row, index) {
+                    	return $.table.tooltip(value);
+                    }
+		        },
+				]
+		    };
+		    $.table.init(options);
+		});
+		
+		/* 导入表结构-选择表结构-提交 */
+		function submitHandler() {
+			var rows = $.table.selectColumns("entityCode");
+			if (rows.length == 0) {
+       			$.modal.alertWarning("请至少选择一条记录");
+       			return;
+       		}
+			var projectId = $("#projectId").val();
+			var data = {
+				"projectId": projectId,
+				"entityCode": rows.join()
+			};
+			$.operate.save(prefix + "/importTable", data);
+		}
+	</script>
+</body>
+</html>

+ 37 - 0
src/main/resources/templates/model/modelEntity/modelEntity.html

@@ -55,6 +55,9 @@
 <!--                <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="model:modelEntity:export">-->
 <!--                    <i class="fa fa-download"></i> 导出-->
 <!--                </a>-->
+                <a class="btn btn-warning" onclick="importTable()" shiro:hasPermission="model:modelEntity:import">
+                    <i class="fa fa-upload"></i> 从数据库导入
+                </a>
                 <a class="btn btn-danger" onclick="closeItem()">
                     <i class="fa fa-reply-all"></i> 关闭
                 </a>
@@ -157,6 +160,40 @@
             $.modal.openTab("字段一览", url);
         }
 
+        function dbReverse() {
+            var url = ctx + "model/modelField?projectId=" + projectId + "&entityId=" + entityId + "&versionId=0";
+            $.modal.openTab("从数据库导入", url);
+        }
+
+        // 从数据库导入
+        function importTable() {
+            var projectId = $("#projectId").val();
+            var checkFlag = false;
+            var config = {
+                url: prefix + "/importTableCheck",
+                type: "post",
+                dataType: "json",
+                data: {
+                    "projectId": projectId
+                },
+                success: function(result) {
+                    if (result.code == web_status.SUCCESS) {
+                        openImportTable();
+                    }  else if (result.code == web_status.WARNING) {
+                        $.modal.alertWarning(result.msg);
+                    }  else {
+                        $.modal.alertError(result.msg);
+                    }
+                }
+            };
+            $.ajax(config);
+        }
+
+        function openImportTable() {
+            var projectId = $("#projectId").val();
+            var importTableUrl = prefix + "/importTable/"+projectId;
+            $.modal.open("从数据库导入", importTableUrl);
+        }
 
         function saveSorted(data) {
             var table = $("#bootstrap-table").bootstrapTable('getOptions');