diff --git a/README.md b/README.md
index 7f00882c..aa284085 100644
--- a/README.md
+++ b/README.md
@@ -161,10 +161,12 @@ Slightly Framework design to  support Spring based java or Bigdata program.
         
         4.Query Configuration XML        
             4.1 Config Spring Bean
-                using Config file                
-                    <bean id="queryFactory" class="com.robin.core.query.util.QueryFactory" autowire="byName">
-                        	<property name="xmlConfigPath" value="classpath:query"></property>
-                    </bean>
+                using Config file   
+```xml
+                <bean id="queryFactory" class="com.robin.core.query.util.QueryFactory" autowire="byName">
+                    <property name="xmlConfigPath" value="classpath:query"></property>
+                </bean>                    
+```
                 xmlConfigPath support three input
                     I.if not assign value,read config xml from classpath:queryConfig
                     II. classpath:query  
@@ -178,14 +180,16 @@ Slightly Framework design to  support Spring based java or Bigdata program.
                          return factory;
                     }
             4.1 config XML File
-                in  xmlConfigPath Path ,add xml file
-                content
-                    <SQLSCRIPT ID="$_GETCODESET">
-                        <FROMSQL>from t_sys_code a,t_sys_codeset b where a.CS_ID=b.ID and ${queryString}</FROMSQL>
-                    	<FIELD>a.ITEM_NAME as ITEMNAME,a.ITEM_VALUE as ITEMVALUE</FIELD>
-                    </SQLSCRIPT>
+                in  xmlConfigPath Path ,add xml file content
+```XML
+            <SQLSCRIPT ID="$_GETCODESET">
+                <FROMSQL>from t_sys_code a,t_sys_codeset b where a.CS_ID=b.ID and ${queryString}</FROMSQL>
+                <FIELD>a.ITEM_NAME as ITEMNAME,a.ITEM_VALUE as ITEMVALUE</FIELD>
+            </SQLSCRIPT>                    
+```
                 SQLSCRIPT ID refrer to   queryBySelectId selectId.example see core test.    
 		5.mybatis like QueryMapper
+```xml
 			<mapper namespace="com.robin.test.query1">
 			<resultMap id="rsMap1" type="com.robin.core.test.model.TestModel">
 				<result column="id" property="id" jdbcType="BIGINT" />
@@ -274,6 +278,7 @@ Slightly Framework design to  support Spring based java or Bigdata program.
 
 			</delete>
 		</mapper>
+```
 		no need to generate Mapper class,Only need QueryMapper xml file
 		exmaple: core/src/test/java/com/robin/core/test/db/JdbcDaoTest  testQueryAndInsertMapper
 		
diff --git a/common/pom.xml b/common/pom.xml
index d5c83a8a..bbdc5298 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -323,7 +323,14 @@
             <groupId>com.github.chrisvest</groupId>
             <artifactId>stormpot</artifactId>
             <version>2.4.1</version>
+            <optional>true</optional>
         </dependency>
+        <!--<dependency>
+            <groupId>com.fasterxml</groupId>
+            <artifactId>aalto-xml</artifactId>
+            <version>1.3.3</version>
+            <optional>true</optional>
+        </dependency>-->
     </dependencies>
     <build>
         <sourceDirectory>src/main/java</sourceDirectory>
@@ -413,6 +420,63 @@
                     </dependency>
                 </dependencies>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy</id>
+                        <phase>install</phase>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>
+                                ${project.build.directory}/lib
+                            </outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <version>2.8.2</version>
+                <configuration>
+                    <!-- altDeploymentRepository ：指定替代方案应该部署项目工件的存储库（除了指定的工件）。 -->
+                    <altDeploymentRepository>internal.repo::default::file://${project.build.directory}/mvn-repo
+                    </altDeploymentRepository>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>com.github.github</groupId>
+                <artifactId>site-maven-plugin</artifactId>
+                <version >0.12</version>
+                <configuration>
+                    <message >Maven artifacts for ${project.version}</message>
+                    <noJekyll>true</noJekyll>
+                    <!--本地jar相关文件地址，与上方配置储存库位置(altDeploymentRepository)保持一致-->
+                    <outputDirectory>${project.build.directory}/mvn-repo</outputDirectory>
+                    <!--配置上传到github哪个分支，此处配置格式必须以refs/heads/+分支名称-->
+                    <branch>refs/heads/main</branch>
+                    <merge>true</merge>
+                    <includes>
+                        <include>**/*</include>
+                    </includes>
+                    <!--对应github上创建的仓库名称 name-->
+                    <repositoryName>mvn-repo</repositoryName>
+                    <!--github 仓库所有者即登录用户名-->
+                    <repositoryOwner>robinhood-jim</repositoryOwner>
+                    <server>github</server>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>site</goal>
+                        </goals>
+                        <phase>deploy</phase>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 </project>
diff --git a/common/src/main/java/com/robin/comm/util/config/YamlUtils.java b/common/src/main/java/com/robin/comm/util/config/YamlUtils.java
index 9ca4904d..228d0ac2 100644
--- a/common/src/main/java/com/robin/comm/util/config/YamlUtils.java
+++ b/common/src/main/java/com/robin/comm/util/config/YamlUtils.java
@@ -3,9 +3,7 @@
 import org.yaml.snakeyaml.Yaml;
 import org.yaml.snakeyaml.constructor.Constructor;
 
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
+import java.io.*;
 import java.util.Map;
 
 
@@ -16,7 +14,10 @@ public static Map<String,Object> parseYamlFileWithClasspath(String classPathFile
         Map<String,Object> map= yaml.load(clazz.getClassLoader().getResourceAsStream(classPathFile));
         return map;
     }
-    public static Map<String,Object> parseYamlFileWithStream(InputStream in){
+    public static Map<String,Object> parseYamlFromFile(String filePath) throws IOException {
+        return parseYamlFromStream(new FileInputStream(filePath));
+    }
+    public static Map<String,Object> parseYamlFromStream(InputStream in){
         Map<String,Object> map= yaml.load(in);
         return map;
     }
@@ -31,5 +32,8 @@ public static <T> T loadFromStream(InputStream inputStream,Class<T> clazz){
         Yaml tyaml=new Yaml(new Constructor(clazz.getClass()));
         return tyaml.load(inputStream);
     }
+    public static <T> T loadFromClassPath(String classPath,Class<T> clazz){
+        return loadFromStream(clazz.getClassLoader().getResourceAsStream(classPath),clazz);
+    }
 
 }
diff --git a/common/src/main/java/com/robin/comm/util/xls/ExcelBaseOper.java b/common/src/main/java/com/robin/comm/util/xls/ExcelBaseOper.java
index c0a36f4d..4e0b46a4 100644
--- a/common/src/main/java/com/robin/comm/util/xls/ExcelBaseOper.java
+++ b/common/src/main/java/com/robin/comm/util/xls/ExcelBaseOper.java
@@ -36,7 +36,6 @@
 import org.springframework.util.CollectionUtils;
 
 import java.awt.Color;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
@@ -57,7 +56,7 @@ private ExcelBaseOper() {
 
     public static final String TYPE_EXCEL2003 = "xls";
     public static final String TYPE_EXCEL2007 = "xlsx";
-    public static final String defaultFontName = Locale.CHINA.equals(Locale.getDefault()) || Locale.SIMPLIFIED_CHINESE.equals(Locale.getDefault()) ? "宋体" : java.awt.Font.SANS_SERIF;
+    public static final String defaultFontName = Locale.CHINA.equals(Locale.getDefault()) || Locale.SIMPLIFIED_CHINESE.equals(Locale.getDefault()) ? "宋体" : "Calibri";
     private static final Logger logger = LoggerFactory.getLogger(ExcelBaseOper.class);
     private static final Pattern paramPattern=Pattern.compile("\\w+(\\{P([\\+|-]?[\\d+])?\\})");
 
@@ -76,7 +75,7 @@ public static Workbook createWorkBook(ExcelSheetProp prop) {
                     })
                     .orElseGet(HSSFWorkbook::new);
         } else {
-            wb = Optional.of(prop.isStreamInsert()).map(f -> {
+            wb = Optional.of(prop.isStreamMode()).map(f -> {
                 Workbook wb1 = Optional.ofNullable(prop.getTemplateFile()).map(p1 -> {
                     try {
                         SXSSFWorkbook wb3 = new SXSSFWorkbook(new XSSFWorkbook(getTemplateInputStream(prop)), prop.getStreamRows());
@@ -333,6 +332,14 @@ private static short getAlignment(int align) {
         return (short) align;
     }
 
+    private static Cell createCell(Row row, int column, CellStyle cellStyle, CreationHelper helper, String objvalue) {
+        Cell cell = row.createCell(column);
+
+        cell.setCellValue(objvalue);
+        cell.setCellStyle(cellStyle);
+        return cell;
+    }
+
     public static Cell createCell(Row row1,int j, String value, String colType, CellStyle cellStyle, CreationHelper helper) {
         Cell cell;
         if (colType.equals(Const.META_TYPE_STRING)) {
@@ -363,14 +370,6 @@ public static Cell createCell(Row row1,int j, String value, String colType, Cell
         return cell;
     }
 
-    private static Cell createCell(Row row, int column, CellStyle cellStyle, CreationHelper helper, String objvalue) {
-        Cell cell = row.createCell(column);
-
-        cell.setCellValue(objvalue);
-        cell.setCellStyle(cellStyle);
-        return cell;
-    }
-
     private static Cell createCell(Row row, int column, CellStyle cellStyle, CreationHelper helper, double value) {
         Cell cell = row.createCell(column);
 
@@ -383,8 +382,10 @@ private static Cell createCell(Row row, int column, CellStyle cellStyle, Creatio
 
     private static Cell createFormulaCell(Row row, int column, CellStyle cellStyle, String formula) {
         Cell cell = row.createCell(column);
+        FormulaEvaluator evaluator = cell.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
         cell.setCellFormula(formula);
         cell.setCellStyle(cellStyle);
+        cell.setCellValue(evaluator.evaluate(cell).getNumberValue());
         return cell;
     }
 
@@ -400,7 +401,7 @@ private static Cell createCell(Row row, int column, CellStyle cellStyle, Creatio
 
     private static Cell createCellDate(Row row, int column, CellStyle cellStyle, CreationHelper helper, String value) {
         Cell cell = row.createCell(column);
-        cellStyle.setDataFormat(helper.createDataFormat().getFormat("yyyy-MM-dd hh:mm:ss"));
+        //cellStyle.setDataFormat(helper.createDataFormat().getFormat("yyyy-MM-dd hh:mm:ss"));
 
         cell.setCellValue(new Date(Long.parseLong(value)));
         cell.setCellStyle(cellStyle);
diff --git a/common/src/main/java/com/robin/comm/util/xls/ExcelCellStyleUtil.java b/common/src/main/java/com/robin/comm/util/xls/ExcelCellStyleUtil.java
index c265f32c..3b6149b4 100644
--- a/common/src/main/java/com/robin/comm/util/xls/ExcelCellStyleUtil.java
+++ b/common/src/main/java/com/robin/comm/util/xls/ExcelCellStyleUtil.java
@@ -17,6 +17,7 @@
 
 import java.util.Map;
 
+import com.robin.core.base.util.DateTimeFormatHolder;
 import org.apache.poi.hssf.usermodel.HSSFDataFormat;
 import org.apache.poi.ss.usermodel.*;
 
@@ -30,6 +31,7 @@ private ExcelCellStyleUtil() {
 
     }
 
+
     public static CellStyle getNoBorderCellType(Workbook wb, String metaType) {
         CellStyle cs = wb.createCellStyle();
         cs.setAlignment(HorizontalAlignment.CENTER);
@@ -39,11 +41,11 @@ public static CellStyle getNoBorderCellType(Workbook wb, String metaType) {
         cs.setFillForegroundColor(IndexedColors.WHITE.getIndex());
         cs.setFillPattern(FillPatternType.SOLID_FOREGROUND);
         cs.setWrapText(true);
-        extractMeta(metaType, cs);
+        extractMeta(wb,metaType, cs);
         return cs;
     }
 
-    private static void extractMeta(String metaType, CellStyle cs) {
+    private static void extractMeta(Workbook wb,String metaType, CellStyle cs) {
         switch (metaType) {
             case Const.META_TYPE_NUMERIC:
             case Const.META_TYPE_DOUBLE:
@@ -51,7 +53,8 @@ private static void extractMeta(String metaType, CellStyle cs) {
                 cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));
                 break;
             case Const.META_TYPE_DATE:
-                cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("yyyy-MM-dd hh:mm:ss"));
+            case Const.META_TYPE_TIMESTAMP:
+                cs.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat(DateTimeFormatHolder.getTimestampFormatter().toString()));
                 break;
             case Const.META_TYPE_INTEGER:
                 cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("0"));
@@ -76,10 +79,36 @@ public static CellStyle getBorderCellType(Workbook wb, String metaType) {
         Font font = wb.createFont();
         font.setFontName(ExcelBaseOper.defaultFontName);
         cs.setFont(font);
-        extractMeta(metaType, cs);
+        extractMeta(wb,metaType, cs);
         return cs;
 
     }
+    public static CellStyle getCellStyle(Workbook wb,String metaType,Map<String, CellStyle> cellMap){
+        if(cellMap.containsKey(metaType)){
+            return cellMap.get(metaType);
+        }else{
+            CellStyle cs = wb.createCellStyle();
+            cs.setVerticalAlignment(VerticalAlignment.CENTER);
+            cs.setAlignment(HorizontalAlignment.CENTER);
+            cs.setBorderBottom(BorderStyle.THIN);
+            cs.setBottomBorderColor(IndexedColors.BLACK.getIndex());
+            cs.setBorderLeft(BorderStyle.THIN);
+            cs.setLeftBorderColor(IndexedColors.BLACK.getIndex());
+            cs.setBorderRight(BorderStyle.THIN);
+            cs.setRightBorderColor(IndexedColors.BLACK.getIndex());
+            cs.setBorderTop(BorderStyle.THIN);
+            cs.setTopBorderColor(IndexedColors.BLACK.getIndex());
+            cs.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+            Font font = wb.createFont();
+            font.setFontName(ExcelBaseOper.defaultFontName);
+            cs.setFont(font);
+            cs.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+            cs.setWrapText(true);
+            extractMeta(wb,metaType,cs);
+            cellMap.put(metaType,cs);
+            return cs;
+        }
+    }
 
     public static CellStyle getCellStyle(Workbook wb, int rowspan, int colspan, String metaType, TableConfigProp header, Map<String, CellStyle> cellMap) {
         CellStyle cs = null;
@@ -114,7 +143,7 @@ public static CellStyle getCellStyle(Workbook wb, int rowspan, int colspan, Stri
             cs.setFont(font);
             cs.setFillPattern(FillPatternType.SOLID_FOREGROUND);
             cs.setWrapText(true);
-            extractMeta(metaType,cs);
+            extractMeta(wb,metaType,cs);
             cellMap.put("C_" + rowspan + "_" + colspan + "_" + metaType, cs);
         }
         return cs;
diff --git a/common/src/main/java/com/robin/comm/util/xls/ExcelColumnProp.java b/common/src/main/java/com/robin/comm/util/xls/ExcelColumnProp.java
index cb21fead..62f3b66d 100644
--- a/common/src/main/java/com/robin/comm/util/xls/ExcelColumnProp.java
+++ b/common/src/main/java/com/robin/comm/util/xls/ExcelColumnProp.java
@@ -25,6 +25,7 @@ public class ExcelColumnProp {
     private String columnCode;
     private String columnType;
     private String formula;
+    private String format;
     private boolean needMerge;
 
 
diff --git a/common/src/main/java/com/robin/comm/util/xls/ExcelProcessor.java b/common/src/main/java/com/robin/comm/util/xls/ExcelProcessor.java
index a9003989..cfe63fee 100644
--- a/common/src/main/java/com/robin/comm/util/xls/ExcelProcessor.java
+++ b/common/src/main/java/com/robin/comm/util/xls/ExcelProcessor.java
@@ -476,7 +476,7 @@ public static Workbook generateExcelFile(ExcelSheetProp prop, TableConfigProp he
             while (iterator.hasNext()) {
                 Map<String, Object> map = iterator.next();
                 processSingleLine(map, wb, sheet, row, prop, header, helper, cellMap);
-                if (prop.isStreamInsert() && (row + 1) % prop.getStreamRows() == 0) {
+                if (prop.isStreamMode() && (row + 1) % prop.getStreamRows() == 0) {
                     ((SXSSFSheet) sheet).flushRows(prop.getStreamRows());
                 }
                 row++;
@@ -688,7 +688,7 @@ private static void fillColumns(Workbook wb, Sheet targetsheet, ExcelSheetProp p
                 Map<String, CellStyle> cellMap = new HashMap<>();
                 for (int i = 0; i < list.size(); i++) {
                     processSingleLine(list.get(i), wb, targetsheet, i, prop, header, helper, cellMap);
-                    if (prop.isStreamInsert() && (i + 1) % prop.getStreamRows() == 0) {
+                    if (prop.isStreamMode() && (i + 1) % prop.getStreamRows() == 0) {
                         ((SXSSFSheet) targetsheet).flushRows(prop.getStreamRows());
                     }
                 }
@@ -817,7 +817,7 @@ public static void processSingleLine(Map<String, ?> map, Workbook wb, Sheet targ
 
     private static void autoSizeSheet(ExcelSheetProp prop, Sheet sheet, int count) {
         for (int i = 0; i < count; i++) {
-            if (!prop.isStreamInsert()) {
+            if (!prop.isStreamMode()) {
                 sheet.autoSizeColumn(i);
             } else {
                 if (i == 0) {
diff --git a/common/src/main/java/com/robin/comm/util/xls/ExcelRsExtractor.java b/common/src/main/java/com/robin/comm/util/xls/ExcelRsExtractor.java
index 070cf30d..61a79b74 100644
--- a/common/src/main/java/com/robin/comm/util/xls/ExcelRsExtractor.java
+++ b/common/src/main/java/com/robin/comm/util/xls/ExcelRsExtractor.java
@@ -38,7 +38,7 @@ public boolean executeAdditionalOperation(Map<String, Object> map, ResultSetMeta
         pos++;
         processRows++;
         try {
-            if (prop.isStreamInsert() && (processRows) % prop.getStreamRows() == 0) {
+            if (prop.isStreamMode() && (processRows) % prop.getStreamRows() == 0) {
                 ((SXSSFSheet) targetSheet).flushRows(prop.getStreamRows());
             }
 
diff --git a/common/src/main/java/com/robin/comm/util/xls/ExcelSheetProp.java b/common/src/main/java/com/robin/comm/util/xls/ExcelSheetProp.java
index 71bdc3f2..64df8891 100644
--- a/common/src/main/java/com/robin/comm/util/xls/ExcelSheetProp.java
+++ b/common/src/main/java/com/robin/comm/util/xls/ExcelSheetProp.java
@@ -15,6 +15,8 @@
  */
 package com.robin.comm.util.xls;
 
+import com.robin.core.fileaccess.meta.DataCollectionMeta;
+import com.robin.core.fileaccess.meta.DataSetColumnMeta;
 import lombok.Data;
 
 import java.util.*;
@@ -32,12 +34,16 @@ public class ExcelSheetProp {
 	private int startCol=1;  
 	private Integer tableId;
 	// using SXSSFWorkbook with streamingWrite
-	private boolean streamInsert=false;
+	private boolean streamMode =false;
 	private Integer streamRows=100;
 	private int sheetNum=0;
 	private boolean fillHeader=true;
 	private String templateFile;
-	public ExcelSheetProp(){
+	private boolean useOffHeap=false;
+	private String fontName;
+	private int maxRows;
+	private int maxSheetSize;
+	private ExcelSheetProp(){
 
 	}
 	public ExcelSheetProp(String[] headerName,String[] columnName,String fileExt){
@@ -60,6 +66,95 @@ public List<ExcelColumnProp> getColumnPropList() {
 		return columnPropList;
 	}
 
+	public static ExcelSheetProp fromDataCollectionMeta(DataCollectionMeta colmeta){
+		ExcelSheetProp.Builder builder=ExcelSheetProp.Builder.newBuilder();
+		for(DataSetColumnMeta setColumnMeta:colmeta.getColumnList()){
+			builder.addColumnProp(setColumnMeta.getColumnName(), setColumnMeta.getColumnName(), setColumnMeta.getColumnType());
+		}
+		builder.setStartRow(2);
+		return builder.build();
+	}
+	public static class Builder{
+		private ExcelSheetProp prop=new ExcelSheetProp();
+		private Builder(){
+
+		}
+		public static Builder newBuilder(){
+			Builder builder=new Builder();
+			return builder;
+		}
+		public Builder setFileExt(String fileExt){
+			prop.setFileExt(fileExt);
+			return this;
+		}
+		public Builder addColumnProp(String columnName,String columnCode,String columnType){
+			prop.getColumnPropList().add(new ExcelColumnProp(columnName,columnCode,columnType));
+			return this;
+		}
+		public Builder addColumnProp(String columnName,String columnCode,String columnType,String formula){
+			prop.getColumnPropList().add(new ExcelColumnProp(columnName,columnCode,columnType,formula));
+			return this;
+		}
+		public Builder addColumnProp(ExcelColumnProp columnProp){
+			prop.getColumnPropList().add(columnProp);
+			return this;
+		}
+		public Builder addColumnProp(String columnName,String columnCode,String columnType,boolean needMerge){
+			prop.getColumnPropList().add(new ExcelColumnProp(columnName,columnCode,columnType,needMerge));
+			return this;
+		}
+		public Builder setStartRow(int row){
+			prop.setStartRow(row);
+			return this;
+		}
+		public Builder setStartCol(int col){
+			prop.setStartCol(col);
+			return this;
+		}
+		public Builder setSheetName(String sheetName){
+			prop.setSheetName(sheetName);
+			return this;
+		}
+		public Builder setStreamMode(){
+			prop.setStreamMode(true);
+			return this;
+		}
+		public Builder setStreamRows(int streamRows){
+			prop.setStreamRows(streamRows);
+			return this;
+		}
+		public Builder setBatchMode(){
+			prop.setStreamMode(false);
+			return this;
+		}
+		public Builder doNotFillHeader(){
+			prop.setFillHeader(false);
+			return this;
+		}
+		public Builder useTemplateFile(String templateFile){
+			prop.setTemplateFile(templateFile);
+			return this;
+		}
+		public Builder dumpUseOffHeap(){
+			prop.setUseOffHeap(true);
+			return this;
+		}
+		public Builder dumpUseTempFile(){
+			prop.setUseOffHeap(false);
+			return this;
+		}
+		public Builder maxRows(int maxRows){
+			prop.setMaxRows(maxRows);
+			return this;
+		}
+		public Builder maxSheetSize(int maxSheetSize){
+			prop.setMaxSheetSize(maxSheetSize);
+			return this;
+		}
+		public ExcelSheetProp build(){
+			return prop;
+		}
+	}
 
 
 }
diff --git a/common/src/main/java/com/robin/core/fileaccess/iterator/AbstractFileIterator.java b/common/src/main/java/com/robin/core/fileaccess/iterator/AbstractFileIterator.java
index 14f23b70..b921b4ff 100644
--- a/common/src/main/java/com/robin/core/fileaccess/iterator/AbstractFileIterator.java
+++ b/common/src/main/java/com/robin/core/fileaccess/iterator/AbstractFileIterator.java
@@ -114,51 +114,52 @@ public void beforeProcess() {
             }else{
                 this.instream=accessUtil.getInResourceByStream(ResourceUtil.getProcessPath(colmeta.getPath()));
             }
-            if(useOrderBy || useGroupBy){
-                //pool all record through OffHeap
-                //ByteBuffer buffer=ByteBuffer.allocate(512);
-                pullNext();
-                StringBuilder builder=new StringBuilder();
-                while (!CollectionUtils.isEmpty(cachedValue)){
-                    while (!CollectionUtils.isEmpty(cachedValue) && useFilter && !CommRecordGenerator.doesRecordAcceptable(segment, cachedValue)) {
-                        pullNext();
-                    }
-                    if (segment != null && (!segment.isIncludeAllOriginColumn() && !CollectionUtils.isEmpty(segment.getSelectColumns()))) {
-                        newRecord.clear();
-                        CommRecordGenerator.doAsyncCalculator(segment, cachedValue, newRecord);
+        } catch (Exception ex) {
+            logger.error("{}", ex.getMessage());
+        }
+    }
+    protected void groupOrderByInit() throws Exception{
+        if(useOrderBy || useGroupBy){
+            //pool all record through OffHeap
+            //ByteBuffer buffer=ByteBuffer.allocate(512);
+            pullNext();
+            StringBuilder builder=new StringBuilder();
+            while (!CollectionUtils.isEmpty(cachedValue)){
+                while (!CollectionUtils.isEmpty(cachedValue) && useFilter && !CommRecordGenerator.doesRecordAcceptable(segment, cachedValue)) {
+                    pullNext();
+                }
+                if (segment != null && (!segment.isIncludeAllOriginColumn() && !CollectionUtils.isEmpty(segment.getSelectColumns()))) {
+                    newRecord.clear();
+                    CommRecordGenerator.doAsyncCalculator(segment, cachedValue, newRecord);
+                }
+                //get group by column
+                if(!CollectionUtils.isEmpty(segment.getGroupBy())){
+                    if(builder.length()>0){
+                        builder.delete(0,builder.length());
                     }
-                    //get group by column
-                    if(!CollectionUtils.isEmpty(segment.getGroupBy())){
-                        if(builder.length()>0){
-                            builder.delete(0,builder.length());
+                    for(SqlNode tnode:segment.getGroupBy()) {
+                        String columnName=((SqlIdentifier)tnode).getSimple();
+                        if (!ObjectUtils.isEmpty(newRecord.get(columnName))) {
+                            appendByType(builder,newRecord.get(columnName));
                         }
-                        for(SqlNode tnode:segment.getGroupBy()) {
-                            String columnName=((SqlIdentifier)tnode).getSimple();
-                            if (!ObjectUtils.isEmpty(newRecord.get(columnName))) {
-                                appendByType(builder,newRecord.get(columnName));
-                            }
-                        }
-                        doGroupAgg(builder.toString());//ByteBufferUtils.getContent(buffer)
                     }
-                    pullNext();
+                    doGroupAgg(builder.toString());//ByteBufferUtils.getContent(buffer)
                 }
-                //calculate avg
-                for(CommSqlParser.ValueParts parts:segment.getSelectColumns()){
-                    if("avg".equalsIgnoreCase(parts.getFunctionName())){
-                        groupByMap.entrySet().forEach(entry->{
-                            if(!ObjectUtils.isEmpty(entry.getValue().get(parts.getAliasName())) &&
-                                    !ObjectUtils.isEmpty(entry.getValue().get(parts.getAliasName()+"cou"))){
-                                entry.getValue().put(parts.getAliasName(),(Double)entry.getValue().get(parts.getAliasName())/(Integer)entry.getValue().get(parts.getAliasName()+"cou"));
-                                entry.getValue().remove(parts.getAliasName()+"cou");
-                            }
-                        });
-                    }
+                pullNext();
+            }
+            //calculate avg
+            for(CommSqlParser.ValueParts parts:segment.getSelectColumns()){
+                if("avg".equalsIgnoreCase(parts.getFunctionName())){
+                    groupByMap.entrySet().forEach(entry->{
+                        if(!ObjectUtils.isEmpty(entry.getValue().get(parts.getAliasName())) &&
+                                !ObjectUtils.isEmpty(entry.getValue().get(parts.getAliasName()+"cou"))){
+                            entry.getValue().put(parts.getAliasName(),(Double)entry.getValue().get(parts.getAliasName())/(Integer)entry.getValue().get(parts.getAliasName()+"cou"));
+                            entry.getValue().remove(parts.getAliasName()+"cou");
+                        }
+                    });
                 }
-                groupIter=groupByMap.entrySet().iterator();
             }
-
-        } catch (Exception ex) {
-            logger.error("{}", ex.getMessage());
+            groupIter=groupByMap.entrySet().iterator();
         }
     }
     private void doGroupAgg(String key){
@@ -254,6 +255,7 @@ public boolean hasNext() {
         try {
             // no order by
             if(!useOrderBy && !useGroupBy) {
+
                 pullNext();
                 while (!CollectionUtils.isEmpty(cachedValue) && useFilter && !CommRecordGenerator.doesRecordAcceptable(segment, cachedValue)) {
                     pullNext();
@@ -265,6 +267,9 @@ public boolean hasNext() {
                 return !CollectionUtils.isEmpty(cachedValue);
             }else{
                 //capture all record to offHeap
+                if(CollectionUtils.isEmpty(groupByMap)) {
+                    groupOrderByInit();
+                }
                 newRecord.clear();
                 if(groupIter.hasNext()) {
 
@@ -312,7 +317,7 @@ private String getHavingColumnName(){
         return aliasName;
     }
 
-    protected abstract void pullNext();
+    protected abstract void pullNext() throws Exception;
     public DataCollectionMeta getCollectionMeta(){
         return colmeta;
     }
diff --git a/common/src/main/java/com/robin/core/fileaccess/iterator/XlsxFileIterator.java b/common/src/main/java/com/robin/core/fileaccess/iterator/XlsxFileIterator.java
new file mode 100644
index 00000000..f114dd5a
--- /dev/null
+++ b/common/src/main/java/com/robin/core/fileaccess/iterator/XlsxFileIterator.java
@@ -0,0 +1,255 @@
+package com.robin.core.fileaccess.iterator;
+
+import com.google.common.collect.Sets;
+import com.robin.core.base.util.Const;
+import com.robin.core.convert.util.ConvertUtil;
+import com.robin.core.fileaccess.fs.AbstractFileSystemAccessor;
+import com.robin.core.fileaccess.meta.DataCollectionMeta;
+import com.robin.core.fileaccess.meta.DataSetColumnMeta;
+import com.robin.core.fileaccess.util.PolandNotationUtil;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.xssf.eventusermodel.XSSFReader;
+import org.apache.poi.xssf.model.SharedStrings;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Timestamp;
+import java.util.*;
+/**
+ * read xlsx with StAX api
+ */
+public class XlsxFileIterator extends AbstractFileIterator{
+    private XMLInputFactory factory;
+    private XMLStreamReader streamReader;
+    private OPCPackage opcPackage;
+    private Iterator<InputStream> sheetStreams;
+    private InputStream readStreams;
+    private XSSFReader xssfReader;
+    private SharedStrings sharedStrings;
+    private static final char charA='A';
+    private static boolean hasHeader=true;
+    private Map<String,String> formulaStrMap=new HashMap<>();
+    private Map<String, Queue<String>> formulaMap=new HashMap<>();
+    private static final Set<Character> formulaSets= Sets.newHashSet('(',')','+','-','*','/');
+
+    public XlsxFileIterator(){
+        identifier= Const.FILEFORMATSTR.XLSX.getValue();
+    }
+
+    public XlsxFileIterator(DataCollectionMeta meta) {
+        super(meta);
+        identifier= Const.FILEFORMATSTR.XLSX.getValue();
+    }
+    public XlsxFileIterator(DataCollectionMeta meta, AbstractFileSystemAccessor accessor) {
+        super(meta,accessor);
+        identifier= Const.FILEFORMATSTR.XLSX.getValue();
+        if(meta.getResourceCfgMap().containsKey(Const.COLUMN_XLSX_HASHEADER) && Const.FALSE.equalsIgnoreCase(meta.getResourceCfgMap().get(Const.COLUMN_XLSX_HASHEADER).toString())){
+            hasHeader=false;
+        }
+    }
+
+    @Override
+    public void beforeProcess() {
+        super.beforeProcess();
+        try {
+            factory = XMLInputFactory.newFactory();
+            factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
+            factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
+            opcPackage=OPCPackage.open(instream);
+            xssfReader=new XSSFReader(opcPackage);
+            sheetStreams=xssfReader.getSheetsData();
+            sharedStrings=xssfReader.getSharedStringsTable();
+
+            if(sheetStreams.hasNext()){
+                readStreams=sheetStreams.next();
+                streamReader=factory.createXMLStreamReader(readStreams,colmeta.getEncode());
+                String nodeName;
+                while(streamReader.hasNext()){
+                    if(streamReader.getEventType()== XMLStreamConstants.START_ELEMENT) {
+                        nodeName = streamReader.getLocalName();
+                        if("row".equalsIgnoreCase(nodeName)){
+                            break;
+                        }
+                    }
+                    streamReader.next();
+                }
+            }
+            if(hasHeader){
+                readNext();
+            }
+        }catch (Exception ex){
+
+        }
+    }
+    private void readNext() throws Exception{
+        String nodeName;
+        int rowNum;
+        String rowNumStr;
+        int columnPos=0;
+        String value;
+        boolean sharedValue=false;
+        boolean breakTag=false;
+        Object targetValue=null;
+
+
+        while (streamReader.hasNext() && !breakTag){
+            if(streamReader.getEventType()== XMLStreamConstants.START_ELEMENT){
+                nodeName=streamReader.getLocalName();
+                switch (nodeName.toLowerCase()){
+                    case "row":
+                        rowNumStr = streamReader.getAttributeValue("", "r");
+                        rowNum = Integer.parseInt(rowNumStr);
+                        break;
+                    case "c":
+                        columnPos=getColumnPos(streamReader.getAttributeValue("","r"))-1;
+                        String cellType=streamReader.getAttributeValue("","t");
+                        if("s".equals(cellType)){
+                            sharedValue=true;
+                        }
+                        break;
+                    case "v":
+                        streamReader.next();
+                        value=streamReader.getText();
+                        if(sharedValue){
+                            targetValue=new XSSFRichTextString(sharedStrings.getItemAt(Integer.parseInt(value)).getString()).toString();
+                            sharedValue=false;
+                        }else{
+                            targetValue=parseValue(value, colmeta.getColumnList().get(columnPos));
+                        }
+                        break;
+                    case "t":
+                        streamReader.next();
+                        targetValue=streamReader.getText();
+                        break;
+                    case "f":
+                        streamReader.next();
+                        if(streamReader.getEventType()==XMLStreamConstants.CHARACTERS) {
+                            value = streamReader.getText();
+
+                        }
+                        break;
+                }
+
+            }else if(streamReader.getEventType()==XMLStreamConstants.END_ELEMENT){
+                nodeName=streamReader.getLocalName();
+                switch (nodeName.toLowerCase()) {
+                    case "row":
+                        breakTag=true;
+                        break;
+                    case "t":
+                    case "v":
+                        cachedValue.put(colmeta.getColumnList().get(columnPos).getColumnName(),targetValue);
+                        break;
+                    case "f":
+                        /*if(!formulaStrMap.containsKey(colmeta.getColumnList().get(columnPos).getColumnName()) || !formulaStrMap.get(colmeta.getColumnList().get(columnPos).getColumnName()).equals(value)){
+                            formulaStrMap.put(colmeta.getColumnList().get(columnPos).getColumnName(),value);
+                            Queue<String> queue= PolandNotationUtil.parsePre(getFormula(value));
+                            if(!CollectionUtils.isEmpty(queue)){
+                                formulaMap.put(colmeta.getColumnList().get(columnPos).getColumnName(),queue);
+                            }
+                        }*/
+                        break;
+
+                }
+            }
+            streamReader.next();
+        }
+    }
+    private Object parseValue(String value, DataSetColumnMeta columnMeta){
+        if(!columnMeta.getColumnType().equals(Const.META_TYPE_TIMESTAMP)){
+           return ConvertUtil.convertStringToTargetObject(value, columnMeta, formatter);
+        }else{
+            double dValue=Double.valueOf(value);
+            Date date = DateUtil.getJavaDate(dValue);
+            return new Timestamp(date.getTime());
+        }
+    }
+    private static int getColumnPos(String columnName){
+        StringBuilder builder=new StringBuilder();
+        for(int i=0;i<columnName.length();i++){
+            if(!Character.isAlphabetic(columnName.charAt(i))){
+                builder.append(columnName.substring(0,i));
+                break;
+            }
+        }
+        int columnPos=0;
+        if(builder.length()>0){
+            for(int i=0;i<builder.length();i++){
+                int val=(builder.charAt(i)-charA)+1;
+                if(i>0){
+                    columnPos=columnPos*26+val;
+                }else{
+                    columnPos=val;
+                }
+            }
+        }
+        return columnPos;
+    }
+    private String getFormula(String formula){
+        StringBuilder builder=new StringBuilder();
+        StringBuilder outBuilder=new StringBuilder();
+        for(int i=0;i<formula.length();i++){
+            if(formulaSets.contains(formula.charAt(i))){
+                if(builder.length()>0){
+                    String columnName=builder.toString();
+                    outBuilder.append(colmeta.getColumnList().get(getColumnPos(columnName)).getColumnName());
+                    builder.delete(0,builder.length());
+                }
+                outBuilder.append(formula.charAt(i));
+            }else{
+                builder.append(formula.charAt(i));
+            }
+        }
+        if(formulaSets.contains(builder.charAt(0))){
+            outBuilder.append(builder.charAt(0));
+        }else{
+            String columnName=builder.toString();
+            outBuilder.append(colmeta.getColumnList().get(getColumnPos(columnName)).getColumnName());
+        }
+        return outBuilder.toString();
+    }
+
+    @Override
+    protected void pullNext() throws Exception {
+        cachedValue.clear();
+        readNext();
+        if(CollectionUtils.isEmpty(cachedValue)){
+            if(sheetStreams.hasNext()){
+                readStreams.close();
+                streamReader.close();
+                readStreams=sheetStreams.next();
+                streamReader=factory.createXMLStreamReader(readStreams,colmeta.getEncode());
+                if(hasHeader) {
+                    readNext();
+                }
+            }
+            readNext();
+        }
+        //calculate formula column
+        if(!formulaMap.isEmpty()){
+            formulaMap.forEach((k,v)->{
+                if(ObjectUtils.isEmpty(cachedValue.get(k))){
+                    cachedValue.put(k,PolandNotationUtil.computeResult(v,cachedValue));
+                }
+            });
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        super.close();
+        if(readStreams!=null){
+            readStreams.close();
+        }
+        if(opcPackage!=null){
+            opcPackage.close();
+        }
+    }
+}
diff --git a/common/src/main/java/com/robin/core/fileaccess/util/ByteBufferInputStream.java b/common/src/main/java/com/robin/core/fileaccess/util/ByteBufferInputStream.java
index f8c64b27..766354a1 100644
--- a/common/src/main/java/com/robin/core/fileaccess/util/ByteBufferInputStream.java
+++ b/common/src/main/java/com/robin/core/fileaccess/util/ByteBufferInputStream.java
@@ -16,6 +16,22 @@ public ByteBufferInputStream(ByteBuffer byteBuffer,int count){
         byteBuffer.position(0);
         this.count=count;
     }
+    public ByteBufferInputStream(ByteBuffer buffer,byte[] bytes){
+        this.byteBuffer=buffer;
+        byteBuffer.position(0);
+        buffer.put(bytes);
+        this.count=bytes.length;
+    }
+    public ByteBufferInputStream(ByteBuffer buffer,InputStream inputStream) throws IOException{
+        this.byteBuffer=buffer;
+        byteBuffer.position(0);
+        byte[] readBytes=new byte[8192];
+        int count;
+        while ((count=inputStream.read(readBytes))>0){
+            byteBuffer.put(readBytes,0,count);
+        }
+        this.count=byteBuffer.position();
+    }
     @Override
     public int read() throws IOException {
         if (byteBuffer.position()>count || byteBuffer.remaining() == 0) {
@@ -83,4 +99,9 @@ public int capacity(){
     public void seek(int pos){
         byteBuffer.position(pos);
     }
+
+    @Override
+    public void close() throws IOException {
+        byteBuffer.clear();
+    }
 }
diff --git a/common/src/main/java/com/robin/core/fileaccess/util/ByteBufferOutputStream.java b/common/src/main/java/com/robin/core/fileaccess/util/ByteBufferOutputStream.java
index 2e2acf1b..2fb61543 100644
--- a/common/src/main/java/com/robin/core/fileaccess/util/ByteBufferOutputStream.java
+++ b/common/src/main/java/com/robin/core/fileaccess/util/ByteBufferOutputStream.java
@@ -44,6 +44,7 @@ public void writeLong(long value) throws IOException{
     }
     public void writeGap() throws IOException{
         write(0);
+        count++;
     }
     public void writeNullTag() throws IOException{
         //overwrite 0x00 with 0xff
diff --git a/common/src/main/java/com/robin/core/fileaccess/writer/AbstractFileWriter.java b/common/src/main/java/com/robin/core/fileaccess/writer/AbstractFileWriter.java
index 124dd2d9..5c756c13 100644
--- a/common/src/main/java/com/robin/core/fileaccess/writer/AbstractFileWriter.java
+++ b/common/src/main/java/com/robin/core/fileaccess/writer/AbstractFileWriter.java
@@ -48,6 +48,7 @@ public abstract class AbstractFileWriter implements IResourceWriter {
 	protected DateTimeFormatter formatter;
 	protected AbstractFileSystemAccessor accessUtil;
 	protected String identifier;
+	protected boolean useBufferedWriter=false;
 
 	public AbstractFileWriter(){
 
@@ -105,7 +106,9 @@ public void beginWrite() throws IOException{
 		if(out==null){
 			checkAccessUtil(colmeta.getPath());
 			out = accessUtil.getOutResourceByStream(ResourceUtil.getProcessPath(colmeta.getPath()));
-			writer=new BufferedWriter(new OutputStreamWriter(out));
+			if(useBufferedWriter) {
+				writer = new BufferedWriter(new OutputStreamWriter(out));
+			}
 		}
 		logger.info("using Writer {}",getClass().getCanonicalName());
 	}
diff --git a/common/src/main/java/com/robin/core/fileaccess/writer/JsonFileWriter.java b/common/src/main/java/com/robin/core/fileaccess/writer/JsonFileWriter.java
index 0f58df3a..3b090f41 100644
--- a/common/src/main/java/com/robin/core/fileaccess/writer/JsonFileWriter.java
+++ b/common/src/main/java/com/robin/core/fileaccess/writer/JsonFileWriter.java
@@ -17,6 +17,7 @@
 
 import com.google.gson.stream.JsonWriter;
 import com.robin.core.base.util.Const;
+import com.robin.core.fileaccess.fs.AbstractFileSystemAccessor;
 import com.robin.core.fileaccess.meta.DataCollectionMeta;
 
 import javax.naming.OperationNotSupportedException;
@@ -32,6 +33,11 @@ public JsonFileWriter(DataCollectionMeta colmeta) {
 		super(colmeta);
 		this.identifier= Const.FILEFORMATSTR.JSON.getValue();
 	}
+	public JsonFileWriter(DataCollectionMeta colmeta, AbstractFileSystemAccessor accessor) {
+		super(colmeta,accessor);
+		this.identifier= Const.FILEFORMATSTR.JSON.getValue();
+		this.useBufferedWriter=true;
+	}
 
 	@Override
 	public void beginWrite() throws IOException{
diff --git a/common/src/main/java/com/robin/core/fileaccess/writer/PlainTextFileWriter.java b/common/src/main/java/com/robin/core/fileaccess/writer/PlainTextFileWriter.java
index 692db1df..6aa87c6d 100644
--- a/common/src/main/java/com/robin/core/fileaccess/writer/PlainTextFileWriter.java
+++ b/common/src/main/java/com/robin/core/fileaccess/writer/PlainTextFileWriter.java
@@ -21,6 +21,7 @@
 import java.util.Map;
 
 import com.robin.core.base.util.Const;
+import com.robin.core.fileaccess.fs.AbstractFileSystemAccessor;
 import org.apache.commons.lang3.StringUtils;
 
 import com.robin.core.fileaccess.meta.DataCollectionMeta;
@@ -37,6 +38,10 @@ public PlainTextFileWriter(DataCollectionMeta colmeta) {
 		super(colmeta);
 		this.identifier= Const.FILEFORMATSTR.CSV.getValue();
 	}
+	public PlainTextFileWriter(DataCollectionMeta colmeta, AbstractFileSystemAccessor accessor) {
+		super(colmeta,accessor);
+		this.identifier= Const.FILEFORMATSTR.CSV.getValue();
+	}
 
 	@Override
 	public void beginWrite() throws IOException {
diff --git a/common/src/main/java/com/robin/core/fileaccess/writer/TextBasedFileWriter.java b/common/src/main/java/com/robin/core/fileaccess/writer/TextBasedFileWriter.java
index 4d9abb83..0737275c 100644
--- a/common/src/main/java/com/robin/core/fileaccess/writer/TextBasedFileWriter.java
+++ b/common/src/main/java/com/robin/core/fileaccess/writer/TextBasedFileWriter.java
@@ -16,6 +16,7 @@
 package com.robin.core.fileaccess.writer;
 
 import com.robin.core.base.util.StringUtils;
+import com.robin.core.fileaccess.fs.AbstractFileSystemAccessor;
 import com.robin.core.fileaccess.meta.DataCollectionMeta;
 
 import java.io.BufferedWriter;
@@ -30,6 +31,11 @@ public TextBasedFileWriter(){
 
 	protected TextBasedFileWriter(DataCollectionMeta colmeta) {
 		super(colmeta);
+		this.useBufferedWriter=true;
+	}
+	protected TextBasedFileWriter(DataCollectionMeta colmeta, AbstractFileSystemAccessor accessor) {
+		super(colmeta,accessor);
+		this.useBufferedWriter=true;
 	}
 	@Override
 	public void setOutputStream(OutputStream out) {
diff --git a/common/src/main/java/com/robin/core/fileaccess/writer/TextFileWriterFactory.java b/common/src/main/java/com/robin/core/fileaccess/writer/TextFileWriterFactory.java
index 76ad3738..69d41728 100644
--- a/common/src/main/java/com/robin/core/fileaccess/writer/TextFileWriterFactory.java
+++ b/common/src/main/java/com/robin/core/fileaccess/writer/TextFileWriterFactory.java
@@ -42,6 +42,7 @@ public static IResourceWriter getWriterByType(DataCollectionMeta colmeta, Buffer
         }
         return fileWriter;
     }
+
     public static IResourceWriter getWriterByType(DataCollectionMeta colmeta, BufferedWriter writer,AbstractFileSystemAccessor accessor) throws IOException {
         IResourceWriter fileWriter = getWriterByType(colmeta,accessor);
         if(!ObjectUtils.isEmpty(fileWriter) && writer!=null) {
@@ -96,7 +97,7 @@ public static IResourceWriter getWriterByType(DataCollectionMeta colmeta, Abstra
 
             Class<? extends IResourceWriter> writerClass=fileWriterMap.get(fileSuffix);
             if (!ObjectUtils.isEmpty(writerClass)) {
-                fileWriter =  writerClass.getConstructor(DataCollectionMeta.class).newInstance(colmeta);
+                fileWriter =  writerClass.getDeclaredConstructor(DataCollectionMeta.class, AbstractFileSystemAccessor.class).newInstance(colmeta,accessor);
                 fileWriter.setAccessUtil(accessor);
                 logger.info("using resource writer {}",writerClass.getCanonicalName());
             }
diff --git a/common/src/main/java/com/robin/core/fileaccess/writer/XlsxFileWriter.java b/common/src/main/java/com/robin/core/fileaccess/writer/XlsxFileWriter.java
new file mode 100644
index 00000000..9d47b93f
--- /dev/null
+++ b/common/src/main/java/com/robin/core/fileaccess/writer/XlsxFileWriter.java
@@ -0,0 +1,347 @@
+package com.robin.core.fileaccess.writer;
+
+import cn.hutool.core.io.FileUtil;
+import com.robin.comm.util.xls.ExcelBaseOper;
+import com.robin.comm.util.xls.ExcelCellStyleUtil;
+import com.robin.comm.util.xls.ExcelColumnProp;
+import com.robin.comm.util.xls.ExcelSheetProp;
+import com.robin.core.base.util.Const;
+import com.robin.core.fileaccess.fs.AbstractFileSystemAccessor;
+import com.robin.core.fileaccess.meta.DataCollectionMeta;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackagePartName;
+import org.apache.poi.openxml4j.opc.PackagingURIHelper;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.util.ObjectUtils;
+import org.tukaani.xz.FinishableOutputStream;
+
+import javax.naming.OperationNotSupportedException;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.*;
+import java.lang.reflect.Field;
+import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+
+/**
+ * Xlsx StaX writer,Support divided Sheet write,MAX_LINE max sheet lines
+ */
+public class XlsxFileWriter extends AbstractFileWriter{
+    private XMLStreamWriter streamWriter;
+    private XSSFWorkbook workbook;
+    private OPCPackage opcPackage;
+
+    private static final char CHARA = 'A';
+    private final Map<String,CellStyle> cellStyleMap=new HashMap<>();
+    private int rowPos=2;
+    private int currentSheetPos=0;
+    private ExcelSheetProp sheetProp;
+    private ZipOutputStream zipOutputStream;
+    private BufferedOutputStream bufferedOutputStream;
+    private boolean multipleSheets=false;
+    private ByteArrayOutputStream byteOut;
+    private FileOutputStream tmpZipFile;
+    private String tmpFileName;
+    private XMLOutputFactory factory;
+    private int MAX_LINE=Double.valueOf(Math.pow(2,18)).intValue();
+    public XlsxFileWriter(){
+        this.identifier= Const.FILEFORMATSTR.XLSX.getValue();
+    }
+    public XlsxFileWriter(DataCollectionMeta colmeta) {
+        super(colmeta);
+        this.identifier= Const.FILEFORMATSTR.XLSX.getValue();
+        if(colmeta.getResourceCfgMap().containsKey(Const.COLUMN_XLSX_MULTIPLESHEETS) && Const.TRUE.equalsIgnoreCase(colmeta.getResourceCfgMap().get(Const.COLUMN_XLSX_MULTIPLESHEETS).toString())){
+            multipleSheets=true;
+        }
+        if(colmeta.getResourceCfgMap().containsKey(Const.COLUMN_XLSX_SHEETLINELIMITS) && NumberUtils.isNumber(colmeta.getResourceCfgMap().get(Const.COLUMN_XLSX_SHEETLINELIMITS).toString())){
+            MAX_LINE=Integer.parseInt(colmeta.getResourceCfgMap().get(Const.COLUMN_XLSX_SHEETLINELIMITS).toString());
+        }
+    }
+    public XlsxFileWriter(DataCollectionMeta colmeta, AbstractFileSystemAccessor accessor) {
+        super(colmeta,accessor);
+        this.identifier= Const.FILEFORMATSTR.XLSX.getValue();
+        if(colmeta.getResourceCfgMap().containsKey(Const.COLUMN_XLSX_MULTIPLESHEETS) && Const.TRUE.equalsIgnoreCase(colmeta.getResourceCfgMap().get(Const.COLUMN_XLSX_MULTIPLESHEETS).toString())){
+            multipleSheets=true;
+        }
+        if(colmeta.getResourceCfgMap().containsKey(Const.COLUMN_XLSX_SHEETLINELIMITS) && NumberUtils.isNumber(colmeta.getResourceCfgMap().get(Const.COLUMN_XLSX_SHEETLINELIMITS).toString())){
+            MAX_LINE=Integer.parseInt(colmeta.getResourceCfgMap().get(Const.COLUMN_XLSX_SHEETLINELIMITS).toString());
+        }
+    }
+
+    @Override
+    public void beginWrite() throws IOException {
+        super.beginWrite();
+        try {
+            factory=XMLOutputFactory.newFactory();
+            workbook = new XSSFWorkbook();
+            Field field = workbook.getClass().getSuperclass().getDeclaredField("pkg");
+            field.setAccessible(true);
+            opcPackage = (OPCPackage) field.get(workbook);
+            workbook.createSheet("sheet1");
+            PackagePartName packagePartName = PackagingURIHelper.createPartName("/xl/worksheets/sheet1.xml");
+            opcPackage.removePart(packagePartName);
+            for(int i=0;i<colmeta.getColumnList().size();i++){
+                ExcelCellStyleUtil.getCellStyle(workbook, colmeta.getColumnList().get(i).getColumnType(), cellStyleMap);
+            }
+            byteOut=new ByteArrayOutputStream();
+
+            if(!multipleSheets) {
+                workbook.write(byteOut);
+                workbook.close();
+                zipOutputStream = new ZipOutputStream(out);
+                writeOrigin(zipOutputStream,new ByteArrayInputStream(byteOut.toByteArray()));
+            }else{
+                String tmpPath=System.getProperty("java.io.tmpdir");
+                tmpFileName=tmpPath+File.separator+System.currentTimeMillis()+".zip";
+                tmpZipFile=new FileOutputStream(tmpFileName);
+                zipOutputStream = new ZipOutputStream(tmpZipFile);
+            }
+            zipOutputStream.putNextEntry(new ZipEntry("xl/worksheets/sheet1.xml"));
+            bufferedOutputStream=new BufferedOutputStream(zipOutputStream,81920);
+            streamWriter = factory.createXMLStreamWriter(bufferedOutputStream,colmeta.getEncode());
+            writePrefix();
+            writeHeader(sheetProp.getColumnPropList().stream().map(ExcelColumnProp::getColumnName).collect(Collectors.toList()),cellStyleMap);
+        }catch (Exception ex){
+            ex.printStackTrace();
+        }
+    }
+    private void createSheet() throws Exception {
+        int sheetNum=rowPos/MAX_LINE+1;
+        workbook.createSheet("sheet"+sheetNum);
+        PackagePartName packagePartName = PackagingURIHelper.createPartName("/xl/worksheets/sheet"+sheetNum+".xml");
+        opcPackage.removePart(packagePartName);
+        zipOutputStream.putNextEntry(new ZipEntry("xl/worksheets/sheet"+sheetNum+".xml"));
+        //streamWriter = factory.createXMLStreamWriter(bufferedOutputStream,colmeta.getEncode());
+        writePrefix();
+        writeHeader(sheetProp.getColumnPropList().stream().map(ExcelColumnProp::getColumnName).collect(Collectors.toList()),cellStyleMap);
+    }
+    protected void writePrefix() throws XMLStreamException {
+        streamWriter.writeStartDocument("UTF-8", "1.0");
+        streamWriter.writeStartElement("worksheet");
+        streamWriter.writeAttribute("xmlxs", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
+        streamWriter.writeEmptyElement("dimension");
+        streamWriter.writeAttribute("ref", "A1");
+        streamWriter.writeStartElement("sheetViews");
+        streamWriter.writeStartElement("sheetView");
+        streamWriter.writeAttribute("workbookViewId", "0");
+        streamWriter.writeAttribute("tabSelected", "true");
+        streamWriter.writeEndElement();
+        streamWriter.writeEndElement();
+        streamWriter.writeEmptyElement("sheetFormatPr");
+        streamWriter.writeAttribute("defaultRowHeight", "15.0");
+        streamWriter.writeStartElement("cols");
+        streamWriter.writeStartElement("col");
+        streamWriter.writeAttribute("min", "1");
+        streamWriter.writeAttribute("max", "1");
+        streamWriter.writeAttribute("customWidth", "true");
+        streamWriter.writeEndElement();
+        streamWriter.writeEndElement();
+        streamWriter.writeStartElement("sheetData");
+    }
+
+    private void writeOrigin(ZipOutputStream outputStream,InputStream inStream){
+        try(ZipInputStream zis=ZipInputStream.class.isAssignableFrom(inStream.getClass())?(ZipInputStream)inStream:new ZipInputStream(inStream)){
+            ZipEntry entry;
+            while ((entry = zis.getNextEntry()) != null) {
+                outputStream.putNextEntry(new ZipEntry(entry.getName()));
+                byte[] buffer = new byte[8192];
+                int len;
+                while ((len = zis.read(buffer)) != -1) {
+                    outputStream.write(buffer, 0, len);
+                }
+                outputStream.closeEntry();
+            }
+        }catch (IOException ex){
+
+        }
+    }
+
+    @Override
+    public void finishWrite() throws IOException {
+        try{
+            streamWriter.writeEndElement();
+            streamWriter.writeEndElement();
+            if(bufferedOutputStream!=null){
+                bufferedOutputStream.flush();
+            }
+            streamWriter.flush();
+            if(!(out instanceof FinishableOutputStream)) {
+                writer.flush();
+            }else{
+                ((FinishableOutputStream) out).finish();
+            }
+
+        }catch (Exception ex){
+            throw new IOException(ex);
+        }finally {
+            try {
+                if(streamWriter!=null) {
+                    streamWriter.close();
+                }
+            }catch (XMLStreamException ex){
+                ex.printStackTrace();
+            }
+            if(zipOutputStream!=null) {
+                zipOutputStream.closeEntry();
+                zipOutputStream.close();
+                if(multipleSheets){
+                    workbook.write(byteOut);
+                    workbook.close();
+                    bufferedOutputStream.close();
+                    tmpZipFile.close();
+                    try(ZipOutputStream zOut1=new ZipOutputStream(out);
+                            ZipInputStream sheetIn=new ZipInputStream(new FileInputStream(tmpFileName))){
+                        writeOrigin(zOut1,new ByteArrayInputStream(byteOut.toByteArray()));
+                        writeOrigin(zOut1,sheetIn);
+                    }catch (Exception ex){
+
+                    }finally {
+                        FileUtil.del(tmpFileName);
+                    }
+                }
+            }
+            if(bufferedOutputStream!=null) {
+                bufferedOutputStream.close();
+            }
+        }
+    }
+
+    @Override
+    public void flush() throws IOException {
+        if(bufferedOutputStream!=null) {
+            bufferedOutputStream.flush();
+        }
+    }
+
+    @Override
+    public void writeRecord(Map<String, Object> map) throws IOException, OperationNotSupportedException {
+        try{
+            //数据量超过单sheet上限，需要新的Sheet
+            if(currentSheetPos==MAX_LINE){
+                if(!multipleSheets){
+                    throw new OperationNotSupportedException("must set tag "+Const.COLUMN_XLSX_MULTIPLESHEETS);
+                }
+                streamWriter.writeEndElement();
+                streamWriter.writeEndElement();
+                streamWriter.flush();
+                //streamWriter.close();
+                bufferedOutputStream.flush();
+                zipOutputStream.closeEntry();
+                createSheet();
+                currentSheetPos=0;
+            }
+            writeLine(map,colmeta,cellStyleMap,currentSheetPos+2);
+            rowPos++;
+            currentSheetPos++;
+        }catch (Exception ex){
+            throw new IOException(ex);
+        }
+    }
+    private String getEndCell(int columnSize) {
+        int firstPos = columnSize / 26;
+        int secondPos = columnSize % 26;
+        StringBuilder builder = new StringBuilder();
+        if (firstPos > 0) {
+            builder.append((char)(CHARA + firstPos - 1));
+        }
+        builder.append((char)(CHARA + secondPos - 1));
+        return builder.toString();
+    }
+    protected void writeLine(Map<String, Object> valueMap, DataCollectionMeta colmeta, Map<String, CellStyle> cellStyleMap, int rowpos) throws XMLStreamException {
+
+        streamWriter.writeStartElement("row");
+        streamWriter.writeAttribute("r", String.valueOf(rowpos));
+        for (int i = 0; i < colmeta.getColumnList().size(); i++) {
+            CellStyle style = cellStyleMap.get(colmeta.getColumnList().get(i).getColumnType());
+            if (!ObjectUtils.isEmpty(valueMap.get(colmeta.getColumnList().get(i).getColumnName()))) {
+                streamWriter.writeStartElement("c");
+                streamWriter.writeAttribute("r", getEndCell(i + 1) + rowpos);
+                streamWriter.writeAttribute("s", String.valueOf(style.getFontIndexAsInt()));
+                if (Const.META_TYPE_STRING.equals(colmeta.getColumnList().get(i).getColumnType())) {
+                    streamWriter.writeAttribute("t", "inlineStr");
+                    streamWriter.writeStartElement("is");
+                    streamWriter.writeStartElement("t");
+                    streamWriter.writeCharacters(valueMap.get(colmeta.getColumnList().get(i).getColumnName()).toString());
+                    streamWriter.writeEndElement();
+                    streamWriter.writeEndElement();
+                } else {
+                    streamWriter.writeAttribute("t", "n");
+
+                    if (Const.META_TYPE_TIMESTAMP.equals(colmeta.getColumnList().get(i).getColumnType()) || Const.META_TYPE_DATE.equals(colmeta.getColumnList().get(i).getColumnType())) {
+                        streamWriter.writeStartElement("v");
+                        Object value = valueMap.get(colmeta.getColumnList().get(i).getColumnName());
+                        Date valDate = null;
+                        double dateVal=0.0;
+                        if (Timestamp.class.isAssignableFrom(value.getClass())) {
+                            valDate = new Date(((Timestamp) value).getTime());
+                            dateVal = DateUtil.getExcelDate(valDate);
+                        } else if(LocalDateTime.class.isAssignableFrom(value.getClass())){
+                            dateVal=DateUtil.getExcelDate((LocalDateTime) value);
+                        }else if(LocalDate.class.isAssignableFrom(value.getClass())){
+                            dateVal=DateUtil.getExcelDate((LocalDate) value);
+                        }
+                        else if(Date.class.isAssignableFrom(value.getClass())){
+                            dateVal=DateUtil.getExcelDate((Date) value);
+                        }else{
+                            dateVal=DateUtil.getExcelDate(new Date(Long.valueOf(value.toString())));
+                        }
+                        streamWriter.writeCharacters(String.valueOf(dateVal));
+                    }
+                    else {
+                        streamWriter.writeStartElement("v");
+                        streamWriter.writeCharacters(valueMap.get(colmeta.getColumnList().get(i).getColumnName()).toString());
+                    }
+                    streamWriter.writeEndElement();
+                }
+                streamWriter.writeEndElement();
+            }else if(Const.META_TYPE_FORMULA.equals(sheetProp.getColumnPropList().get(i).getColumnType())){
+                streamWriter.writeStartElement("c");
+                streamWriter.writeAttribute("r", getEndCell(i + 1) + rowpos);
+                streamWriter.writeAttribute("s", String.valueOf(style.getFontIndexAsInt()));
+                streamWriter.writeStartElement("f");
+                streamWriter.writeCharacters(ExcelBaseOper.returnFormulaWithPos(sheetProp.getColumnPropList().get(i).getFormula(),rowpos));
+                streamWriter.writeEndElement();
+                streamWriter.writeEndElement();
+            }
+        }
+        streamWriter.writeEndElement();
+        streamWriter.writeCharacters("\n");
+    }
+
+    public void setSheetProp(ExcelSheetProp sheetProp) {
+        this.sheetProp = sheetProp;
+    }
+
+    private void writeHeader(List<String> columnName, Map<String, CellStyle> cellStyleMap) throws Exception {
+        CellStyle style = cellStyleMap.get(Const.META_TYPE_STRING);
+        streamWriter.writeStartElement("row");
+        streamWriter.writeAttribute("r", "1");
+        for (int i = 0; i < columnName.size(); i++) {
+            streamWriter.writeStartElement("c");
+            streamWriter.writeAttribute("r", getEndCell(i + 1) + "1");
+            streamWriter.writeAttribute("s", String.valueOf(style.getIndex()));
+            streamWriter.writeAttribute("t", "inlineStr");
+            streamWriter.writeStartElement("is");
+            streamWriter.writeStartElement("t");
+            streamWriter.writeCharacters(columnName.get(i));
+            streamWriter.writeEndElement();
+            streamWriter.writeEndElement();
+            streamWriter.writeEndElement();
+        }
+        streamWriter.writeEndElement();
+    }
+}
diff --git a/common/src/main/java/com/robin/core/fileaccess/writer/XmlFileWriter.java b/common/src/main/java/com/robin/core/fileaccess/writer/XmlFileWriter.java
index ffd45a0c..99c48ccf 100644
--- a/common/src/main/java/com/robin/core/fileaccess/writer/XmlFileWriter.java
+++ b/common/src/main/java/com/robin/core/fileaccess/writer/XmlFileWriter.java
@@ -16,6 +16,7 @@
 package com.robin.core.fileaccess.writer;
 
 import com.robin.core.base.util.Const;
+import com.robin.core.fileaccess.fs.AbstractFileSystemAccessor;
 import com.robin.core.fileaccess.meta.DataCollectionMeta;
 import org.tukaani.xz.FinishableOutputStream;
 
@@ -37,6 +38,10 @@ public XmlFileWriter(DataCollectionMeta colmeta) {
 		super(colmeta);
 		this.identifier= Const.FILEFORMATSTR.XML.getValue();
 	}
+	public XmlFileWriter(DataCollectionMeta colmeta, AbstractFileSystemAccessor accessor) {
+		super(colmeta,accessor);
+		this.identifier= Const.FILEFORMATSTR.XML.getValue();
+	}
 
 	@Override
 	public void beginWrite() throws IOException {
diff --git a/common/src/main/resources/META-INF/services/com.robin.core.fileaccess.iterator.IResourceIterator b/common/src/main/resources/META-INF/services/com.robin.core.fileaccess.iterator.IResourceIterator
index c0019ebf..9323d271 100644
--- a/common/src/main/resources/META-INF/services/com.robin.core.fileaccess.iterator.IResourceIterator
+++ b/common/src/main/resources/META-INF/services/com.robin.core.fileaccess.iterator.IResourceIterator
@@ -3,3 +3,4 @@ com.robin.core.fileaccess.iterator.PlainTextFileIterator
 com.robin.core.fileaccess.iterator.ArffFileIterator
 com.robin.core.fileaccess.iterator.XmlFileIterator
 com.robin.core.resaccess.iterator.JdbcResIterator
+com.robin.core.fileaccess.iterator.XlsxFileIterator
diff --git a/common/src/main/resources/META-INF/services/com.robin.core.fileaccess.writer.IResourceWriter b/common/src/main/resources/META-INF/services/com.robin.core.fileaccess.writer.IResourceWriter
index 2882c358..1d716e04 100644
--- a/common/src/main/resources/META-INF/services/com.robin.core.fileaccess.writer.IResourceWriter
+++ b/common/src/main/resources/META-INF/services/com.robin.core.fileaccess.writer.IResourceWriter
@@ -1,3 +1,4 @@
 com.robin.core.fileaccess.writer.JsonFileWriter
 com.robin.core.fileaccess.writer.PlainTextFileWriter
-com.robin.core.fileaccess.writer.XmlFileWriter
\ No newline at end of file
+com.robin.core.fileaccess.writer.XmlFileWriter
+com.robin.core.fileaccess.writer.XlsxFileWriter
\ No newline at end of file
diff --git a/common/src/test/java/com/robin/comm/test/TestExcelOperation.java b/common/src/test/java/com/robin/comm/test/TestExcelOperation.java
index 29fd308b..0ad05ee8 100644
--- a/common/src/test/java/com/robin/comm/test/TestExcelOperation.java
+++ b/common/src/test/java/com/robin/comm/test/TestExcelOperation.java
@@ -7,54 +7,333 @@
 import com.robin.core.base.datameta.DataBaseParam;
 import com.robin.core.base.util.Const;
 import com.robin.core.base.util.StringUtils;
+import com.robin.core.fileaccess.fs.LocalFileSystemAccessor;
+import com.robin.core.fileaccess.iterator.AbstractFileIterator;
 import com.robin.core.fileaccess.iterator.AbstractResIterator;
+import com.robin.core.fileaccess.iterator.TextFileIteratorFactory;
+import com.robin.core.fileaccess.meta.DataCollectionMeta;
+import com.robin.core.fileaccess.writer.TextFileWriterFactory;
+import com.robin.core.fileaccess.writer.XlsxFileWriter;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.openxml4j.opc.*;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.streaming.SXSSFWorkbook;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.util.ObjectUtils;
 
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.*;
+import java.lang.reflect.Field;
 import java.sql.Connection;
+import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
 
 
 @Slf4j
 public class TestExcelOperation {
     private Logger logger = LoggerFactory.getLogger(TestExcelOperation.class);
+    private static final char CHARA = 'A';
+
+    @Test
+    public void testReadWithIterator() throws Exception {
+        DataCollectionMeta.Builder builder = new DataCollectionMeta.Builder();
+        builder.addColumn("name", Const.META_TYPE_STRING).addColumn("time", Const.META_TYPE_TIMESTAMP)
+                .addColumn("intcol", Const.META_TYPE_INTEGER).addColumn("dval", Const.META_TYPE_DOUBLE)
+                .addColumn("dval2", Const.META_TYPE_DOUBLE).addColumn("diff", Const.META_TYPE_DOUBLE)
+                .fileFormat(Const.FILEFORMATSTR.XLSX.getValue()).resPath("file:///d:/test2.xlsx");
+
+        LocalFileSystemAccessor accessor = LocalFileSystemAccessor.getInstance();
+        Long fromTs=System.currentTimeMillis();
+        try (AbstractFileIterator iterator = (AbstractFileIterator) TextFileIteratorFactory.getProcessIteratorByType(builder.build(), accessor)) {
+            int pos = 0;
+            while (iterator.hasNext()) {
+                pos++;
+            }
+            System.out.println(pos);
+            System.out.println(System.currentTimeMillis()-fromTs);
+        } catch (IOException ex) {
+
+        }
+    }
+    @Test
+    public void testWriteStAX() throws Exception{
+        ExcelSheetProp.Builder builder1 = ExcelSheetProp.Builder.newBuilder();
+        builder1.addColumnProp(new ExcelColumnProp("name", "name", Const.META_TYPE_STRING, false));
+        builder1.addColumnProp(new ExcelColumnProp("time", "time", Const.META_TYPE_TIMESTAMP, false));
+        builder1.addColumnProp(new ExcelColumnProp("intcol", "intcol", Const.META_TYPE_INTEGER, false));
+        builder1.addColumnProp(new ExcelColumnProp("dval", "dval", Const.META_TYPE_DOUBLE, false));
+        builder1.addColumnProp(new ExcelColumnProp("dval2", "dval2", Const.META_TYPE_DOUBLE, false));
+        builder1.addColumnProp(new ExcelColumnProp("diff", "diff", Const.META_TYPE_FORMULA, "(D{P}-E{P})/C{P}"));
+        DataCollectionMeta.Builder builder = new DataCollectionMeta.Builder();
+        builder.addColumn("name", Const.META_TYPE_STRING).addColumn("time", Const.META_TYPE_TIMESTAMP)
+                .addColumn("intcol", Const.META_TYPE_INTEGER).addColumn("dval", Const.META_TYPE_DOUBLE)
+                .addColumn("dval2", Const.META_TYPE_DOUBLE).addColumn("diff", Const.META_TYPE_DOUBLE)
+                .fileFormat(Const.FILEFORMATSTR.XLSX.getValue()).resPath("file:///d:/test2.xlsx");
+        DataCollectionMeta meta = builder.build();
+        LocalFileSystemAccessor accessor = LocalFileSystemAccessor.getInstance();
+        Random random = new Random(12312321321312L);
+        Map<String,Object> cachedMap=new HashMap<>();
+        try(XlsxFileWriter writer=(XlsxFileWriter) TextFileWriterFactory.getWriterByType(meta,accessor)){
+            writer.setSheetProp(builder1.build());
+            writer.beginWrite();
+            Long startTs = System.currentTimeMillis() - 3600 * 24 * 1000;
+            for(int j=0;j<1200000;j++){
+                cachedMap.put("name", StringUtils.generateRandomChar(12));
+                cachedMap.put("time", String.valueOf(startTs + j * 1000));
+                cachedMap.put("intcol", String.valueOf(random.nextInt(1000)));
+                cachedMap.put("dval", String.valueOf(random.nextDouble() * 1000));
+                cachedMap.put("dval2", String.valueOf(random.nextDouble() * 500));
+                writer.writeRecord(cachedMap);
+            }
+            writer.finishWrite();
+        }catch (Exception ex){
+            ex.printStackTrace();
+        }
+    }
+
+
+    @Test
+    public void testWriteStream() throws Exception{
+        DataCollectionMeta.Builder builder = new DataCollectionMeta.Builder();
+        builder.addColumn("name", Const.META_TYPE_STRING).addColumn("time", Const.META_TYPE_TIMESTAMP)
+                .addColumn("intcol", Const.META_TYPE_INTEGER).addColumn("dval", Const.META_TYPE_DOUBLE)
+                .addColumn("dval2", Const.META_TYPE_DOUBLE).addColumn("diff", Const.META_TYPE_DOUBLE)
+                .fileFormat(Const.FILEFORMATSTR.XLSX.getValue()).resPath("file:///d:/test.xlsx");
+        DataCollectionMeta meta = builder.build();
+        XMLOutputFactory factory = XMLOutputFactory.newFactory();
+        XMLStreamWriter writer=null;
+        Map<String,CellStyle> cellStyleMap=new HashMap<>();
+        Map<String,Object> cachedMap=new HashMap<>();
+        Random random = new Random(12312321321312L);
+        ByteArrayOutputStream byteOut=new ByteArrayOutputStream();
+        try(XSSFWorkbook workbook=new XSSFWorkbook()){
+            Field field=workbook.getClass().getSuperclass().getDeclaredField("pkg");
+            field.setAccessible(true);
+            OPCPackage opcPackage=(OPCPackage) field.get(workbook);
+            Sheet sheet=workbook.createSheet("sheet1");
+            PackagePartName packagePartName = PackagingURIHelper.createPartName("/xl/worksheets/sheet1.xml");
+            opcPackage.removePart(packagePartName);
+            for(int i=0;i<meta.getColumnList().size();i++){
+                ExcelCellStyleUtil.getCellStyle(workbook, meta.getColumnList().get(i).getColumnType(), cellStyleMap);
+            }
+            workbook.write(byteOut);
+        }catch (Exception ex1){
+            ex1.printStackTrace();
+        }
+        try(ZipOutputStream zout=new ZipOutputStream(new FileOutputStream("d:/test2.xlsx"));
+            ZipInputStream zis=new ZipInputStream(new ByteArrayInputStream(byteOut.toByteArray()))){
+            ZipEntry entry;
+            // Copy existing entries
+            while ((entry = zis.getNextEntry()) != null) {
+                zout.putNextEntry(new ZipEntry(entry.getName()));
+                byte[] buffer = new byte[1024];
+                int len;
+                while ((len = zis.read(buffer)) != -1) {
+                    zout.write(buffer, 0, len);
+                }
+                zout.closeEntry();
+            }
+            zout.putNextEntry(new ZipEntry("xl/worksheets/sheet1.xml"));
+            writer = factory.createXMLStreamWriter(zout);
+            writer.writeStartDocument("UTF-8", "1.0");
+            writer.writeStartElement("worksheet");
+            writer.writeAttribute("xmlxs", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
+            writer.writeEmptyElement("dimension");
+            writer.writeAttribute("ref", "A1:" + getEndCell(meta.getColumnList().size()) + "50001");
+            writer.writeStartElement("sheetViews");
+            writer.writeStartElement("sheetView");
+            writer.writeAttribute("workbookViewId", "0");
+            writer.writeAttribute("tabSelected", "true");
+            writer.writeEndElement();
+            writer.writeEndElement();
+            writer.writeEmptyElement("sheetFormatPr");
+            writer.writeAttribute("defaultRowHeight", "15.0");
+            writer.writeStartElement("cols");
+            writer.writeStartElement("col");
+            writer.writeAttribute("min", "1");
+            writer.writeAttribute("max", "1");
+            writer.writeAttribute("customWidth", "true");
+            writer.writeEndElement();
+            writer.writeEndElement();
+            writer.writeStartElement("sheetData");
+            writeHeader(writer,Arrays.asList("name","time","intcol","dval","dval2","diff"),cellStyleMap);
+            cachedMap.clear();
+            Long startTs = System.currentTimeMillis() - 3600 * 24 * 1000;
+            for(int j=0;j<600000;j++){
+                cachedMap.put("name", StringUtils.generateRandomChar(12));
+                cachedMap.put("time", String.valueOf(startTs + j * 1000));
+                cachedMap.put("intcol", String.valueOf(random.nextInt(1000)));
+                cachedMap.put("dval", String.valueOf(random.nextDouble() * 1000));
+                cachedMap.put("dval2", String.valueOf(random.nextDouble() * 500));
+                writeLine(writer,cachedMap,meta,cellStyleMap,j+2);
+            }
+            writer.writeEndElement();
+            writer.writeEndElement();
+            writer.flush();
+            writer.close();
+            zout.closeEntry();
+        }catch (Exception ex){
+            ex.printStackTrace();
+        }
+
+       /* try (XSSFWorkbook workbook = new XSSFWorkbook()) {
+             Field field=workbook.getClass().getSuperclass().getDeclaredField("pkg");
+             field.setAccessible(true);
+             OPCPackage opcPackage=(OPCPackage) field.get(workbook);
+             workbook.createSheet("sheet1");
+
+            List<PackagePart> sheets = opcPackage.getPartsByContentType(XSSFRelation.WORKSHEET.getContentType());
+
+            List<PackagePart> sharedParts = opcPackage.getPartsByContentType(XSSFRelation.SHARED_STRINGS.getContentType());
+
+            PackagePartName packagePartName = PackagingURIHelper.createPartName("/xl/worksheets/sheet1.xml");
+            opcPackage.removePart(packagePartName);
+            //opcPackage.deletePart(packagePartName);
+            //PackagePart part=opcPackage.getPart(packagePartName);
+            PackagePart part = opcPackage.createPart(packagePartName,XSSFRelation.WORKSHEET.getContentType());
+            opcPackage.addRelationship(packagePartName, TargetMode.INTERNAL,XSSFRelation.WORKSHEET.getRelation());
+            opcPackage.flush();
+            //ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
+            OutputStream outputStream = part.getOutputStream();
+
+            part.flush();
+            opcPackage.flush();
+            Sheet sheet=workbook.getSheetAt(0);
+            for(int i=0;i<meta.getColumnList().size();i++) {
+                sheet.autoSizeColumn(i);
+            }
+            workbook.write(new FileOutputStream("d:/test1.xlsx"));
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        } finally {
+            if(writer!=null) {
+                writer.close();
+            }
+        }*/
+    }
+
+    private String getEndCell(int columnSize) {
+        int firstPos = columnSize / 26;
+        int secondPos = columnSize % 26;
+        StringBuilder builder = new StringBuilder();
+        if (firstPos > 0) {
+            builder.append((char)(CHARA + firstPos - 1));
+        }
+        builder.append((char)(CHARA + secondPos - 1));
+        return builder.toString();
+    }
+
+    private void writeLine(XMLStreamWriter writer,Map<String, Object> valueMap, DataCollectionMeta colmeta, Map<String, CellStyle> cellStyleMap, int rowpos) throws Exception {
+
+        writer.writeStartElement("row");
+        writer.writeAttribute("r", String.valueOf(rowpos));
+        for (int i = 0; i < colmeta.getColumnList().size(); i++) {
+            CellStyle style = cellStyleMap.get(colmeta.getColumnList().get(i).getColumnType());
+            if (!ObjectUtils.isEmpty(valueMap.get(colmeta.getColumnList().get(i).getColumnName()))) {
+                writer.writeStartElement("c");
+                writer.writeAttribute("r", getEndCell(i + 1) + rowpos);
+                writer.writeAttribute("s", String.valueOf(style.getFontIndexAsInt()));
+                if (Const.META_TYPE_STRING.equals(colmeta.getColumnList().get(i).getColumnType())) {
+                    writer.writeAttribute("t", "inlineStr");
+                    writer.writeStartElement("is");
+                    writer.writeStartElement("t");
+                    writer.writeCharacters(valueMap.get(colmeta.getColumnList().get(i).getColumnName()).toString());
+                    writer.writeEndElement();
+                    writer.writeEndElement();
+                } else {
+                    writer.writeAttribute("t", "n");
+                    writer.writeStartElement("v");
+                    if (Const.META_TYPE_TIMESTAMP.equals(colmeta.getColumnList().get(i).getColumnType()) || Const.META_TYPE_DATE.equals(colmeta.getColumnList().get(i).getColumnType())) {
+                        Object value = valueMap.get(colmeta.getColumnList().get(i).getColumnName());
+                        Date valDate = null;
+                        double dateVal=0.0;
+                        if (Timestamp.class.isAssignableFrom(value.getClass())) {
+                            valDate = new Date(((Timestamp) value).getTime());
+                            dateVal = DateUtil.getExcelDate(valDate);
+                        } else if(LocalDateTime.class.isAssignableFrom(value.getClass())){
+                            dateVal=DateUtil.getExcelDate((LocalDateTime) value);
+                        }else if(LocalDate.class.isAssignableFrom(value.getClass())){
+                            dateVal=DateUtil.getExcelDate((LocalDate) value);
+                        }
+                        else if(Date.class.isAssignableFrom(value.getClass())){
+                            dateVal=DateUtil.getExcelDate((Date) value);
+                        }else{
+                            dateVal=DateUtil.getExcelDate(new Date(Long.valueOf(value.toString())));
+                        }
+                        writer.writeCharacters(String.valueOf(dateVal));
+                    } else {
+                        writer.writeCharacters(valueMap.get(colmeta.getColumnList().get(i).getColumnName()).toString());
+                    }
+                    writer.writeEndElement();
+                }
+                writer.writeEndElement();
+            }
+        }
+        writer.writeEndElement();
+        writer.writeCharacters("\n");
+    }
+
+    private void writeHeader(XMLStreamWriter writer, List<String> columnName, Map<String, CellStyle> cellStyleMap) throws Exception {
+        CellStyle style = cellStyleMap.get(Const.META_TYPE_STRING);
+        writer.writeStartElement("row");
+        writer.writeAttribute("r", "1");
+        for (int i = 0; i < columnName.size(); i++) {
+            writer.writeStartElement("c");
+            writer.writeAttribute("r", getEndCell(i + 1) + "1");
+            writer.writeAttribute("s", String.valueOf(style.getIndex()));
+            writer.writeAttribute("t", "inlineStr");
+            writer.writeStartElement("is");
+            writer.writeStartElement("t");
+            writer.writeCharacters(columnName.get(i));
+            writer.writeEndElement();
+            writer.writeEndElement();
+            writer.writeEndElement();
+        }
+        writer.writeEndElement();
+    }
+
+
 
     @Test
     public void testGenerate() throws Exception {
         Long startTs = System.currentTimeMillis() - 3600 * 24 * 1000;
-        ExcelSheetProp prop = new ExcelSheetProp();
+        ExcelSheetProp.Builder prop = ExcelSheetProp.Builder.newBuilder();
         prop.setFileExt("xlsx");
         prop.setStartCol(1);
         prop.setStartRow(1);
         prop.setSheetName("test");
-        prop.setStreamInsert(true);
+        prop.setStreamMode();
         prop.addColumnProp(new ExcelColumnProp("name", "name", Const.META_TYPE_STRING, false));
         prop.addColumnProp(new ExcelColumnProp("time", "time", Const.META_TYPE_TIMESTAMP, false));
         prop.addColumnProp(new ExcelColumnProp("intcol", "intcol", Const.META_TYPE_INTEGER, false));
         prop.addColumnProp(new ExcelColumnProp("dval", "dval", Const.META_TYPE_DOUBLE, false));
-        prop.addColumnProp(new ExcelColumnProp("差距1", "sep1", Const.META_TYPE_FORMULA, "D{P+1}-D{P}"));
-        prop.addColumnProp(new ExcelColumnProp("差距2", "sep2", Const.META_TYPE_FORMULA, "D{P-1}-D{P}"));
+        prop.addColumnProp(new ExcelColumnProp("dval2", "dval2", Const.META_TYPE_DOUBLE, false));
+        prop.addColumnProp(new ExcelColumnProp("diff", "diff", Const.META_TYPE_FORMULA, "(D{P}-E{P})/C{P}"));
+        //prop.addColumnProp(new ExcelColumnProp("差距1", "sep1", Const.META_TYPE_FORMULA, "D{P+1}-D{P}"));
+        //prop.addColumnProp(new ExcelColumnProp("差距2", "sep2", Const.META_TYPE_FORMULA, "D{P-1}-D{P}"));
         TableConfigProp header = new TableConfigProp();
         header.setContainrow(1);
         Random random = new Random(12312321321312L);
         AbstractResIterator iterator = new AbstractResIterator() {
             Map<String, Object> map = new HashMap<>();
             int row = 0;
+
             @Override
             public void beforeProcess() {
 
             }
+
             @Override
             public void afterProcess() {
 
@@ -67,7 +346,7 @@ public void close() throws IOException {
 
             @Override
             public boolean hasNext() {
-                if (row < 5000)
+                if (row < 50000)
                     return true;
                 return false;
             }
@@ -79,6 +358,7 @@ public Map<String, Object> next() {
                 map.put("time", String.valueOf(startTs + row * 1000));
                 map.put("intcol", String.valueOf(random.nextInt(1000)));
                 map.put("dval", String.valueOf(random.nextDouble() * 1000));
+                map.put("dval2", String.valueOf(random.nextDouble() * 500));
                 row++;
                 return map;
             }
@@ -88,7 +368,7 @@ public String getIdentifier() {
                 return "test";
             }
         };
-        Workbook wb = ExcelProcessor.generateExcelFile(prop, header, iterator);
+        Workbook wb = ExcelProcessor.generateExcelFile(prop.build(), header, iterator);
         FileOutputStream out = new FileOutputStream("d:/test.xlsx");
         wb.write(out);
         out.close();
@@ -97,18 +377,19 @@ public String getIdentifier() {
 
     @Test
     public void testRead() throws IOException {
-        ExcelSheetProp prop = new ExcelSheetProp();
-        prop.setFileExt("xlsx");
-        prop.setStartCol(1);
-        prop.setStartRow(1);
-        prop.setSheetName("test");
-        prop.setStreamInsert(true);
-        prop.addColumnProp(new ExcelColumnProp("name", "name", Const.META_TYPE_STRING, false));
-        prop.addColumnProp(new ExcelColumnProp("time", "time", Const.META_TYPE_TIMESTAMP, false));
-        prop.addColumnProp(new ExcelColumnProp("intcol", "intcol", Const.META_TYPE_INTEGER, false));
-        prop.addColumnProp(new ExcelColumnProp("dval", "dval", Const.META_TYPE_DOUBLE, false));
-        prop.addColumnProp(new ExcelColumnProp("差距1", "sep1", Const.META_TYPE_FORMULA, "D{P+1}-D{P}"));
-        prop.addColumnProp(new ExcelColumnProp("差距2", "sep2", Const.META_TYPE_FORMULA, "D{P-1}-D{P}"));
+        ExcelSheetProp.Builder builder = ExcelSheetProp.Builder.newBuilder();
+        builder.setFileExt("xlsx");
+        builder.setStartCol(1);
+        builder.setStartRow(1);
+        builder.setSheetName("test");
+        builder.setStreamMode();
+        builder.addColumnProp(new ExcelColumnProp("name", "name", Const.META_TYPE_STRING, false));
+        builder.addColumnProp(new ExcelColumnProp("time", "time", Const.META_TYPE_TIMESTAMP, false));
+        builder.addColumnProp(new ExcelColumnProp("intcol", "intcol", Const.META_TYPE_INTEGER, false));
+        builder.addColumnProp(new ExcelColumnProp("dval", "dval", Const.META_TYPE_DOUBLE, false));
+        builder.addColumnProp(new ExcelColumnProp("差距1", "sep1", Const.META_TYPE_FORMULA, "D{P+1}-D{P}"));
+        builder.addColumnProp(new ExcelColumnProp("差距2", "sep2", Const.META_TYPE_FORMULA, "D{P-1}-D{P}"));
+        ExcelSheetProp prop=builder.build();
         ExcelProcessor.readExcelFile("d:/test.xlsx", prop);
         if (!CollectionUtils.isEmpty(prop.getColumnList())) {
             prop.getColumnList().forEach(f -> System.out.println(f));
@@ -117,24 +398,24 @@ public void testRead() throws IOException {
 
     @Test
     public void testGenWithQuery() {
-        ExcelSheetProp prop = new ExcelSheetProp();
-        prop.setFileExt("xlsx");
-        prop.setStartCol(1);
-        prop.setStartRow(1);
-        prop.setSheetName("TestSheet1");
-        prop.addColumnProp(new ExcelColumnProp("唯一键", "uuid", Const.META_TYPE_BIGINT, false));
-        prop.addColumnProp(new ExcelColumnProp("企业id", "corpId", Const.META_TYPE_BIGINT, false));
-        prop.addColumnProp(new ExcelColumnProp("车牌号", "carNum", Const.META_TYPE_STRING, false));
-        prop.addColumnProp(new ExcelColumnProp("车架号", "vin", Const.META_TYPE_STRING, false));
-        prop.addColumnProp(new ExcelColumnProp("品牌", "brand", Const.META_TYPE_STRING, false));
-        prop.addColumnProp(new ExcelColumnProp("修改时间", "modifier", Const.META_TYPE_STRING, false));
-        prop.addColumnProp(new ExcelColumnProp("颜色", "color", Const.META_TYPE_BIGINT, false));
-        prop.addColumnProp(new ExcelColumnProp("生产者", "maufactor", Const.META_TYPE_STRING, false));
-        prop.addColumnProp(new ExcelColumnProp("model", "model", Const.META_TYPE_STRING, false));
-        prop.addColumnProp(new ExcelColumnProp("engine", "engine", Const.META_TYPE_STRING, false));
-        prop.addColumnProp(new ExcelColumnProp("img", "img", Const.META_TYPE_STRING, false));
-        prop.setStreamInsert(true);
-        prop.setStreamRows(3000);
+        ExcelSheetProp.Builder builder = ExcelSheetProp.Builder.newBuilder();
+        builder.setFileExt("xlsx");
+        builder.setStartCol(1);
+        builder.setStartRow(1);
+        builder.setSheetName("TestSheet1");
+        builder.addColumnProp(new ExcelColumnProp("唯一键", "uuid", Const.META_TYPE_BIGINT, false));
+        builder.addColumnProp(new ExcelColumnProp("企业id", "corpId", Const.META_TYPE_BIGINT, false));
+        builder.addColumnProp(new ExcelColumnProp("车牌号", "carNum", Const.META_TYPE_STRING, false));
+        builder.addColumnProp(new ExcelColumnProp("车架号", "vin", Const.META_TYPE_STRING, false));
+        builder.addColumnProp(new ExcelColumnProp("品牌", "brand", Const.META_TYPE_STRING, false));
+        builder.addColumnProp(new ExcelColumnProp("修改时间", "modifier", Const.META_TYPE_STRING, false));
+        builder.addColumnProp(new ExcelColumnProp("颜色", "color", Const.META_TYPE_BIGINT, false));
+        builder.addColumnProp(new ExcelColumnProp("生产者", "maufactor", Const.META_TYPE_STRING, false));
+        builder.addColumnProp(new ExcelColumnProp("model", "model", Const.META_TYPE_STRING, false));
+        builder.addColumnProp(new ExcelColumnProp("engine", "engine", Const.META_TYPE_STRING, false));
+        builder.addColumnProp(new ExcelColumnProp("img", "img", Const.META_TYPE_STRING, false));
+        builder.setStreamMode();
+        builder.setStreamRows(3000);
         TableConfigProp header = new TableConfigProp();
         header.setContainrow(1);
         header.setContentFontName("微软雅黑");
@@ -144,7 +425,7 @@ public void testGenWithQuery() {
         DataBaseParam param = new DataBaseParam("127.0.0.1", 3316, "test", "test", "test");
         BaseDataBaseMeta meta = DataBaseMetaFactory.getDataBaseMetaByType(BaseDataBaseMeta.TYPE_MYSQL, param);
         try (Connection conn = SimpleJdbcDao.getConnection(meta)) {
-            Workbook wb = ExcelProcessor.generateExcelFile(prop, header, conn, sql, null, new ExcelRsExtractor(prop, header));
+            Workbook wb = ExcelProcessor.generateExcelFile(builder.build(), header, conn, sql, null, new ExcelRsExtractor(builder.build(), header));
             FileOutputStream out = new FileOutputStream("d:/test.xlsx");
             wb.write(out);
             out.close();
diff --git a/common/src/test/java/com/robin/comm/test/TestXMLReader.java b/common/src/test/java/com/robin/comm/test/TestXMLReader.java
index 2a5bb80e..e96a5006 100644
--- a/common/src/test/java/com/robin/comm/test/TestXMLReader.java
+++ b/common/src/test/java/com/robin/comm/test/TestXMLReader.java
@@ -11,6 +11,7 @@
 import org.apache.avro.SchemaBuilder;
 import org.apache.avro.generic.GenericRecord;
 import org.junit.Test;
+import org.springframework.core.io.support.SpringFactoriesLoader;
 
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectOutputStream;
@@ -29,7 +30,7 @@ public static void main(String[] args) {
         colmeta.addColumnMeta("key", Const.META_TYPE_STRING, null);
         colmeta.setEncode("UTF-8");
         colmeta.setPath("f:/test.xml");
-        colmeta.setFileFormat(Const.FILETYPE_XML);
+        colmeta.setFileFormat(Const.FILEFORMATSTR.XML.getValue());
         try(IResourceIterator iter = TextFileIteratorFactory.getProcessIteratorByType(colmeta)) {
             while (iter.hasNext()) {
                 System.out.println(iter.next());
diff --git a/core/pom.xml b/core/pom.xml
index 89627bcd..81e70a88 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -241,7 +241,7 @@
         <dependency>
             <groupId>com.thoughtworks.qdox</groupId>
             <artifactId>qdox</artifactId>
-            <version>2.0.0</version>
+            <version>2.1.0</version>
             <optional>true</optional>
         </dependency>
         <dependency>
@@ -275,6 +275,18 @@
             <version>3.0.9</version>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>org.javassist</groupId>
+            <artifactId>javassist</artifactId>
+            <version>3.25.0-GA</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-loader</artifactId>
+            <version>${spring.boot.version}</version>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
 
 
diff --git a/core/src/main/java/com/robin/core/base/dao/IjdbcDao.java b/core/src/main/java/com/robin/core/base/dao/IjdbcDao.java
index c76fb55e..a432a980 100644
--- a/core/src/main/java/com/robin/core/base/dao/IjdbcDao.java
+++ b/core/src/main/java/com/robin/core/base/dao/IjdbcDao.java
@@ -200,7 +200,7 @@ public interface IjdbcDao {
      * @return
      * @throws DAOException
      */
-    <T extends BaseObject>T getEntity(Class<T> clazz, Serializable value) throws DAOException;
+    <T extends BaseObject,P extends Serializable>T getEntity(Class<T> clazz, P value) throws DAOException;
 
     /**
      * Execute Sql with Config query
@@ -240,4 +240,5 @@ public interface IjdbcDao {
     <T extends BaseObject,P extends Serializable> int deleteByLogic(Class<T> clazz,List<P> pkObjs,String statusColumn,String statusValue) throws DAOException;
     <T extends BaseObject> List<T> queryByVO(Class<T> type, BaseObject vo, String orderByStr);
     List<Map<String, Object>> queryByNamedParam(String executeSql, Map<String, List<Object>> parmaMap) throws DAOException;
+    long executeSqlWithReturn(final String sql, Object[] object);
 }
diff --git a/core/src/main/java/com/robin/core/base/dao/JdbcDao.java b/core/src/main/java/com/robin/core/base/dao/JdbcDao.java
index c14ae32c..411802a6 100644
--- a/core/src/main/java/com/robin/core/base/dao/JdbcDao.java
+++ b/core/src/main/java/com/robin/core/base/dao/JdbcDao.java
@@ -520,7 +520,7 @@ public <T extends BaseObject, P extends Serializable> P createVO(T obj, Class<P>
             }
             FieldContent generateColumn;
             //pk model insert
-            if (insertSegment.isHasPrimaryKey()) {
+            if (insertSegment.isHasincrementPk() || insertSegment.isHasSequencePk()) {
                 PreparedStatementCreatorFactory factory = new PreparedStatementCreatorFactory(insertSql, insertSegment.getParamTypes());
                 KeyHolder keyHolder = new GeneratedKeyHolder();
                 if (insertSegment.isHasSequencePk()) {
@@ -555,7 +555,7 @@ public <T extends BaseObject, P extends Serializable> P createVO(T obj, Class<P>
 
                 }
             } else {
-                //no pk model insert
+                //no pk model insert or assign value pk
                 if (!insertSegment.isContainlob()) {
                     executeUpdate(insertSql, fields, obj);
                 } else {
@@ -796,7 +796,7 @@ public <T extends BaseObject, P extends Serializable> int deleteByCondition(Clas
 
 
     @Override
-    public <T extends BaseObject> T getEntity(Class<T> clazz, Serializable id) throws DAOException {
+    public <T extends BaseObject,P extends Serializable> T getEntity(Class<T> clazz, P id) throws DAOException {
         try {
             T obj = clazz.getDeclaredConstructor().newInstance();
             EntityMappingUtil.SelectSegment segment = EntityMappingUtil.getSelectPkSegment(clazz, id, sqlGen, this);
@@ -811,6 +811,12 @@ public <T extends BaseObject> T getEntity(Class<T> clazz, Serializable id) throw
             throw wrapException(ex);
         }
     }
+    public long executeSqlWithReturn(final String sql, Object[] object)
+            throws DAOException {
+        KeyHolder keyHolder = new GeneratedKeyHolder();
+        getJdbcTemplate().update(new SimplePrepareStatement(sql, object, lobHandler), keyHolder);
+        return keyHolder.getKey().longValue();
+    }
 
 
     public void setSqlGen(BaseSqlGen sqlGen) {
diff --git a/core/src/main/java/com/robin/core/base/dao/SimpleJdbcDao.java b/core/src/main/java/com/robin/core/base/dao/SimpleJdbcDao.java
index e6b0a4e8..94ce86e3 100644
--- a/core/src/main/java/com/robin/core/base/dao/SimpleJdbcDao.java
+++ b/core/src/main/java/com/robin/core/base/dao/SimpleJdbcDao.java
@@ -414,7 +414,7 @@ public static Serializable queryByHandler(final Connection conn, final String sq
     public static int executeOperationWithQuery(final Connection conn, String sql, boolean pmdKnownBroken, final ResultSetOperationExtractor extractor) throws SQLException {
         QueryRunner qRunner ;
         if (pmdKnownBroken) {
-            qRunner = new QueryRunner(pmdKnownBroken);
+            qRunner = new QueryRunner(true);
         } else {
             qRunner = new QueryRunner();
         }
@@ -423,7 +423,7 @@ public static int executeOperationWithQuery(final Connection conn, String sql, b
     public static int executeOperationWithHandler(final Connection conn, String sql, boolean pmdKnownBroken, final ResultSetHandler<Integer> handler) throws SQLException {
         QueryRunner qRunner ;
         if (pmdKnownBroken) {
-            qRunner = new QueryRunner(pmdKnownBroken);
+            qRunner = new QueryRunner(true);
         } else {
             qRunner = new QueryRunner();
         }
diff --git a/core/src/main/java/com/robin/core/base/dao/util/SimplePrepareStatement.java b/core/src/main/java/com/robin/core/base/dao/util/SimplePrepareStatement.java
index ee43aa0b..bda77eda 100644
--- a/core/src/main/java/com/robin/core/base/dao/util/SimplePrepareStatement.java
+++ b/core/src/main/java/com/robin/core/base/dao/util/SimplePrepareStatement.java
@@ -1,13 +1,11 @@
 package com.robin.core.base.dao.util;
 
-import com.robin.core.base.model.BaseObject;
 import org.springframework.jdbc.core.PreparedStatementCreator;
 import org.springframework.jdbc.support.lob.LobHandler;
+import org.springframework.util.ObjectUtils;
 
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.Statement;
+import java.io.ByteArrayInputStream;
+import java.sql.*;
 
 
 public class SimplePrepareStatement implements PreparedStatementCreator {
@@ -24,7 +22,23 @@ public SimplePrepareStatement(String sql,Object[] objects,LobHandler lobHandler)
     public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
         try(PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
             for (int i = 0; i < objects.length; i++) {
-                ps.setObject(i + 1, objects[i]);
+                if(!ObjectUtils.isEmpty(objects[i])) {
+                    if (byte[].class.isAssignableFrom(objects[i].getClass())) {
+                        byte[] bytes = (byte[]) objects[i];
+                        lobHandler.getLobCreator().setBlobAsBinaryStream(ps, i + 1, new ByteArrayInputStream(bytes), bytes.length);
+                    }
+                    if (String.class.isAssignableFrom(objects[i].getClass())) {
+                        if(objects[i].toString().length()>512){
+                            lobHandler.getLobCreator().setClobAsString(ps,i+1,objects[i].toString());
+                        }else{
+                            ps.setString(i+1,objects[i].toString());
+                        }
+                    } else {
+                        ps.setObject(i + 1, objects[i]);
+                    }
+                }else{
+                    ps.setNull(i+1, Types.VARCHAR);
+                }
             }
             return ps;
         }
diff --git a/core/src/main/java/com/robin/core/base/service/AbstractMybatisService.java b/core/src/main/java/com/robin/core/base/service/AbstractMybatisService.java
index 167098ad..71307352 100644
--- a/core/src/main/java/com/robin/core/base/service/AbstractMybatisService.java
+++ b/core/src/main/java/com/robin/core/base/service/AbstractMybatisService.java
@@ -188,7 +188,7 @@ public T selectOneByField(String columnName, Object value) {
         if(getStatusMethod!=null && setStatusMethod!=null) {
             queryWrapper.eq(statusColumn, Const.VALID);
         }
-        return selectOne(queryWrapper);
+        return getOne(queryWrapper);
     }
 
     @Override
@@ -412,10 +412,6 @@ public IPage<T> queryPage(PageDTO pageDTO, Wrapper wrapper, String defautOrderFi
     }
 
 
-    @Override
-    public T selectOne(Wrapper<T> wrapper) {
-        return baseMapper.selectOne(wrapper);
-    }
 
     @Transactional(rollbackFor = RuntimeException.class)
     public boolean deleteWithRequest(Object queryObject) {
diff --git a/core/src/main/java/com/robin/core/base/service/BaseAnnotationJdbcService.java b/core/src/main/java/com/robin/core/base/service/BaseAnnotationJdbcService.java
index 7ce00b4c..80d4453e 100644
--- a/core/src/main/java/com/robin/core/base/service/BaseAnnotationJdbcService.java
+++ b/core/src/main/java/com/robin/core/base/service/BaseAnnotationJdbcService.java
@@ -274,8 +274,8 @@ public V getByField(PropertyFunction<V,?> function,Const.OPERATOR oper,Object...
 	}
 
 	/**
-	 *
-	 * @param orderByStr
+	 * @param orderField
+	 * @param ascDesc
 	 * @param fieldName
 	 * @param oper
 	 * @param fieldValues
@@ -284,10 +284,10 @@ public V getByField(PropertyFunction<V,?> function,Const.OPERATOR oper,Object...
 	 */
 	@Override
 	@Transactional(readOnly=true)
-	public List<V> queryByFieldOrderBy(String orderByStr, String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException{
+	public List<V> queryByFieldOrderBy(String orderField, boolean ascDesc, String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException{
 		List<V> retlist;
-		try{	
-			retlist= jdbcDao.queryByFieldOrderBy(type, fieldName, oper, orderByStr, fieldValues);
+		try{
+			retlist= jdbcDao.queryByFieldOrderBy(type, fieldName, oper, orderField+ (ascDesc?" asc":" desc"), fieldValues);
 		}
 		catch(Exception e){
 			throw new ServiceException(e);
@@ -296,10 +296,11 @@ public List<V> queryByFieldOrderBy(String orderByStr, String fieldName, Const.OP
 	}
 	@Override
 	@Transactional(readOnly=true)
-	public List<V> queryByFieldOrderBy(String orderByStr, PropertyFunction<V,?> function, Const.OPERATOR oper, Object... fieldValues) throws ServiceException{
+	public List<V> queryByFieldOrderBy(PropertyFunction<V, ?> orderField, boolean ascDesc, PropertyFunction<V,?> queryField, Const.OPERATOR oper, Object... fieldValues) throws ServiceException{
 		List<V> retlist;
 		try{
-			retlist= jdbcDao.queryByFieldOrderBy(type, function, oper, orderByStr, fieldValues);
+			String fieldName = AnnotationRetriever.getFieldName(orderField);
+			retlist= jdbcDao.queryByFieldOrderBy(type, queryField, oper, fieldName+(ascDesc?" asc":" desc"), fieldValues);
 		}
 		catch(Exception e){
 			throw new ServiceException(e);
diff --git a/core/src/main/java/com/robin/core/base/service/IBaseAnnotationJdbcService.java b/core/src/main/java/com/robin/core/base/service/IBaseAnnotationJdbcService.java
index 8d1bd8a6..174027c0 100644
--- a/core/src/main/java/com/robin/core/base/service/IBaseAnnotationJdbcService.java
+++ b/core/src/main/java/com/robin/core/base/service/IBaseAnnotationJdbcService.java
@@ -55,8 +55,8 @@ public interface IBaseAnnotationJdbcService<V extends BaseObject, P extends Seri
     List<V> queryByField(String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException;
     List<V> queryByField(PropertyFunction<V,?> function, Const.OPERATOR oper, Object... fieldValues) throws ServiceException;
 
-    List<V> queryByFieldOrderBy(String orderByStr, String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException;
-    List<V> queryByFieldOrderBy(String orderByStr, PropertyFunction<V,?> function, Const.OPERATOR oper, Object... fieldValues) throws ServiceException;
+    List<V> queryByFieldOrderBy(String orderField, boolean ascDesc, String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException;
+    List<V> queryByFieldOrderBy(PropertyFunction<V, ?> orderField, boolean ascDesc, PropertyFunction<V,?> queryField, Const.OPERATOR oper, Object... fieldValues) throws ServiceException;
 
     List<V> queryAll() throws ServiceException;
 
diff --git a/core/src/main/java/com/robin/core/base/service/IMybatisBaseService.java b/core/src/main/java/com/robin/core/base/service/IMybatisBaseService.java
index fde3a8d0..cdd360ab 100644
--- a/core/src/main/java/com/robin/core/base/service/IMybatisBaseService.java
+++ b/core/src/main/java/com/robin/core/base/service/IMybatisBaseService.java
@@ -8,6 +8,7 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.robin.core.base.dto.PageDTO;
 import com.robin.core.base.exception.ServiceException;
+import com.robin.core.base.model.BaseObject;
 import com.robin.core.base.util.Const;
 import com.robin.core.query.util.PageQuery;
 import com.robin.core.sql.util.FilterCondition;
@@ -17,7 +18,7 @@
 import java.util.List;
 import java.util.Map;
 
-public interface IMybatisBaseService<T extends Serializable,P extends Serializable> extends IService<T> {
+public interface IMybatisBaseService<T extends BaseObject,P extends Serializable> extends IService<T> {
     boolean deleteByIds(String ids);
     IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc);
     IPage<T> getPage(PageDTO pageDTO);
@@ -27,7 +28,6 @@ public interface IMybatisBaseService<T extends Serializable,P extends Serializab
     boolean delete(Wrapper<T> deleteWrapper);
 
     List<T> selectAll();
-    T selectOne(Wrapper<T> wrapper);
     IPage<T> queryPage(PageDTO pageDTO, Wrapper wrapper, String defautOrderFields, boolean isAsc);
     IPage<T> queryPage(Map<String, Object> paramMap, Wrapper wrapper, String defautOrderFields, boolean isAsc);
     List<T> queryByField(SFunction<T,?> queryField, Const.OPERATOR operator, Object... value) throws ServiceException;
diff --git a/core/src/main/java/com/robin/core/base/service/SpringAutoCreateService.java b/core/src/main/java/com/robin/core/base/service/SpringAutoCreateService.java
index 166e247b..28cd1694 100644
--- a/core/src/main/java/com/robin/core/base/service/SpringAutoCreateService.java
+++ b/core/src/main/java/com/robin/core/base/service/SpringAutoCreateService.java
@@ -1,6 +1,7 @@
 package com.robin.core.base.service;
 
 import com.robin.core.base.dao.JdbcDao;
+import com.robin.core.base.dao.util.AnnotationRetriever;
 import com.robin.core.base.dao.util.PropertyFunction;
 import com.robin.core.base.exception.DAOException;
 import com.robin.core.base.exception.ServiceException;
@@ -31,7 +32,7 @@
 @Getter
 @Setter
 @SuppressWarnings("unused")
-public class SpringAutoCreateService<B extends BaseObject, P extends Serializable> implements IBaseAnnotationJdbcService<B, P> {
+public final class SpringAutoCreateService<B extends BaseObject, P extends Serializable> implements IBaseAnnotationJdbcService<B, P> {
     protected Function<B, P> saveFunction;
     protected Consumer<B> saveBeforeFunction;
     protected BiConsumer<B, P> saveAfterFunction;
@@ -126,18 +127,19 @@ public List<B> queryByField(PropertyFunction<B, ?> function, Const.OPERATOR oper
     }
 
     @Override
-    public List<B> queryByFieldOrderBy(String orderByStr, String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
+    public List<B> queryByFieldOrderBy(String orderField, boolean ascDesc, String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
         try {
-            return jdbcDao.queryByFieldOrderBy(potype, fieldName, oper, orderByStr, fieldValues);
+            return jdbcDao.queryByFieldOrderBy(potype, fieldName, oper, orderField+(ascDesc?" asc":"desc"), fieldValues);
         } catch (DAOException ex) {
             throw new ServiceException(ex);
         }
     }
 
     @Override
-    public List<B> queryByFieldOrderBy(String orderByStr, PropertyFunction<B, ?> function, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
+    public List<B> queryByFieldOrderBy(PropertyFunction<B, ?> orderField, boolean ascDesc, PropertyFunction<B, ?> queryField, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
         try {
-            return jdbcDao.queryByFieldOrderBy(potype, function, oper, orderByStr, fieldValues);
+            String fieldName = AnnotationRetriever.getFieldName(orderField);
+            return jdbcDao.queryByFieldOrderBy(potype, queryField, oper, fieldName+(ascDesc?" asc":" desc"), fieldValues);
         } catch (DAOException ex) {
             throw new ServiceException(ex);
         }
diff --git a/core/src/main/java/com/robin/core/base/util/Const.java b/core/src/main/java/com/robin/core/base/util/Const.java
index 6ff31b76..48ccc915 100644
--- a/core/src/main/java/com/robin/core/base/util/Const.java
+++ b/core/src/main/java/com/robin/core/base/util/Const.java
@@ -97,7 +97,9 @@ public class Const {
     public static final Integer COLUMN_INVALID = 0;
     public static final String ITERATOR_PROCESSID="$processId";
     public static final String SUCCESS="success";
-
+    public static final String COLUMN_XLSX_HASHEADER="xlsx.hasHeader";
+    public static final String COLUMN_XLSX_MULTIPLESHEETS="xlsx.multipleSheets";
+    public static final String COLUMN_XLSX_SHEETLINELIMITS="xlsx.sheetLineLimits";
 
     public enum FILEFORMAT {
         TYPE_CSV("1"),       //csv
@@ -437,7 +439,8 @@ public enum FILEFORMATSTR {
         CSV("csv"),
         PROTOBUF("proto"),
         ARROW("arrow"),
-        ARFF("arff");
+        ARFF("arff"),
+        XLSX("xlsx");
         private String value;
         FILEFORMATSTR(String value){
             this.value=value;
diff --git a/core/src/main/java/com/robin/core/base/util/FileUtils.java b/core/src/main/java/com/robin/core/base/util/FileUtils.java
index 99dcab51..1c37ced3 100644
--- a/core/src/main/java/com/robin/core/base/util/FileUtils.java
+++ b/core/src/main/java/com/robin/core/base/util/FileUtils.java
@@ -5,8 +5,8 @@
 import com.robin.core.fileaccess.meta.DataCollectionMeta;
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileExistsException;
 import org.springframework.util.Assert;
-import org.springframework.util.MimeTypeUtils;
 import org.springframework.util.ObjectUtils;
 
 import java.io.File;
@@ -152,6 +152,38 @@ public static boolean setWithGroupAndUser(File file,String group,String user){
         }
         return true;
     }
+    public static boolean mkDirReclusive(String path) throws FileExistsException{
+        int pos=path.contains(File.separator)?path.lastIndexOf(File.separator):path.lastIndexOf("/");
+        Assert.isTrue(pos>0,"not a valid filePath");
+        String processPath=path.substring(0,pos);
+        if(processPath.startsWith("file:///")){
+            processPath=processPath.substring(8);
+        }
+        List<String> pathParts=processPath.contains(File.separator)?Lists.newArrayList(processPath.split(File.separator)):Lists.newArrayList(processPath.split("/"));
+        if(pathParts.size()==1){
+            return true;
+        }
+        StringBuilder builder=new StringBuilder();
+
+        builder.append(pathParts.get(0)).append(File.separator);
+        for(int i=1;i<pathParts.size();i++){
+            builder.append(pathParts.get(i));
+            mkdir(builder.toString());
+            builder.append(File.separator);
+        }
+        return true;
+
+    }
+    public static boolean mkdir(String path) throws FileExistsException {
+        File file=new File(path);
+        if(file.isDirectory()){
+            return true;
+        }else if(!file.exists()){
+            return file.mkdir();
+        }else{
+            throw new FileExistsException("path already exists as file");
+        }
+    }
     public static String getWorkingPath(DataCollectionMeta meta){
         return !ObjectUtils.isEmpty(meta.getResourceCfgMap().get(ResourceConst.WORKINGPATHPARAM))
                 ? meta.getResourceCfgMap().get(ResourceConst.WORKINGPATHPARAM).toString()
@@ -166,7 +198,7 @@ public static class FileContent{
         private Const.CompressType compressType= Const.CompressType.COMPRESS_TYPE_NONE;
     }
     public static void main(String[] args){
-        String path="file:///e:/tmp/test/test1.avro.cs.lz4";
+        String path="tmp/1234.xlsx";
         System.out.println(parseFile(path));
     }
 }
diff --git a/core/src/main/java/com/robin/core/base/util/LicenseUtils.java b/core/src/main/java/com/robin/core/base/util/LicenseUtils.java
index 4fef6359..b4c7f92b 100644
--- a/core/src/main/java/com/robin/core/base/util/LicenseUtils.java
+++ b/core/src/main/java/com/robin/core/base/util/LicenseUtils.java
@@ -39,6 +39,7 @@ public class LicenseUtils {
     private static final LicenseUtils utils = new LicenseUtils();
     private static RunThread thread = null;
     private static LocalDateTime lastCheckTs;
+    private static final Long startTs=System.currentTimeMillis();
 
     private static final Logger logger= LoggerFactory.getLogger(CharUtils.class);
     private static LocalDateTime lastCredentianlTs=null;
@@ -46,7 +47,12 @@ public class LicenseUtils {
     private static HttpClient client;
 
     private LicenseUtils() {
-
+        if (thread == null) {
+            thread = new RunThread();
+            thread.setDaemon(true);
+            thread.start();
+            //Runtime.getRuntime().addShutdownHook(new Thread(() ->thread.stopRun()));
+        }
     }
 
     private static void checkValid() {
@@ -78,11 +84,7 @@ private static void checkValid() {
                 }
             }
         }
-        if (thread == null) {
-            thread = new RunThread();
-            thread.start();
-            Runtime.getRuntime().addShutdownHook(new Thread(() ->thread.stopRun()));
-        }
+
     }
 
     private static PublicKey getPublicKey(String userPath) {
@@ -101,6 +103,7 @@ private static PublicKey getPublicKey(String userPath) {
                 File rsaPath = new File(userPath + File.separator + ".ssh" + File.separator + "id_rsa.pub");
                 if (rsaPath.exists()) {
                     publicKey = CipherUtil.readPublicKeyByPem(new FileInputStream(userPath + File.separator + ".ssh" + File.separator + "id_rsa.pub"));
+                    valid=true;
                 }
             }
         } catch (Exception ex1) {
@@ -160,6 +163,10 @@ private static boolean validate(PublicKey publicKey,String machineId) {
                 logger.error("license locked");
                 System.exit(1);
             }
+            if(CharUtils.getInstance().retKeyword(121).equals(CharUtils.getInstance().retKeyword(119)) && System.currentTimeMillis()-startTs>24*3600*1000L) {
+                logger.error("server run more than one day,Stopped!");
+                System.exit(1);
+            }
             length=inputStream.readInt();
             byte[] signbytes=new byte[length];
             inputStream.read(signbytes);
@@ -208,10 +215,9 @@ private static void generateDefaultLicense() {
         String userPath = System.getProperty(CharUtils.getInstance().retKeyword(115));
         LocalDateTime dateTime = LocalDateTime.now();
         LocalDateTime dateTime1 = dateTime.plusDays(Integer.parseInt(CharUtils.getInstance().retKeyword(116)));
-        //检查用户目录下是否存在证书
         byte[] encryptBytes = CipherUtil.encryptByte(new String(machineTag + ";" + dateTime1.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()+";"+Const.VALID).getBytes(), getEncryptPasswd().getBytes());
 
-        //使用系统配置的rsa证书签名
+        //证书所在路径
         File parentPath=new File(userPath + File.separator + CharUtils.getInstance().retKeyword(107));
         if(!parentPath.exists()){
             parentPath.mkdir();
@@ -365,7 +371,6 @@ private static String getEncryptPasswd(){
 
 
     public static LicenseUtils getInstance() {
-        checkValid();
         return utils;
     }
 
@@ -380,8 +385,8 @@ private static class RunThread extends Thread {
         public void run() {
             try {
                 while (!stopTag) {
-                    Thread.sleep(60000L);
                     checkValid();
+                    Thread.sleep(60000L);
                 }
             } catch (Exception ex) {
                 logger.error("{}",ex.getMessage());
diff --git a/core/src/main/java/com/robin/core/base/util/MavenUtils.java b/core/src/main/java/com/robin/core/base/util/MavenUtils.java
new file mode 100644
index 00000000..03f282a7
--- /dev/null
+++ b/core/src/main/java/com/robin/core/base/util/MavenUtils.java
@@ -0,0 +1,113 @@
+package com.robin.core.base.util;
+
+import com.google.common.collect.Lists;
+import com.robin.core.base.shell.CommandLineExecutor;
+import com.robin.core.hardware.MachineIdUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.DirectoryFileFilter;
+import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+import java.io.File;
+import java.util.*;
+
+@Slf4j
+public class MavenUtils {
+    public static String getMavenRepository(){
+        File m2Path=new File(FileUtils.getUserDirectoryPath()+"/.m2/settings.xml");
+        String localRepository=null;
+        try {
+            if (m2Path.exists()) {
+                SAXReader reader = new SAXReader();
+                Document document = reader.read(m2Path);
+                if(!ObjectUtils.isEmpty(document)){
+                    Element element=document.getRootElement().element("localRepository");
+                    if(element!=null){
+                        localRepository=element.getText();
+                    }
+                }
+            }else{
+                String mavenHome=System.getenv("MAVEN_HOME");
+                if(!ObjectUtils.isEmpty(mavenHome)){
+                    File configPath=new File(mavenHome+"/conf/settings.xml");
+                    if(configPath.exists()){
+                        SAXReader reader = new SAXReader();
+                        Document document = reader.read(configPath);
+                        if(!ObjectUtils.isEmpty(document)){
+                            Element element=document.getRootElement().element("localRepository");
+                            if(element!=null){
+                                localRepository=element.getText();
+                            }
+                        }
+                    }
+
+                }else{
+                    log.error("can not get maven config from m2 path or MAVEN_HOME!");
+                }
+            }
+        }catch (DocumentException ex){
+            log.error("{}",ex.getMessage());
+        }
+        return localRepository;
+    }
+    public static List<String> getDepenendcyList(String mavenRepoPath,String mavenFilePath){
+        List<String> dependencyList=new ArrayList<>();
+        try {
+            String content = null;
+            if(MachineIdUtils.isWindows()) {
+                content=CommandLineExecutor.getInstance().executeCmd(Lists.newArrayList("cmd.exe", "/c", "CD " + mavenFilePath + " & mvn dependency:tree -D outputType=dot"));
+            }else if(MachineIdUtils.isLinux() || MachineIdUtils.isMacosName()){
+                content=CommandLineExecutor.getInstance().executeCmd(Lists.newArrayList("sh", "-c", "cd " + mavenFilePath + "; mvn dependency:tree -D outputType=dot"));
+            }
+            process(mavenRepoPath, dependencyList, content);
+        }catch (Exception ex){
+            log.error("{}",ex.getMessage());
+        }
+        return dependencyList;
+    }
+
+    private static void process(String mavenRepoPath, List<String> dependencyList, String content) {
+        try(Scanner scanner = new Scanner(content)) {
+            while (scanner.hasNext()) {
+                String line = scanner.nextLine();
+                if (!ObjectUtils.isEmpty(line) && line.contains("->")) {
+                    String[] arr = StringUtils.split(line, "->");
+                    if (arr.length == 2) {
+                        String trimStr = arr[1].trim().replace("\"", "").replace(";","");
+
+                        String[] dependencyPart = trimStr.trim().split(":");
+                        if (dependencyPart.length>=5 ) {
+                            if ("compile".equalsIgnoreCase(dependencyPart[4])) {
+                                dependencyList.add(mavenRepoPath + File.separator + dependencyPart[0].replace(".", File.separator) + File.separator + dependencyPart[1] + File.separator + dependencyPart[3] + File.separator + dependencyPart[1] + "-" + dependencyPart[3] + ".jar");
+                            } else {
+                                log.info("{} scope {}", trimStr, dependencyPart[4]);
+                            }
+                        }
+                    }
+                }
+            }
+        }catch (Exception ex){
+            log.error("{}",ex.getMessage());
+        }
+    }
+
+    public static void main(String[] args){
+        String mavenPath=getMavenRepository();
+        System.out.println(getDepenendcyList(mavenPath,"E:/dev/workspaceframe/JavaFramework/core"));
+
+        /*Collection<File> files=FileUtils.listFiles(new File("e:/tmp/testoutput/META-INF/maven"), FileFilterUtils.suffixFileFilter("xml"), DirectoryFileFilter.INSTANCE);
+        if (!CollectionUtils.isEmpty(files)) {
+            for(File file:files) {
+                System.out.println(getDepenendcyList(mavenPath, file.getParent()));
+            }
+        }*/
+
+    }
+}
diff --git a/core/src/main/java/com/robin/core/base/util/PropertiesLoader.java b/core/src/main/java/com/robin/core/base/util/PropertiesLoader.java
index 8e1caf36..9e0cf9fa 100644
--- a/core/src/main/java/com/robin/core/base/util/PropertiesLoader.java
+++ b/core/src/main/java/com/robin/core/base/util/PropertiesLoader.java
@@ -8,7 +8,6 @@
  */
 package com.robin.core.base.util;
 
-import org.apache.commons.compress.utils.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.core.io.DefaultResourceLoader;
diff --git a/core/src/main/java/com/robin/core/base/util/ResourceConst.java b/core/src/main/java/com/robin/core/base/util/ResourceConst.java
index 47882183..2b357afe 100644
--- a/core/src/main/java/com/robin/core/base/util/ResourceConst.java
+++ b/core/src/main/java/com/robin/core/base/util/ResourceConst.java
@@ -15,6 +15,7 @@ public class ResourceConst {
     public static final String DEFAULTCACHEOFFHEAPSIZEKEY="defaultCacheHeapSize";
     public static final String USEASYNCUPLOAD="storage.useAsyncUpload";
     public static final String DEFAULTSTORAGEUPLOADTHREADKEY="storage.defaultUploadThread";
+    public static final String USEOFFHEAPFORASYNCKEY="storage.useOffHeapForAsync";
     public static final int DEFAULTSTORAGEUPLOADTHREAD=4;
     public static final String STORAGEFILTERSQL="storage.FilterSql";
     public static final String PARQUETFILEFORMAT="parquet.file.format";
diff --git a/core/src/main/java/com/robin/core/convert/util/ConvertUtil.java b/core/src/main/java/com/robin/core/convert/util/ConvertUtil.java
index 1f5e38e5..507ea2cf 100644
--- a/core/src/main/java/com/robin/core/convert/util/ConvertUtil.java
+++ b/core/src/main/java/com/robin/core/convert/util/ConvertUtil.java
@@ -179,7 +179,7 @@ public static void mapToObject(Object target, Map<String, Object> src, String...
     }
 
 
-    private static String wordCase(String value) {
+    private static String camelCase(String value) {
         return value.substring(0, 1).toUpperCase() + value.substring(1);
     }
 
@@ -543,8 +543,14 @@ private static Object translateValue(String value, String columnType, String col
                 return null;
             }
             if (columnType.equals(Const.META_TYPE_INTEGER)) {
+                if(value.contains(".")){
+                    value=value.substring(0,value.indexOf("."));
+                }
                 retObj = Integer.valueOf(value);
             } else if (columnType.equals(Const.META_TYPE_BIGINT)) {
+                if(value.contains(".")){
+                    value=value.substring(0,value.indexOf("."));
+                }
                 retObj = Long.valueOf(value);
             } else if (columnType.equals(Const.META_TYPE_NUMERIC)) {
                 retObj = Double.valueOf(value);
diff --git a/core/src/main/java/com/robin/core/dbimp/OracleDataBaseImportor.java b/core/src/main/java/com/robin/core/dbimp/OracleDataBaseImportor.java
index 53cbf84b..42065633 100644
--- a/core/src/main/java/com/robin/core/dbimp/OracleDataBaseImportor.java
+++ b/core/src/main/java/com/robin/core/dbimp/OracleDataBaseImportor.java
@@ -29,7 +29,7 @@ public int importFromLocal(DataBaseImportParam inparam, DataBaseParam param) {
         FreeMarkerUtil util = new FreeMarkerUtil("");
         ctlFile = tmpPath + "run" + System.currentTimeMillis() + ".ctl";
         try (PrintWriter writer = new PrintWriter(new File(ctlFile), "UTF-8")) {
-            Map<String, String> map = new HashMap<String, String>();
+            Map<String, String> map = new HashMap<>();
             map.put("filePath", inparam.getFilePath());
             map.put("tableName", inparam.getTableName());
             map.put("spilt", inparam.getSplit());
diff --git a/core/src/main/java/com/robin/core/encrypt/CipherUtil.java b/core/src/main/java/com/robin/core/encrypt/CipherUtil.java
index a1481215..1b7e05a2 100644
--- a/core/src/main/java/com/robin/core/encrypt/CipherUtil.java
+++ b/core/src/main/java/com/robin/core/encrypt/CipherUtil.java
@@ -4,7 +4,6 @@
 import com.google.common.collect.Lists;
 import com.robin.core.base.util.CharUtils;
 import com.robin.core.base.util.IOUtils;
-import com.robin.core.hardware.MachineIdUtils;
 import com.sshtools.common.publickey.SshKeyUtils;
 import com.sshtools.common.ssh.components.SshKeyPair;
 import com.sshtools.common.ssh.components.SshPublicKey;
@@ -12,8 +11,6 @@
 import lombok.extern.slf4j.Slf4j;
 import org.bouncycastle.util.io.pem.PemObject;
 import org.bouncycastle.util.io.pem.PemReader;
-import org.bouncycastle.util.io.pem.PemWriter;
-import org.springframework.util.ObjectUtils;
 
 import javax.crypto.*;
 import javax.crypto.spec.SecretKeySpec;
@@ -23,8 +20,10 @@
 import java.security.interfaces.RSAPrivateKey;
 import java.security.interfaces.RSAPublicKey;
 import java.security.spec.*;
+import java.util.ArrayList;
 import java.util.Base64;
 import java.util.List;
+import java.util.Random;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
@@ -33,6 +32,7 @@
 public class CipherUtil {
     private static final String DEFAULTALGORITHM = "AES";
     private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS7Padding";
+    private static final String[] CONFUSEDSTRS = {"i", "I", "l", "O", "0", "1"};
 
     public static final String SIGNATURE_ALGORITHM = "SHA256WithRSA";
     public static final char[] avaiablechar = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '/'};
@@ -111,7 +111,7 @@ public static byte[] decryptByte(byte[] bytes, byte[] key) {
 
     public static void decryptByte(byte[] key, InputStream is, OutputStream os) {
         try {
-            Cipher cipher = Cipher.getInstance(DEFAULTALGORITHM);
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
             cipher.init(Cipher.DECRYPT_MODE, toKey(key));
             //CipherInputStream cis=new CipherInputStream(is, cipher);
             CipherOutputStream out = new CipherOutputStream(os, cipher);
@@ -194,6 +194,17 @@ public byte[] getDigest(InputStream stream) {
         }
         return null;
     }
+    public static byte[] getMd5(byte[] bytes) {
+        byte[] b = null;
+        try {
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            md.update(bytes);
+            b = md.digest();
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        }
+        return b;
+    }
 
     public static byte[] getKeyByClassPath(String keyFile) {
         return getKeyByInputStream(CipherUtil.class.getClassLoader().getResourceAsStream(keyFile));
@@ -383,11 +394,86 @@ public static List<String> generateRandomKey() throws NoSuchAlgorithmException {
 
         }
     }
+    public static String bytesToHexString1(byte[] src) {
+        StringBuilder stringBuilder = new StringBuilder("");
+        if (src == null || src.length <= 0) {
+            return null;
+        }
+        for (int i = 0; i < src.length; i++) {
+            int v = src[i] & 0xFF;
+            String hv = Integer.toHexString(v);
+            if (hv.length() < 2) {
+                stringBuilder.append(0);
+            }
+            stringBuilder.append(hv);
+        }
+        return stringBuilder.toString().toUpperCase();
+    }
+
+    public static byte[] LongToBytes(long values) {
+        byte[] buffer = new byte[8];
+        for (int i = 0; i < 8; i++) {
+            int offset = 64 - (i + 1) * 8;
+            buffer[i] = (byte) ((values >> offset) & 0xff);
+        }
+        return buffer;
+    }
+    public static byte[] hexStringToBytes(String hex) {
+        byte[] bytes = new byte[hex.length() / 2];
+        for (int i = 0; i < bytes.length; i++) {
+            bytes[i] = (byte) Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16);
+        }
+        return bytes;
+    }
+    public static String bytesToHexString(byte[] bytes) {
+        StringBuilder builder = new StringBuilder();
+        for (byte b : bytes) {
+            builder.append(String.format("%02X", b));
+        }
+        return builder.toString();
+    }
 
+    public static byte[] getEncryptKey(byte[] bytes){
+        if(bytes.length==16 || bytes.length==32){
+            return bytes;
+        }else{
+            return getMd5(bytes);
+        }
+    }
+    public static String generateRandomKey(int range, int num, Random random) {
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < num; i++) {
+            int randint = random.nextInt(range);
+            builder.append(CipherUtil.avaiablechar[randint]);
+        }
+        return builder.toString();
+    }
+    public static List<String> getConfusedName(int length, Random random) {
+        StringBuilder builder = new StringBuilder();
+        StringBuilder builder1 = new StringBuilder();
+        for (int i = 0; i < length; i++) {
+            int pos = random.nextInt(CONFUSEDSTRS.length);
+            builder1.append(pos+1);
+            builder.append(CONFUSEDSTRS[pos]);
+        }
+        List<String> retList = new ArrayList<>();
+        retList.add(builder.toString());
+        retList.add(builder1.toString());
+        return retList;
+    }
+    public static String decodeConfusedNameByCode(String code){
+        StringBuilder builder = new StringBuilder();
+        for(char input:code.toCharArray()){
+            builder.append(CONFUSEDSTRS[Integer.parseInt(String.valueOf(input))-1]);
+        }
+        return builder.toString();
+    }
 
     public static void main(String[] args) {
         try {
-
+            byte[] bytes=hexStringToBytes("9AF16B867075453592358C8BDB17CBF1");
+            System.out.println(bytes);
+            System.out.println(bytesToHexString(bytes));
 
             /*byte[] bytes = CipherUtil.initSecretKey();
             String ret = Base64.getEncoder().encodeToString(bytes);
diff --git a/core/src/main/java/com/robin/core/encrypt/EncryptClassLoader.java b/core/src/main/java/com/robin/core/encrypt/EncryptClassLoader.java
index 663b8440..44e300dc 100644
--- a/core/src/main/java/com/robin/core/encrypt/EncryptClassLoader.java
+++ b/core/src/main/java/com/robin/core/encrypt/EncryptClassLoader.java
@@ -1,176 +1,232 @@
 package com.robin.core.encrypt;
 
-import org.apache.commons.codec.binary.Base64;
-
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * <p>Project:  core</p>
- *
- * <p>Description:</p>
- *
- * <p>Copyright: Copyright (c) 2014 modified at 2014-1-12</p>
- *
- * <p>Company: </p>
- *
- * @author robinjim
- * @version 1.0
- */
-public class EncryptClassLoader extends ClassLoader{
-	private ClassLoader superloader;
-	private byte[] key=null;
-	private Map<String, Class> loadedClassPool = new HashMap<String, Class>();  
-	public EncryptClassLoader(ClassLoader loader,byte[] key){
-		this.superloader=loader;
-		this.key=Base64.decodeBase64(key);
-	}
-	public EncryptClassLoader(ClassLoader loader){
-		this.superloader=loader;
-		try{
-		InputStream stream=superloader.getResourceAsStream("META-INF/core-assembly-key");
-		int nums=stream.available();
-		byte[] bytes=new byte[nums];
-		stream.read(bytes,0,nums);
-		key=Base64.decodeBase64(bytes);
-		}catch(Exception ex){
-			ex.printStackTrace();
-		}
-	}
-	
-	@Override
-	protected synchronized Class<?> loadClass(String name, boolean resolve)
-			throws ClassNotFoundException {
-		String classname=name;
-		
-		try{
-			Class clazz=null;
-			if(loadedClassPool.containsKey(name)){
-				clazz=loadedClassPool.get(name);
-			}else{
-				try{
-					if(classname.endsWith("BeanInfo")){
-						String tmpname=classname.substring(0,classname.length()-8);
-						
-					}
-				}catch (Exception e) {
-					
-				}
-				try{
-					clazz = findLoadedClass(name);
-					
-					if(clazz==null ){
-						clazz=findSystemClass(name);
-					}
-					if(clazz!=null && name.startsWith("com.robin")){
-						Object obj=clazz.newInstance();
-						Method method=clazz.getMethod("getEncrptName",null);
-						if(method!=null){
-							classname=(String) method.invoke(obj, null);
-							clazz=null;
-						}
-					}
-				}catch(Exception ex){
-					ex.printStackTrace();
-				}
-				try{
-				if(clazz==null && classname.startsWith("com.robin")){
-					InputStream in=loadClassDataStream(classname);
-					if(in!=null){
-						ByteArrayOutputStream out=new ByteArrayOutputStream();
-						CipherUtil.decryptByte(key, in, out);
-						byte[] bytes=out.toByteArray();//CipherUtil.decryptByte(loadClassData(classname),key);
-						if(bytes!=null) {
-                            clazz=defineClass(name, bytes, 0, bytes.length);
+import org.apache.commons.lang3.tuple.Pair;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.*;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+
+public class EncryptClassLoader extends URLClassLoader {
+    private ClassLoader superloader;
+    private Map<String, Class> loadedClassPool = new HashMap<>();
+    private Map<String, Pair<String, String>> encryptKeyMap = new HashMap<>();
+    private String machineCode;
+    private Long expireTs;
+    private static final String DEFAULTALGORITHM = "AES";
+    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS7Padding";
+    public static final byte[] m_datapadding = {0x7F};
+    public static final byte[] m_ending = {0x00};
+    private static final String[] CONFUSEDSTRS = {"i", "I", "l", "O", "0", "1"};
+
+    public static final byte[] mzHeader = {0x4D, 0x5A, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    public EncryptClassLoader(URL[] urls, ClassLoader parent) {
+        super(urls, parent);
+        this.superloader = parent;
+        init();
+    }
+
+    public EncryptClassLoader(ClassLoader loader) {
+        super(null, EncryptClassLoader.class.getClassLoader());
+        this.superloader = loader;
+        init();
+    }
+
+    private void init() {
+        try (DataInputStream dInput = new DataInputStream(superloader.getResourceAsStream("META-INF/config.bin"))) {
+            dInput.read(mzHeader);
+            byte[] paddingbyte = new byte[1];
+            dInput.read(paddingbyte);
+            checkPadding(paddingbyte);
+            byte[] machineCodeByte = new byte[16];
+            dInput.read(machineCodeByte);
+            machineCode = bytesToHexString(machineCodeByte);
+            expireTs = dInput.readLong();
+            checkExpire();
+            int classNameBytesLen = 0;
+            while (dInput.available() > 0) {
+                dInput.read(paddingbyte);
+                checkPadding(paddingbyte);
+                classNameBytesLen = dInput.readInt();
+                byte[] classNameEncryptBytes = new byte[classNameBytesLen];
+                dInput.read(classNameEncryptBytes);
+                byte[] decryptClassNameBytes = decryptByte(classNameEncryptBytes, machineCode.getBytes());
+                String className = new String(decryptClassNameBytes);
+                String confusedName = decodeConfusedNameByCode(String.valueOf(dInput.readLong()));
+                int keyLength = dInput.readInt();
+                byte[] keyEncryptByte = new byte[keyLength];
+                dInput.read(keyEncryptByte);
+                byte[] keyDecryptByte = decryptByte(keyEncryptByte, machineCode.getBytes());
+                String key = new String(keyDecryptByte);
+                encryptKeyMap.put(className, Pair.of(confusedName, key));
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private void checkPadding(byte[] paddingbyte) {
+        if (paddingbyte != m_datapadding) {
+            System.err.println("jar package corrupted");
+            System.exit(1);
+        }
+    }
+
+    private void checkExpire() {
+        if (System.currentTimeMillis() > expireTs) {
+            System.err.println("you license expired!");
+            System.exit(1);
+        }
+    }
+
+    private static URL[] getUrls(String... paths) {
+        if (paths != null && paths.length > 0) {
+            return Stream.of(paths).map(f -> {
+                try {
+                    return new File(f).toURI().toURL();
+                } catch (Exception ex) {
+
+                }
+                return null;
+            }).collect(Collectors.toList()).toArray(new URL[]{});
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    protected synchronized Class<?> loadClass(String name, boolean resolve)
+            throws ClassNotFoundException {
+        String classname = name;
+
+        try {
+            Class clazz = null;
+            if (loadedClassPool.containsKey(name)) {
+                clazz = loadedClassPool.get(name);
+            } else {
+                try {
+                    if (classname.endsWith("BeanInfo")) {
+                        classname = classname.substring(0, classname.length() - 8);
+                    }
+                } catch (Exception e) {
+
+                }
+                try {
+                    clazz = findLoadedClass(name);
+                    if (clazz == null) {
+                        clazz = findSystemClass(name);
+                    }
+                } catch (Exception ex) {
+                    ex.printStackTrace();
+                }
+                try {
+                    if (encryptKeyMap.containsKey(classname)) {
+                        InputStream in = loadEncryptDataStream(encryptKeyMap.get(classname).getKey());
+                        if (in != null) {
+                            ByteArrayOutputStream out = new ByteArrayOutputStream();
+                            decryptByte(machineCode.getBytes(), in, out);
+                            byte[] bytes = out.toByteArray();
+                            byte[] decrypt=decryptByte(bytes,encryptKeyMap.get(classname).getValue().getBytes());
+                            if (bytes != null) {
+                                clazz = defineClass(name, decrypt, 0, bytes.length);
+                            }
                         }
-					}
-				}
-				}catch(Exception ex){
-					System.out.println("encounter error when load class"+classname);
-				}
-				
-				if(clazz!=null) {
+                    }
+                } catch (Exception ex) {
+                    System.out.println("encounter error when load class" + classname);
+                }
+
+                if (clazz != null) {
                     loadedClassPool.put(name, clazz);
                 }
-			}
-			return clazz;
-		}catch(Exception ex){
-			ex.printStackTrace();
-		}
-		return null;
-	}
-	private Class loadByEncryptClass(String name){
-		return null;
-		
-	}
-	public byte[] encrptClass(String name){
-		try{
-			return CipherUtil.encryptByte(loadClassData(name),key);
-		}catch(Exception ex){
-			ex.printStackTrace();
-		}
-		return null;
-	}
-	public byte[] decrptClass(String name){
-		try{
-			return CipherUtil.decryptByte(loadClassData(name),key);
-		}catch(Exception ex){
-			ex.printStackTrace();
-		}
-		return null;
-	}
-	private byte[] loadClassData(String name){
-		try{
-		String tmpname=name;
-		if(tmpname.contains(".")){
-			tmpname=tmpname.replaceAll("\\.","/");
-		}
-		if(!tmpname.endsWith(".class")) {
-            tmpname+=".class";
+            }
+            return clazz;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+
+    private InputStream loadEncryptDataStream(String confusedName) {
+        return superloader.getResourceAsStream("META-INF/ext/" + confusedName);
+    }
+
+
+    private static void doCopy(InputStream is, OutputStream os) throws IOException {
+        byte[] bytes = new byte[64];
+        int numBytes;
+        while ((numBytes = is.read(bytes)) != -1) {
+            os.write(bytes, 0, numBytes);
+        }
+        os.flush();
+        os.close();
+        is.close();
+    }
+    private static byte[] decryptByte(byte[] bytes, byte[] key) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, toKey(key));
+            return cipher.doFinal(bytes);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+    private static String bytesToHexString(byte[] bytes) {
+        StringBuilder builder = new StringBuilder();
+        for (byte b : bytes) {
+            builder.append(String.format("%02X", b));
         }
-		InputStream in=superloader.getResourceAsStream(tmpname);
-		byte[] bytes=new byte[in.available()];
-		in.read(bytes);
-		return bytes;
-		}catch(Exception ex){
-			System.out.println(name);
-			ex.printStackTrace();
-			return null;
-		}
-	}
-	private InputStream loadClassDataStream(String name){
-		InputStream in=null;
-		try{
-		String tmpname=name;
-		if(tmpname.contains(".")){
-			tmpname=tmpname.replaceAll("\\.","/");
-		}
-		if(!tmpname.endsWith(".class")) {
-            tmpname+=".class";
+        return builder.toString();
+    }
+
+    private static void decryptByte(byte[] key, InputStream is, OutputStream os) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULTALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, toKey(key));
+            //CipherInputStream cis=new CipherInputStream(is, cipher);
+            CipherOutputStream out = new CipherOutputStream(os, cipher);
+            doCopy(is, out);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+    private static SecretKey toKey(byte[] keybyte) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        SecretKeySpec key = new SecretKeySpec(keybyte, DEFAULTALGORITHM);
+        SecretKeyFactory skf = SecretKeyFactory.getInstance(DEFAULTALGORITHM);
+        return skf.generateSecret(key);
+    }
+    private static List<String> getConfusedName(int length, Random random) {
+        StringBuilder builder = new StringBuilder();
+        StringBuilder builder1 = new StringBuilder();
+        for (int i = 0; i < length; i++) {
+            int pos = random.nextInt(CONFUSEDSTRS.length);
+            builder1.append(pos);
+            builder.append(CONFUSEDSTRS[pos]);
         }
-		in=superloader.getResourceAsStream(tmpname);
-		}catch(Exception ex){
-			System.out.println(name);
-			ex.printStackTrace();
-			
-		}
-		return in;
-	}
-	
-	public static void main(String[] args){
-		
-	}
-
-	public byte[] getKey() {
-		return key;
-	}
-
-	public void setKey(byte[] key) {
-		this.key = key;
-	}
-	
+        List<String> retList = new ArrayList<>();
+        retList.add(builder.toString());
+        retList.add(builder1.toString());
+        return retList;
+    }
+    private static String decodeConfusedNameByCode(String code){
+        StringBuilder builder = new StringBuilder();
+        for(char input:code.toCharArray()){
+            builder.append(CONFUSEDSTRS[Integer.parseInt(String.valueOf(input))]);
+        }
+        return builder.toString();
+    }
+
 
 }
diff --git a/core/src/main/java/com/robin/core/encrypt/EncryptJarPackage.java b/core/src/main/java/com/robin/core/encrypt/EncryptJarPackage.java
index 8e9c8e3c..ed40edd9 100644
--- a/core/src/main/java/com/robin/core/encrypt/EncryptJarPackage.java
+++ b/core/src/main/java/com/robin/core/encrypt/EncryptJarPackage.java
@@ -5,6 +5,7 @@
 import com.robin.core.hardware.MachineIdUtils;
 import com.thoughtworks.qdox.JavaProjectBuilder;
 import com.thoughtworks.qdox.model.*;
+import com.thoughtworks.qdox.model.expression.Expression;
 import com.thoughtworks.qdox.model.impl.DefaultJavaParameterizedType;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.binary.Base64;
@@ -12,10 +13,10 @@
 import org.apache.commons.io.filefilter.DirectoryFileFilter;
 import org.apache.commons.io.filefilter.FileFilterUtils;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
 
 import javax.tools.*;
 import java.io.*;
-import java.math.BigInteger;
 import java.net.URI;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
@@ -37,7 +38,7 @@ public class EncryptJarPackage {
     public static void main(String[] args) {
         String sourcePath = "E:/dev/workspaceframe/JavaFramework/core/src/";
         String compileclassPath = ".;E:/dev/workspaceframe/JavaFramework/core/target/lib/*;d:/servlet-api-2.5.jar;D:/dev/workspaceframe/JavaFramework/core/target/core-1.0-SNAPSHOT_proLists.newArrayListrd_base.jar;d:/jdk1.8/lib/tools.jar";
-        String srcPath = "E:/tmp/corencrypt/src/";
+        String srcPath = "E:/tmp/corencrypt/src/main/java/";
         JavaProjectBuilder builder = new JavaProjectBuilder();
         builder.addSourceFolder(new File(sourcePath));
         String machineSerial = MachineIdUtils.getMachineId();
@@ -45,6 +46,8 @@ public static void main(String[] args) {
 
         DataOutputStream dout = null;
         Iterator<File> iter = col.iterator();
+        JavaClass tmpClass = null;
+        ZipOutputStream outputStream=null;
         try {
             while (iter.hasNext()) {
                 File tpFile = iter.next();
@@ -55,7 +58,7 @@ public static void main(String[] args) {
 
             //bin encrypt key file init
             dout = new DataOutputStream(new FileOutputStream(new File(srcPath + "config.bin")));
-            ZipOutputStream outputStream = getJarClasses("E:/dev/workspaceframe/JavaFramework/core/target/core-1.0-SNAPSHOT_proguard_base.jar", "com/robin/core/ext/", dout, machineSerial);
+            outputStream = getJarClasses("E:/dev/workspaceframe/JavaFramework/core/target/core-1.0_proguard_base.jar", "com/robin/core/ext/", dout, machineSerial);
             while (iter1.hasNext()) {
                 StringBuilder buffer = new StringBuilder();
                 JavaSource source = iter1.next();
@@ -72,10 +75,11 @@ public static void main(String[] args) {
                 StringBuilder tmpBuilder = new StringBuilder();
                 for (int i = 0; i < classlist.size(); i++) {
                     JavaClass clazz = classlist.get(i);
+                    tmpClass = clazz;
                     List<JavaAnnotation> annotations = clazz.getAnnotations();
                     if (!CollectionUtils.isEmpty(annotations)) {
                         for (JavaAnnotation annotation : annotations) {
-                            buffer.append(annotation.getCodeBlock());
+                            buffer.append(getAnnotationPart(annotation));
                         }
                     }
 
@@ -84,29 +88,14 @@ public static void main(String[] args) {
                     List<JavaTypeVariable<JavaGenericDeclaration>> annotaions = clazz.getTypeParameters();
                     List<JavaField> props = clazz.getFields();
                     name = clazz.getName();
+                    if(packagename.contains(".test") || name.contains("Test")){
+                        continue;
+                    }
                     fullName = (packagename + "." + name);
                     boolean isinterface = clazz.isInterface();
                     boolean hasgenric = false;
                     getClassDef(clazz, buffer);
-
-                    if (annotaions != null && !annotaions.isEmpty()) {
-                        buffer.append("<");
-                        StringBuilder tbuilder = new StringBuilder();
-                        for (JavaTypeVariable<JavaGenericDeclaration> define : annotaions) {
-                            tbuilder.append(define.getValue());
-                            StringBuilder tBuffer = new StringBuilder();
-                            if (define.getBounds() != null) {
-                                tbuilder.append(" extends ");
-                                for (JavaType type : define.getBounds()) {
-                                    tbuilder.append(type.getGenericCanonicalName()).append(",");
-                                }
-                                //tbuilder.append(" extends ").append(define.getBounds().get(0).getCanonicalName()).append(",");
-                            } else {
-                                tbuilder.append(",");
-                            }
-                        }
-                        buffer.append(tbuilder.substring(0, tbuilder.length() - 1)).append(">");
-                    }
+                    parseAnotation(buffer, annotaions);
 
                     if (superclass != null) {
                         buffer.append(" extends ").append(superclass.getGenericFullyQualifiedName());
@@ -135,39 +124,54 @@ public static void main(String[] args) {
                     }
                     buffer.append("{").append("\n");
                     String tmpStr;
-                    if (props != null && props.size() > 0) {
+                    if (!CollectionUtils.isEmpty(props)) {
                         for (JavaField prop : props) {
                             tmpStr = null;
                             if (!isinterface) {
-                                tmpStr = prop.getCodeBlock().replaceAll(clazz.getPackage().getName() + "." + clazz.getName() + ".", "");
-                                //log.info(" tmpStr {}",tmpStr);
-                                if (tmpStr.indexOf("\n") < tmpStr.lastIndexOf("\n")) {
-                                    int pos = tmpStr.indexOf("=");
-                                    if (pos != -1) {
-                                        if (!tmpStr.contains("static")) {
-                                            tmpStr = tmpStr.substring(0, pos - 1) + ";\n";
+                                if (!prop.isEnumConstant()) {
+                                    tmpStr = prop.getCodeBlock().replaceAll(clazz.getPackage().getName() + "." + clazz.getName() + ".", "");
+                                } else {
+                                    List<Expression> list = prop.getEnumConstantArguments();
+                                    buffer.append(prop.getName()).append("(");
+                                    for (int pos = 0; pos < list.size(); pos++) {
+                                        if (!ObjectUtils.isEmpty(list.get(pos))) {
+                                            buffer.append(list.get(pos).getParameterValue());
                                         } else {
-                                            if (";".equals(tmpStr.substring(pos + 1).replaceAll("\r", "").replaceAll("\n", "").trim())) {
-                                                if (!prop.getType().isPrimitive()) {
-                                                    tmpStr = tmpStr.substring(0, pos - 1) + "=null;\n";
-                                                } else {
-                                                    if (tmpStr.contains("long")) {
-                                                        tmpStr = tmpStr.substring(0, pos - 1) + "=0L;\n";
-                                                    } else if (tmpStr.contains("int")) {
-                                                        tmpStr = tmpStr.substring(0, pos - 1) + "=0L;\n";
-                                                    } else if (tmpStr.contains("float") || tmpStr.contains("double'")) {
-                                                        tmpStr = tmpStr.substring(0, pos - 1) + "=0.0;\n";
+                                            buffer.append("null");
+                                        }
+                                        if (i < list.size() - 1) {
+                                            buffer.append(",");
+                                        }
+                                    }
+                                    buffer.append(")\n");
+                                }
+                                if (!ObjectUtils.isEmpty(tmpStr)) {
+                                    if (tmpStr.indexOf("\n") < tmpStr.lastIndexOf("\n")) {
+                                        int pos = tmpStr.indexOf("=");
+                                        if (pos != -1) {
+                                            if (!tmpStr.contains("static")) {
+                                                tmpStr = tmpStr.substring(0, pos - 1) + ";\n";
+                                            } else {
+                                                if (";".equals(tmpStr.substring(pos + 1).replaceAll("\r", "").replaceAll("\n", "").trim())) {
+                                                    if (!prop.getType().isPrimitive()) {
+                                                        tmpStr = tmpStr.substring(0, pos - 1) + "=null;\n";
+                                                    } else {
+                                                        if (tmpStr.contains("long")) {
+                                                            tmpStr = tmpStr.substring(0, pos - 1) + "=0L;\n";
+                                                        } else if (tmpStr.contains("int")) {
+                                                            tmpStr = tmpStr.substring(0, pos - 1) + "=0L;\n";
+                                                        } else if (tmpStr.contains("float") || tmpStr.contains("double'")) {
+                                                            tmpStr = tmpStr.substring(0, pos - 1) + "=0.0;\n";
+                                                        }
                                                     }
                                                 }
                                             }
                                         }
-                                    }
-
-                                } else {
 
+                                    }
+                                    buffer.append(tmpStr);
                                 }
                             }
-                            buffer.append(tmpStr);
                         }
                     }
                     List<JavaConstructor> constructList = clazz.getConstructors();
@@ -212,7 +216,6 @@ public static void main(String[] args) {
                         getParameters(parameters, tmpbuffer, method);
                         tmpbuffer.append(")");
                         if (!isinterface) {
-                            String code = method.getCodeBlock();
                             tmpbuffer.append("{");
                             if (!"void".equals(rettype)) {
                                 if (rettype.contains("[") && rettype.contains("]")) {
@@ -281,9 +284,7 @@ public static void main(String[] args) {
 
                     }
                     buffer.append("}");
-
                 }
-
                 String classPathStr = fullName.replace(".", "/");
                 String encryptclaspath = classPathStr + ".class";
                 String srcFilepath = srcPath + classPathStr + ".java";
@@ -293,7 +294,7 @@ public static void main(String[] args) {
                 if (!parentpath.exists()) {
                     parentpath.mkdir();
                 }
-                FileUtils.writeStringToFile(srcFile, buffer.toString(), Charset.defaultCharset(),false);
+                FileUtils.writeStringToFile(srcFile, buffer.toString(), Charset.defaultCharset(), false);
                 //compile classes
 
                 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
@@ -317,8 +318,11 @@ public static void main(String[] args) {
 
         } catch (Exception ex) {
             ex.printStackTrace();
+            System.out.println(tmpClass.getPackage().getName() + "." + tmpClass.getName());
+
         } finally {
             try {
+                outputStream.close();
                 if (dout != null) {
                     dout.flush();
                     dout.close();
@@ -329,6 +333,38 @@ public static void main(String[] args) {
         }
     }
 
+
+    private static void parseAnotation(StringBuilder buffer, List<JavaTypeVariable<JavaGenericDeclaration>> annotaions) {
+        if (annotaions != null && !annotaions.isEmpty()) {
+            buffer.append("<");
+            StringBuilder tbuilder = new StringBuilder();
+            for (JavaTypeVariable<JavaGenericDeclaration> define : annotaions) {
+                tbuilder.append(define.getValue());
+                StringBuilder tBuffer = new StringBuilder();
+                if (define.getBounds() != null) {
+                    tbuilder.append(" extends ");
+                    for (JavaType type : define.getBounds()) {
+                        tbuilder.append(type.getGenericCanonicalName()).append(",");
+                    }
+                    //tbuilder.append(" extends ").append(define.getBounds().get(0).getCanonicalName()).append(",");
+                } else {
+                    tbuilder.append(",");
+                }
+            }
+            buffer.append(tbuilder.substring(0, tbuilder.length() - 1)).append(">");
+        }
+    }
+
+    private static String getAnnotationPart(JavaAnnotation annotation){
+        String code=null;
+        try {
+            code=annotation.getCodeBlock();
+        }catch (Exception ex){
+            code=annotation.toString()+"\n";
+        }
+        return code;
+    }
+
     private static String getExceptions(List<JavaClass> exceptions) {
         StringBuilder builder = new StringBuilder("");
         if (exceptions != null && !exceptions.isEmpty()) {
@@ -476,12 +512,15 @@ private static ZipOutputStream getJarClasses(String jarFile, String basePath, Da
 
             Random random1 = new Random();
             //List<String> insertFloder = new ArrayList<>();
-            String[] caculateStr = caculateMachineSerail(machineSerial, System.currentTimeMillis() + 365 * 3600 * 24 * 1000);
-            byte[] machineSerailbytes = Base64.decodeBase64(caculateStr[1].getBytes());
+            String[] caculateStr = calculateMachineSerial(machineSerial, System.currentTimeMillis() + 365 * 3600 * 24 * 1000);
+
             //core key ,contains machineId and expireTs
             dout.write(CipherUtil.mzHeader);
-            dout.writeUTF(encrypt(caculateStr[0]));
-            dout.write(CipherUtil.m_datapadding);
+            byte[] keybytes=CipherUtil.encryptByte(caculateStr[0].getBytes(),CipherUtil.getEncryptKey(caculateStr[0].getBytes()));
+            dout.writeInt(keybytes.length);
+            dout.write(keybytes);
+            //dout.writeUTF(encrypt(caculateStr[0]));
+            //dout.write(CipherUtil.m_datapadding);
             while ((entry = inputStream.getNextEntry()) != null) {
                 String path = entry.getName();
                 int pos = path.lastIndexOf("/");
@@ -496,23 +535,24 @@ private static ZipOutputStream getJarClasses(String jarFile, String basePath, Da
                     pos = className.indexOf(".");
                     String clazzName = className.substring(0, pos);
                     String keystr = generateEncrytKey(range, 16, random);
-                    byte[] key = Base64.decodeBase64(keystr.getBytes());
+                    //byte[] key = Base64.decodeBase64(keystr.getBytes());
                     byte[] bytes = getZipByte(inputStream);
                     //使用随机密码加密
                     byte[] outbyte = CipherUtil.encryptByte(bytes, keystr.getBytes());
                     //使用机器码加密，用于失效验证
-                    byte[] encryptbytes = CipherUtil.encryptByte(outbyte, caculateStr[0].getBytes());
+
                     //FileUtils.writeByteArrayToFile(new File(basePath + path), outbyte);
                     String randomoutputPath = randomFolders.get(random1.nextInt(8));
                     List<String> params = getRandomName(16, random);
                     String fileName = params.get(0);
-                    dout.writeUTF(encrypt(packageName + "." + clazzName));
-                    dout.write(CipherUtil.m_datapadding);
+                    byte[] classNameBytes=CipherUtil.encryptByte((packageName + "." + clazzName).getBytes(),CipherUtil.getEncryptKey(caculateStr[0].getBytes()));
+                    dout.writeInt(classNameBytes.length);
+                    dout.write(classNameBytes);
                     //dout.writeUTF(encrypt(basePath + randomoutputPath + fileName));
                     dout.write(longToBytes(Long.valueOf(params.get(1))));
-                    dout.write(CipherUtil.m_datapadding);
                     dout.write(getKeyByte(keystr));
-                    dout.write(CipherUtil.m_datapadding);
+                    byte[] encryptbytes = CipherUtil.encryptByte(outbyte, keystr.getBytes());
+                    //dout.write(CipherUtil.m_datapadding);
                     outputStream.putNextEntry(new JarEntry(basePath + fileName));
                     IOUtils.copyBytes(new ByteArrayInputStream(encryptbytes), outputStream, 8094);
                     System.out.println(packageName + "." + clazzName + "=" + keystr);
@@ -664,12 +704,12 @@ private static String processConstruction(String codeBase) {
         return "";
     }
 
-    private static String[] caculateMachineSerail(String machineId, Long expireTs) {
+    public static String[] calculateMachineSerial(String machineId, Long expireTs) {
         //取机器码对应bigint
         //BigInteger integer = new BigInteger(machineId.replaceAll("-", ""), 16);
         int len = String.valueOf(expireTs).length();
         //String machineStr = integer.toString();
-        String machineStr=machineId.replace("-","");
+        String machineStr = machineId.replace("-", "");
         StringBuilder builder = new StringBuilder();
         String key = machineStr.substring(0, machineStr.length() - len);
         builder.append(key);
@@ -678,13 +718,14 @@ private static String[] caculateMachineSerail(String machineId, Long expireTs) {
         }
         String remain = machineStr.substring(machineStr.length() - len);
         String headerStr = machineStr.substring(0, len);
-        Long remainVal = Long.valueOf(remain,16);
+        Long remainVal = Long.valueOf(remain, 16);
         Long overflowval = Double.valueOf(Math.pow(10.0, len + 1)).longValue() - expireTs - 1L;
         //机器码后部分与 超时时间补进行xor
-        Long xorVal = (Long.valueOf(headerStr,16) & remainVal) ^ overflowval;
+        Long xorVal = (Long.valueOf(headerStr, 16) & remainVal) ^ overflowval;
         //BigInteger real = new BigInteger(builder.toString(),10).add(BigInteger.valueOf(Long.valueOf(xorVal)));
-        String[] output = new String[3];
-        output[0] = xorVal.toString();
+        String[] output = new String[2];
+
+        output[0] = Long.toHexString(xorVal);
         output[1] = key;
         return output;
     }
diff --git a/core/src/main/java/com/robin/core/encrypt/EncryptWebClassLoaderHolder.java b/core/src/main/java/com/robin/core/encrypt/EncryptWebClassLoaderHolder.java
index 662bb0da..b70ed33a 100644
--- a/core/src/main/java/com/robin/core/encrypt/EncryptWebClassLoaderHolder.java
+++ b/core/src/main/java/com/robin/core/encrypt/EncryptWebClassLoaderHolder.java
@@ -109,9 +109,11 @@ protected EncryptWebClassLoader(URLClassLoader loader) {
                 // load bin file
                 instream = new DataInputStream(ClassLoader.getSystemResourceAsStream("META-INF/config.bin"));
                 if (instream != null) {
-                    String keystr = decrypt(instream.readUTF());
+                    instream.read(CipherUtil.mzHeader);
+
                     instream.read(m_datapadding);
                     while (instream.available() > 0) {
+                        String keystr = decrypt(instream.readUTF());
                         String className = decrypt(instream.readUTF());
                         instream.readByte();
                         classMappingMap.put(keystr, className);
@@ -418,7 +420,7 @@ public static String encrypt(String inputStr) {
             for (int i = 0; i < inputStr.length(); i++) {
                 int keypos = i % 8;
                 int xorbyte = inputStr.charAt(i) ^ XorKey[keypos];
-                builder.append(bytesToHexString(new byte[]{(byte) xorbyte}));
+                builder.append(CipherUtil.bytesToHexString(new byte[]{(byte) xorbyte}));
             }
             return builder.toString();
         }
@@ -436,21 +438,7 @@ public static String decrypt(String inputStr) {
             return builder.toString();
         }
 
-        public static String bytesToHexString(byte[] src) {
-            StringBuilder stringBuilder = new StringBuilder("");
-            if (src == null || src.length <= 0) {
-                return null;
-            }
-            for (int i = 0; i < src.length; i++) {
-                int v = src[i] & 0xFF;
-                String hv = Integer.toHexString(v);
-                if (hv.length() < 2) {
-                    stringBuilder.append(0);
-                }
-                stringBuilder.append(hv);
-            }
-            return stringBuilder.toString().toUpperCase();
-        }
+
 
         public URLClassLoader getSuperloader() {
             return superloader;
diff --git a/core/src/main/java/com/robin/core/encrypt/JarMethodClearUtils.java b/core/src/main/java/com/robin/core/encrypt/JarMethodClearUtils.java
new file mode 100644
index 00000000..87cb1c29
--- /dev/null
+++ b/core/src/main/java/com/robin/core/encrypt/JarMethodClearUtils.java
@@ -0,0 +1,195 @@
+package com.robin.core.encrypt;
+
+import com.robin.core.base.exception.MissingConfigException;
+import com.robin.core.base.util.MavenUtils;
+import com.robin.core.hardware.MachineIdUtils;
+import javassist.*;
+import javassist.bytecode.*;
+import javassist.compiler.CompileError;
+import javassist.compiler.Javac;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.filefilter.DirectoryFileFilter;
+import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.springframework.util.CollectionUtils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class JarMethodClearUtils {
+    public static void clearClassMethod(List<String> mavenDepends,String basePath, Collection<File> classFiles,String targetPath) {
+        //初始化javassist
+        ClassPool pool = ClassPool.getDefault();
+        //[1]把所有涉及到的类加入到ClassPool的classpath
+        //[1.1]lib目录所有的jar加入classpath
+        loadClassPath(pool, mavenDepends);
+
+        //[1.2]外部依赖的lib加入classpath
+        //[1.3]要修改的class所在的目录（-INF/classes 和 libjar）加入classpath
+        List<String> classPaths = new ArrayList<>();
+        classFiles.forEach(classFile -> {
+            String classPath = resolveClassName(classFile.getAbsolutePath(), basePath);
+            if (classPaths.contains(classPath)) {
+                return;
+            }
+            try {
+                pool.insertClassPath(classPath);
+            } catch (NotFoundException e) {
+                //Ignore
+            }
+            classPaths.add(classPath);
+        });
+
+        //[2]修改class方法体，并保存文件
+        classFiles.forEach(classFile -> {
+            //解析出类全名
+            String className = resolveClassName(classFile.getAbsolutePath(), basePath);
+            byte[] bts = null;
+            try {
+                bts = rewriteAllMethods(pool, className);
+            } catch (Exception e) {
+
+            }
+            if (bts != null) {
+                writeToTarget(targetPath,className, bts);
+            }
+        });
+    }
+    public static void loadJars(ClassPool pool, String... jarFiles){
+        loadClassPath(pool,jarFiles);
+    }
+    public static void loadJars(ClassPool pool, List<String> jarFiles){
+        loadClassPath(pool,jarFiles);
+    }
+    public static byte[] getClearedClass(ClassPool pool,String className) throws RuntimeException{
+        try {
+            return rewriteAllMethods(pool, className);
+        } catch (Exception e) {
+            throw new MissingConfigException(e);
+        }
+    }
+    private static String resolveClassName(String filePath,String basePath){
+        int endPos=filePath.lastIndexOf(".");
+        return filePath.substring(basePath.length()+1,endPos).replace(File.separator,".");
+    }
+    private static void writeToTarget(String targetPath,String className,byte[] bytes){
+        int pos=className.lastIndexOf(".");
+        String parentPath=targetPath+className.substring(0,pos).replace(".","/");
+        try{
+            FileUtils.forceMkdir(new File(parentPath));
+        }catch (IOException ex1){
+            ex1.printStackTrace();
+        }
+        try(FileOutputStream outputStream=new FileOutputStream(targetPath+className.replace(".","/")+".class")){
+            IOUtils.write(bytes,outputStream);
+        }catch (IOException ex){
+            ex.printStackTrace();
+        }
+    }
+    private static void loadClassPath(ClassPool pool,List<String> jarPaths){
+        if(!CollectionUtils.isEmpty(jarPaths)){
+            for(String jarPath:jarPaths){
+                try {
+                    pool.insertClassPath(jarPath);
+                }catch (NotFoundException ex){
+
+                }
+            }
+        }
+    }
+    private static void loadClassPath(ClassPool pool,String... jarPaths){
+        if(jarPaths.length>0){
+            for(String jarPath:jarPaths){
+                try {
+                    pool.insertClassPath(jarPath);
+                }catch (NotFoundException ex){
+
+                }
+            }
+        }
+    }
+    public static byte[] rewriteAllMethods(ClassPool pool, String classname) {
+        String name = null;
+        try {
+            CtClass cc = pool.getCtClass(classname);
+            CtMethod[] methods = cc.getDeclaredMethods();
+
+            for (CtMethod m : methods) {
+                name = m.getName();
+                //不是构造方法，在当前类，不是父lei
+                if (!m.getName().contains("<") && m.getLongName().startsWith(cc.getName())) {
+
+                    CodeAttribute ca = m.getMethodInfo().getCodeAttribute();
+                    //接口的ca就是null,方法体本来就是空的就是-79
+                    if (ca != null && ca.getCodeLength() != 1 && ca.getCode()[0] != -79) {
+                       setBodyKeepParamInfos(m, null, true);
+                        if ("void".equalsIgnoreCase(m.getReturnType().getName()) && m.getLongName().endsWith(".main(java.lang.String[])") && m.getMethodInfo().getAccessFlags() == 9) {
+                            m.insertBefore("System.out.println(\"\\n.\\n\");");
+                        }
+
+                    }
+
+                }
+            }
+            return cc.toBytecode();
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("[" + classname + "(" + name + ")]" + e.getMessage());
+        }
+    }
+    public static void setBodyKeepParamInfos(CtMethod m, String src, boolean rebuild) throws CannotCompileException {
+        CtClass cc = m.getDeclaringClass();
+        if (cc.isFrozen()) {
+            throw new RuntimeException(cc.getName() + " class is frozen");
+        }
+        CodeAttribute ca = m.getMethodInfo().getCodeAttribute();
+        if (ca == null) {
+            throw new CannotCompileException("no method body");
+        } else {
+            CodeIterator iterator = ca.iterator();
+            Javac jv = new Javac(cc);
+
+            try {
+                int nvars = jv.recordParams(m.getParameterTypes(), Modifier.isStatic(m.getModifiers()));
+                jv.recordParamNames(ca, nvars);
+                jv.recordLocalVariables(ca, 0);
+                jv.recordReturnType(Descriptor.getReturnType(m.getMethodInfo().getDescriptor(), cc.getClassPool()), false);
+
+                Bytecode b = jv.compileBody(m, src);
+                int stack = b.getMaxStack();
+                int locals = b.getMaxLocals();
+                if (stack > ca.getMaxStack()) {
+                    ca.setMaxStack(stack);
+                }
+
+                if (locals > ca.getMaxLocals()) {
+                    ca.setMaxLocals(locals);
+                }
+                int pos = iterator.insertEx(b.get());
+                iterator.insert(b.getExceptionTable(), pos);
+                if (rebuild) {
+                    m.getMethodInfo().rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
+                }
+            } catch (NotFoundException var12) {
+                throw new CannotCompileException(var12);
+            } catch (CompileError var13) {
+                throw new CannotCompileException(var13);
+            } catch (BadBytecode var14) {
+                throw new CannotCompileException(var14);
+            }
+        }
+    }
+    public static void main(String[] args){
+        String machineId= MachineIdUtils.getMachineId();
+        String[] str=EncryptJarPackage.calculateMachineSerial(machineId,System.currentTimeMillis()+364*1000*60*24L);
+        List<String> mavenDepends= MavenUtils.getDepenendcyList(MavenUtils.getMavenRepository(),"E:/dev/workspaceframe/JavaFramework/core");
+        Collection<File> classes = FileUtils.listFiles(new File("E:/dev/workspaceframe/JavaFramework/core/target/classes"), FileFilterUtils.suffixFileFilter("class"), DirectoryFileFilter.DIRECTORY);
+        clearClassMethod(mavenDepends,"E:\\dev\\workspaceframe\\JavaFramework\\core\\target\\classes",classes,"e:/tmp/output/");
+
+    }
+
+}
diff --git a/core/src/main/java/com/robin/core/encrypt/JarRepackager.java b/core/src/main/java/com/robin/core/encrypt/JarRepackager.java
new file mode 100644
index 00000000..c51326bd
--- /dev/null
+++ b/core/src/main/java/com/robin/core/encrypt/JarRepackager.java
@@ -0,0 +1,165 @@
+package com.robin.core.encrypt;
+
+
+import cn.hutool.core.io.FileUtil;
+import com.robin.core.base.util.MavenUtils;
+import com.robin.core.hardware.MachineIdUtils;
+import javassist.ClassPool;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.*;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.util.List;
+import java.util.Random;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+@Slf4j
+public class JarRepackager {
+    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
+    private static final char spacebyteVal=20;
+    /**
+     *
+     * @param inputJarFiles  待加密的包
+     * @param outputJarFile  结果包路径
+     * @param mavenSrcPath   工程maven pom.xml所在路径
+     * @param basePath       相对于jar包的相对路径
+     * @param machineId      机器码，与机器绑定
+     * @param expireTs       包失效时间
+     */
+    public static void repackage(String inputJarFiles,String outputJarFile,String mavenSrcPath, String basePath,String machineId,Long expireTs){
+        Random random=new Random(100000L);
+        ClassPool pool=ClassPool.getDefault();
+        List<String> dependencys= MavenUtils.getDepenendcyList(MavenUtils.getMavenRepository(),mavenSrcPath);
+        JarMethodClearUtils.loadJars(pool,dependencys);
+        JarMethodClearUtils.loadJars(pool,inputJarFiles);
+        FileUtil.clean(basePath);
+        try(JarInputStream inputStream=new JarInputStream(new FileInputStream(inputJarFiles));
+            JarOutputStream outputStream=new JarOutputStream(new FileOutputStream(outputJarFile));
+                ByteArrayOutputStream out1=new ByteArrayOutputStream();
+                DataOutputStream dout=new DataOutputStream(out1)) {
+            ZipEntry entry;
+            dout.write(CipherUtil.mzHeader);
+            dout.write(CipherUtil.m_datapadding);
+            dout.write(CipherUtil.hexStringToBytes(machineId.toUpperCase()));
+            dout.writeLong(expireTs);
+
+            while((entry=inputStream.getNextEntry())!=null){
+                if(!entry.isDirectory() && entry.getName().endsWith("class")){
+
+                    String path = entry.getName();
+                    int pos = path.lastIndexOf("/");
+                    String className = path.substring(pos + 1);
+                    String packageName = path.substring(0, pos).replaceAll("/", ".");
+                    pos = className.indexOf(".");
+                    String clazzName = className.substring(0, pos);
+
+                    String keystr = CipherUtil.generateRandomKey(CipherUtil.avaiablechar.length, 16, random);
+                    log.info("{} using {}",packageName + "." + clazzName,keystr);
+                    byte[] bytes = getZipByte(inputStream);
+                    byte[] classNameBytes=encryptByte((packageName + "." + clazzName).getBytes(),CipherUtil.getEncryptKey(machineId.toUpperCase().getBytes()));
+                    byte[] keybytes=encryptByte(keystr.getBytes(),CipherUtil.getEncryptKey(machineId.toUpperCase().getBytes()));
+                    byte[] outbyte = encryptByte(bytes, keystr.getBytes());
+                    byte[] encrypted=encryptByte(outbyte,CipherUtil.getEncryptKey(machineId.toUpperCase().getBytes()));
+
+                    if(!packageName.equals("com.robin.spring") && !"JarMethodClearUtils".equals(clazzName) && !"JarRepackager".equals(clazzName) && !clazzName.contains("Hibernate")) {
+                        dout.write(CipherUtil.m_datapadding);
+                        dout.writeInt(classNameBytes.length);
+                        dout.write(classNameBytes);
+                        List<String> confusedNames=CipherUtil.getConfusedName(16,random);
+                        FileOutputStream fileOut=new FileOutputStream(basePath+confusedNames.get(0));
+                        //outputStream.putNextEntry(new JarEntry(basePath + confusedNames.get(0)));
+                        dout.write(indexToBytes(confusedNames.get(1)));
+                        dout.writeInt(keybytes.length);
+                        dout.write(keybytes);
+                        IOUtils.write(encrypted, fileOut);
+                        fileOut.close();
+                        System.out.println(packageName+"."+clazzName+"="+confusedNames.get(0)+"|"+confusedNames.get(1)+"|"+keystr);
+                        //方法体清理
+
+                        byte[] clearBytes = JarMethodClearUtils.rewriteAllMethods(pool, packageName + "." + clazzName);
+                        outputStream.putNextEntry(new JarEntry(entry.getName()));
+                        IOUtils.write(clearBytes, outputStream);
+                    }else{
+                        outputStream.putNextEntry(new JarEntry(entry.getName()));
+                        IOUtils.write(bytes, outputStream);
+                    }
+                }else {
+                    outputStream.putNextEntry(new JarEntry(entry.getName()));
+                    IOUtils.copy(inputStream, outputStream, 1024);
+                }
+            }
+            if(dout!=null){
+                //outputStream.putNextEntry(new JarEntry("META-INF/config.bin"));
+                FileOutputStream fileOut2=new FileOutputStream(basePath+"../config.bin");
+                IOUtils.write(out1.toByteArray(), fileOut2);
+                fileOut2.close();
+            }
+
+        }catch (IOException ex){
+            ex.printStackTrace();
+        }
+    }
+    private static byte[] getZipByte(ZipInputStream inputStream) throws IOException {
+        ByteArrayOutputStream bArray = new ByteArrayOutputStream();
+        IOUtils.copy(inputStream, bArray, 8192);
+        return bArray.toByteArray();
+    }
+    private static SecretKeySpec toKey(byte[] keybyte,String argrithm) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        return new SecretKeySpec(keybyte, argrithm);
+    }
+    private static byte[] encryptByte(byte[] bytes, byte[] key) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+
+            cipher.init(Cipher.ENCRYPT_MODE, toKey(key,"AES"));
+            return cipher.doFinal(bytes);
+        } catch (Exception ex) {
+            log.error("{}", ex.getMessage());
+        }
+        return null;
+    }
+
+
+    private static byte[] decryptByte(byte[] bytes, byte[] key) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, toKey(key,"AES"));
+            return cipher.doFinal(bytes);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+    private static byte[] indexToBytes(String index){
+        byte[] outputBytes=new byte[index.length()];
+        for(int i=0;i<index.length();i++){
+            outputBytes[i]=(byte)((index.charAt(i)-spacebyteVal));
+        }
+        return outputBytes;
+    }
+    private static String bytesToIndex(byte[] bytes){
+        StringBuilder builder=new StringBuilder();
+        for(byte bytes1:bytes){
+            builder.append((char)((int)bytes1+spacebyteVal));
+        }
+        return builder.toString();
+    }
+    public static void main(String[] args){
+        repackage("E:/dev/core-obs.jar","E:/dev/maven/repository/com/robin/core-encrypt/1.0/core-encrypt-1.0.jar","E:/dev/workspaceframe/JavaFramework/core","E:/dev/workspaceframe/JavaFramework/decryptagent/src/main/resources/META-INF/ext/", MachineIdUtils.getMachineId().replace("-","").toUpperCase(),System.currentTimeMillis()+365*3600*24*1000L);
+        /*Random random=new Random();
+        List<String> strs=CipherUtil.getConfusedName(16,random);
+        System.out.println(strs.get(1));
+        byte[] bytes=indexToBytes(strs.get(1));
+        System.out.println(bytes.length);
+        System.out.println(bytesToIndex(bytes));*/
+    }
+}
diff --git a/core/src/main/java/com/robin/core/fileaccess/meta/DataCollectionMeta.java b/core/src/main/java/com/robin/core/fileaccess/meta/DataCollectionMeta.java
index e8f57c65..8cd74ade 100644
--- a/core/src/main/java/com/robin/core/fileaccess/meta/DataCollectionMeta.java
+++ b/core/src/main/java/com/robin/core/fileaccess/meta/DataCollectionMeta.java
@@ -70,7 +70,7 @@ public void setAvroSchema(Class<?> clazz){
 		valueClassName=fullClassName.substring(pos+1);
 	}
 
-	public void addColumnMeta(String columnName,String columnType,String defaultNullValue){
+	public void addColumnMeta(String columnName,String columnType,Object defaultNullValue){
 		this.columnList.add(new DataSetColumnMeta(columnName, columnType, defaultNullValue));
 		columnNameMap.put(columnName,1);
 	}
@@ -78,11 +78,18 @@ public void addColumnMeta(String columnName,String columnType,boolean flushOut){
 		this.columnList.add(new DataSetColumnMeta(columnName, columnType, flushOut));
 		columnNameMap.put(columnName,1);
 	}
-	public void addColumnMeta(String columnName,String columnType,String defaultNullValue,boolean required){
+
+	public void addColumnMeta(String columnName,String columnType,Object defaultNullValue,boolean required){
 		this.columnList.add(new DataSetColumnMeta(columnName, columnType, defaultNullValue,required));
 		columnNameMap.put(columnName,null);
 	}
-	public void addColumnMeta(String columnName,String columnType,String defaultNullValue,boolean required,String dateFormat){
+	public void addColumnMeta(String columnName,String columnCode,String columnType,Object defaultNullValue,boolean required){
+		DataSetColumnMeta setColumnMeta=new DataSetColumnMeta(columnName,columnCode, columnType, defaultNullValue);
+		setColumnMeta.setRequired(required);
+		this.columnList.add(setColumnMeta);
+		columnNameMap.put(columnName,null);
+	}
+	public void addColumnMeta(String columnName,String columnType,Object defaultNullValue,boolean required,String dateFormat){
 		this.columnList.add(new DataSetColumnMeta(columnName, columnType, defaultNullValue,required,dateFormat));
 		columnNameMap.put(columnName,null);
 	}
diff --git a/core/src/main/java/com/robin/core/fileaccess/meta/DataSetColumnMeta.java b/core/src/main/java/com/robin/core/fileaccess/meta/DataSetColumnMeta.java
index 3f1bc032..223d4af3 100644
--- a/core/src/main/java/com/robin/core/fileaccess/meta/DataSetColumnMeta.java
+++ b/core/src/main/java/com/robin/core/fileaccess/meta/DataSetColumnMeta.java
@@ -11,6 +11,7 @@
 @Data
 public class DataSetColumnMeta implements Serializable {
     private String columnName;
+    private String columnCode;
     private String columnType;
     private Object defaultNullValue;
     private String dateFormat;
@@ -24,10 +25,13 @@ public class DataSetColumnMeta implements Serializable {
     private Integer length;
     private List<String> nominalValues;
     private boolean flushOut=true;
+    public DataSetColumnMeta(){
 
+    }
 
     public DataSetColumnMeta(String columnName,String columnType,Object defaultNullValue){
         this.columnName=columnName;
+        this.columnCode=columnName;
         this.columnType=columnType;
         if(defaultNullValue!=null){
             this.defaultNullValue=defaultNullValue;
@@ -35,6 +39,10 @@ public DataSetColumnMeta(String columnName,String columnType,Object defaultNullV
             this.defaultNullValue="";
         }
     }
+    public DataSetColumnMeta(String columnName,String columnCode,String columnType,Object defaultNullValue){
+        this(columnName,columnType,defaultNullValue);
+        this.columnCode=columnCode;
+    }
     public DataSetColumnMeta(String columnName,String columnType){
         this(columnName,columnType,null);
     }
@@ -48,24 +56,12 @@ public DataSetColumnMeta(String columnName,String columnType,boolean flushOut){
         this.flushOut=flushOut;
     }
     public DataSetColumnMeta(String columnName,String columnType,Object defaultNullValue,boolean required,String dateFormat){
-        this.columnName=columnName;
-        this.columnType=columnType;
-        if(defaultNullValue!=null){
-            this.defaultNullValue=defaultNullValue;
-        }else{
-            this.defaultNullValue="";
-        }
+        this(columnName,columnType,defaultNullValue);
         this.required=required;
         this.dateFormat=dateFormat;
     }
     public DataSetColumnMeta(String columnName,String columnType,Object defaultNullValue,boolean required){
-        this.columnName=columnName;
-        this.columnType=columnType;
-        if(defaultNullValue!=null){
-            this.defaultNullValue=defaultNullValue;
-        }else{
-            this.defaultNullValue="";
-        }
+        this(columnName,columnType,defaultNullValue);
         this.required=required;
     }
     public DataBaseColumnMeta toDataBaseColumnMeta(){
diff --git a/core/src/main/java/com/robin/core/hardware/MachineIdUtils.java b/core/src/main/java/com/robin/core/hardware/MachineIdUtils.java
index e707547e..55e77f3c 100644
--- a/core/src/main/java/com/robin/core/hardware/MachineIdUtils.java
+++ b/core/src/main/java/com/robin/core/hardware/MachineIdUtils.java
@@ -149,11 +149,20 @@ public static String getHardDiskSerial() throws RuntimeException{
         BufferedReader reader=null;
         try{
             if(isWindows()){
-                serial=CommandLineExecutor.getInstance().executeCmdReturnAfterRow(Arrays.asList("powershell.exe","Get-WmiObject","-Class","Win32_DiskDrive","|","Select-Object","SerialNumber"),2);
-                if(serial.contains("\n") || serial.contains("\r\n")){
-                    reader=new BufferedReader(new StringReader(serial));
-                    serial=reader.readLine();
+                serial=CommandLineExecutor.getInstance().executeCmdReturnAfterRow(Arrays.asList("powershell.exe","Get-WmiObject","-Class","Win32_DiskDrive","|","Select-Object","SerialNumber,DeviceId"),2);
+                reader=new BufferedReader(new StringReader(serial));
+                String tmpStr;
+                String selSerial=null;
+                int deviceId=10000;
+                while((tmpStr=reader.readLine())!=null){
+                    String[] arr=tmpStr.split(" ");
+                    int currentdevice=Integer.parseInt(arr[1].substring(arr[1].length()-1));
+                    if(currentdevice<deviceId){
+                        selSerial=arr[0].trim();
+                        deviceId=currentdevice;
+                    }
                 }
+                serial=selSerial;
             }else if(isLinux()){
                 serial=CommandLineExecutor.getInstance().executeCmdReturnAfterRow(Arrays.asList("bash","-c","sudo lsblk -o SERIAL"),1);
 
@@ -256,6 +265,23 @@ public static String getSystemTag(){
         builder.append("_SYS_"+MachineIdUtils.getOsName());
         return builder.toString();
     }
+    public static String getSystemTagNum(){
+        StringBuilder builder=new StringBuilder();
+
+        String machineId = MachineIdUtils.getMachineId();
+        if(!ObjectUtils.isEmpty(machineId)){
+            builder.append(machineId);
+        }
+        String systemSerial=MachineIdUtils.getCPUSerial();
+        if(!ObjectUtils.isEmpty(machineId)){
+            builder.append(systemSerial);
+        }
+        String hardDsSerial=MachineIdUtils.getHardDiskSerial();
+        if(!ObjectUtils.isEmpty(machineId)){
+            builder.append(hardDsSerial);
+        }
+        return builder.toString();
+    }
 
 
     public static void main(String[] args) {
diff --git a/core/src/main/java/com/robin/spring/CustomJarLauncher.java b/core/src/main/java/com/robin/spring/CustomJarLauncher.java
new file mode 100644
index 00000000..94069345
--- /dev/null
+++ b/core/src/main/java/com/robin/spring/CustomJarLauncher.java
@@ -0,0 +1,18 @@
+package com.robin.spring;
+import  org.springframework.boot.loader.JarLauncher;
+import org.springframework.boot.loader.LaunchedURLClassLoader;
+
+import java.net.URL;
+
+public class CustomJarLauncher extends JarLauncher{
+    @Override
+    protected ClassLoader createClassLoader(URL[] urls) throws Exception {
+        CustomerURLClassLoader loader=new CustomerURLClassLoader(urls,this.getClass().getClassLoader());
+        Thread.currentThread().setContextClassLoader(loader);
+        return new LaunchedURLClassLoader(true, this.getArchive(), urls, loader);
+    }
+    public static void main(String[] args) throws Exception {
+        new CustomJarLauncher().launch(args);
+    }
+
+}
diff --git a/core/src/main/java/com/robin/spring/CustomerClassLoader.java b/core/src/main/java/com/robin/spring/CustomerClassLoader.java
new file mode 100644
index 00000000..ff3c3be2
--- /dev/null
+++ b/core/src/main/java/com/robin/spring/CustomerClassLoader.java
@@ -0,0 +1,233 @@
+package com.robin.spring;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.*;
+import java.net.URL;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.security.spec.InvalidKeySpecException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class CustomerClassLoader extends ClassLoader {
+    private ClassLoader superloader;
+    private Map<String, Class> loadedClassPool = new HashMap<>();
+    private Map<String, Pair<String, String>> encryptKeyMap = new HashMap<>();
+    private String machineCode;
+    private Long expireTs;
+    private static final String DEFAULTALGORITHM = "AES";
+    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS7Padding";
+    public static final byte[] m_datapadding = {0x7F};
+    public static final byte[] m_ending = {0x00};
+    private static final String[] CONFUSEDSTRS = {"i", "I", "l", "O", "0", "1"};
+
+    public static final byte[] mzHeader = {0x4D, 0x5A, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+
+    public CustomerClassLoader(ClassLoader loader) {
+        super(loader);
+        this.superloader = loader;
+        init();
+    }
+
+    private void init() {
+        Security.addProvider(new BouncyCastleProvider());
+        try (DataInputStream dInput = new DataInputStream(superloader.getResourceAsStream("META-INF/config.bin"))) {
+            dInput.read(mzHeader);
+            byte[] paddingbyte = new byte[1];
+            dInput.read(paddingbyte);
+            checkPadding(paddingbyte);
+            byte[] machineCodeByte = new byte[16];
+            dInput.read(machineCodeByte);
+            machineCode = bytesToHexString(machineCodeByte);
+            expireTs = dInput.readLong();
+            checkExpire();
+            int classNameBytesLen = 0;
+            while (dInput.available() > 0) {
+                dInput.read(paddingbyte);
+                checkPadding(paddingbyte);
+                classNameBytesLen = dInput.readInt();
+                byte[] classNameEncryptBytes = new byte[classNameBytesLen];
+                dInput.read(classNameEncryptBytes);
+                byte[] decryptClassNameBytes = decryptByte(classNameEncryptBytes, machineCode.getBytes());
+                String className = new String(decryptClassNameBytes);
+                byte[] posByte=new byte[16];
+                dInput.read(posByte);
+                String confusedName = decodeConfusedNameByCode(new String(posByte));
+                int keyLength = dInput.readInt();
+                byte[] keyEncryptByte = new byte[keyLength];
+                dInput.read(keyEncryptByte);
+                byte[] keyDecryptByte = decryptByte(keyEncryptByte, machineCode.getBytes());
+                String key = new String(keyDecryptByte);
+                encryptKeyMap.put(className, Pair.of(confusedName, key));
+                //System.out.println(className+" "+confusedName);
+                //loadClass(className,true);
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private void checkPadding(byte[] paddingbyte) {
+        if (paddingbyte[0] != m_datapadding[0]) {
+            System.err.println("jar package corrupted");
+            System.exit(1);
+        }
+    }
+
+    private void checkExpire() {
+        if (System.currentTimeMillis() > expireTs) {
+            System.err.println("you license expired!");
+            System.exit(1);
+        }
+    }
+
+    private static URL[] getUrls(String... paths) {
+        if (paths != null && paths.length > 0) {
+            return Stream.of(paths).map(f -> {
+                try {
+                    return new File(f).toURI().toURL();
+                } catch (Exception ex) {
+
+                }
+                return null;
+            }).collect(Collectors.toList()).toArray(new URL[]{});
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    protected synchronized Class<?> loadClass(String name, boolean resolve)
+            throws ClassNotFoundException {
+        String classname = name;
+        System.out.println("load class "+name);
+        try {
+            if (classname.endsWith("BeanInfo")) {
+                classname = classname.substring(0, classname.length() - 8);
+            }
+        } catch (Exception e) {
+
+        }
+        try {
+            Class clazz = null;
+            if (encryptKeyMap.containsKey(classname)) {
+                if (loadedClassPool.containsKey(classname)) {
+                    clazz = loadedClassPool.get(classname);
+                } else {
+                    try {
+                        byte[] bytes = loadEncryptDataStream(encryptKeyMap.get(classname).getKey());
+                        if (bytes != null) {
+                            byte[] machinDe = decryptByte(bytes, machineCode.getBytes());
+                            byte[] decrypt = decryptByte(machinDe, encryptKeyMap.get(classname).getValue().getBytes());
+                            if (decrypt != null) {
+                                clazz = defineClass(name, decrypt, 0, decrypt.length);
+                            }
+                        }
+                    } catch (Exception ex) {
+                        System.out.println("encounter error when load class" + classname);
+                    }
+                }
+            } else {
+                try {
+                    clazz = superloader.loadClass(name);
+
+                } catch (Exception ex) {
+
+                }
+                try {
+                    if (clazz == null) {
+                        clazz = findSystemClass(name);
+                    }
+                }catch (Exception ex){
+
+                }
+            }
+            if (clazz != null) {
+                loadedClassPool.put(classname, clazz);
+            }
+
+            return clazz;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+
+
+    private byte[] loadEncryptDataStream(String confusedName) throws IOException {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        IOUtils.copy(superloader.getResourceAsStream("META-INF/ext/" + confusedName), outputStream);
+        return outputStream.toByteArray();
+    }
+
+
+    private static void doCopy(InputStream is, OutputStream os) throws IOException {
+        byte[] bytes = new byte[64];
+        int numBytes;
+        while ((numBytes = is.read(bytes)) != -1) {
+            os.write(bytes, 0, numBytes);
+        }
+        os.flush();
+        os.close();
+        is.close();
+    }
+
+    private static byte[] decryptByte(byte[] bytes, byte[] key) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, toKey(key));
+            return cipher.doFinal(bytes);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+    private static String bytesToHexString(byte[] bytes) {
+        StringBuilder builder = new StringBuilder();
+        for (byte b : bytes) {
+            builder.append(String.format("%02X", b));
+        }
+        return builder.toString();
+    }
+
+    private static void decryptByte(byte[] key, InputStream is, OutputStream os) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, toKey(key));
+            CipherOutputStream out = new CipherOutputStream(os, cipher);
+            doCopy(is, out);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private static SecretKey toKey(byte[] keybyte) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        SecretKeySpec key = new SecretKeySpec(keybyte, DEFAULTALGORITHM);
+        SecretKeyFactory skf = SecretKeyFactory.getInstance(DEFAULTALGORITHM);
+        return skf.generateSecret(key);
+    }
+
+    private static String decodeConfusedNameByCode(String code) {
+        StringBuilder builder = new StringBuilder();
+        for (char input : code.toCharArray()) {
+            builder.append(CONFUSEDSTRS[Integer.parseInt(String.valueOf(input))-1]);
+        }
+        return builder.toString();
+    }
+    public Map<String,Pair<String,String>> getEncryptClass(){
+        return encryptKeyMap;
+    }
+}
diff --git a/core/src/main/java/com/robin/spring/CustomerURLClassLoader.java b/core/src/main/java/com/robin/spring/CustomerURLClassLoader.java
new file mode 100644
index 00000000..c23ef457
--- /dev/null
+++ b/core/src/main/java/com/robin/spring/CustomerURLClassLoader.java
@@ -0,0 +1,228 @@
+package com.robin.spring;
+
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.*;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.security.spec.InvalidKeySpecException;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class CustomerURLClassLoader extends URLClassLoader {
+    private ClassLoader superloader;
+    private Map<String, Class> loadedClassPool = new HashMap<>();
+    private Map<String, Pair<String, String>> encryptKeyMap = new HashMap<>();
+    private String machineCode;
+    private Long expireTs;
+    private static final String DEFAULTALGORITHM = "AES";
+    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS7Padding";
+    public static final byte[] m_datapadding = {0x7F};
+    public static final byte[] m_ending = {0x00};
+    private static final String[] CONFUSEDSTRS = {"i", "I", "l", "O", "0", "1"};
+
+    public static final byte[] mzHeader = {0x4D, 0x5A, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    public CustomerURLClassLoader(URL[] urls, ClassLoader parent) {
+        super(urls, parent);
+        this.superloader = parent;
+        init();
+    }
+
+    public CustomerURLClassLoader(ClassLoader loader) {
+        super(null, CustomerURLClassLoader.class.getClassLoader());
+        this.superloader = loader;
+        init();
+    }
+
+    private void init() {
+        Security.addProvider(new BouncyCastleProvider());
+        try (DataInputStream dInput = new DataInputStream(superloader.getResourceAsStream("META-INF/config.bin"))) {
+            dInput.read(mzHeader);
+            byte[] paddingbyte = new byte[1];
+            dInput.read(paddingbyte);
+            checkPadding(paddingbyte);
+            byte[] machineCodeByte = new byte[16];
+            dInput.read(machineCodeByte);
+            machineCode = bytesToHexString(machineCodeByte);
+            expireTs = dInput.readLong();
+            checkExpire();
+            int classNameBytesLen = 0;
+            while (dInput.available() > 0) {
+                dInput.read(paddingbyte);
+                checkPadding(paddingbyte);
+                classNameBytesLen = dInput.readInt();
+                byte[] classNameEncryptBytes = new byte[classNameBytesLen];
+                dInput.read(classNameEncryptBytes);
+                byte[] decryptClassNameBytes = decryptByte(classNameEncryptBytes, machineCode.getBytes());
+                String className = new String(decryptClassNameBytes);
+                byte[] posByte=new byte[16];
+                dInput.read(posByte);
+                String confusedName = decodeConfusedNameByCode(new String(posByte));
+                int keyLength = dInput.readInt();
+                byte[] keyEncryptByte = new byte[keyLength];
+                dInput.read(keyEncryptByte);
+                byte[] keyDecryptByte = decryptByte(keyEncryptByte, machineCode.getBytes());
+                String key = new String(keyDecryptByte);
+                encryptKeyMap.put(className, Pair.of(confusedName, key));
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private void checkPadding(byte[] paddingbyte) {
+        if (paddingbyte[0] != m_datapadding[0]) {
+            System.err.println("jar package corrupted");
+            System.exit(1);
+        }
+    }
+
+    private void checkExpire() {
+        if (System.currentTimeMillis() > expireTs) {
+            System.err.println("you license expired!");
+            System.exit(1);
+        }
+    }
+
+    private static URL[] getUrls(String... paths) {
+        if (paths != null && paths.length > 0) {
+            return Stream.of(paths).map(f -> {
+                try {
+                    return new File(f).toURI().toURL();
+                } catch (Exception ex) {
+
+                }
+                return null;
+            }).collect(Collectors.toList()).toArray(new URL[]{});
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    protected synchronized Class<?> loadClass(String name, boolean resolve)
+            throws ClassNotFoundException {
+        String classname = name;
+        try {
+            if (classname.endsWith("BeanInfo")) {
+                classname = classname.substring(0, classname.length() - 8);
+            }
+        } catch (Exception e) {
+
+        }
+        try {
+            Class clazz = null;
+            if (encryptKeyMap.containsKey(classname)) {
+                if (loadedClassPool.containsKey(classname)) {
+                    clazz = loadedClassPool.get(classname);
+                } else {
+                    try {
+                        byte[] bytes = loadEncryptDataStream(encryptKeyMap.get(classname).getKey());
+                        if (bytes != null) {
+                            byte[] machinDe = decryptByte(bytes, machineCode.getBytes());
+                            byte[] decrypt = decryptByte(machinDe, encryptKeyMap.get(classname).getValue().getBytes());
+                            if (decrypt != null) {
+                                clazz = defineClass(name, decrypt, 0, decrypt.length);
+                            }
+                        }
+                    } catch (Exception ex) {
+                        System.out.println("encounter error when load class" + classname);
+                    }
+                }
+            } else {
+                try {
+                    clazz = superloader.loadClass(name);
+
+                } catch (Exception ex) {
+
+                }
+                try{
+                    if (clazz == null) {
+                        clazz = findSystemClass(name);
+                    }
+                }catch (Exception ex){
+
+                }
+            }
+            if (clazz != null) {
+                loadedClassPool.put(classname, clazz);
+            }
+
+            return clazz;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+
+    private byte[] loadEncryptDataStream(String confusedName) throws IOException {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        IOUtils.copy(superloader.getResourceAsStream("META-INF/ext/" + confusedName), outputStream);
+        return outputStream.toByteArray();
+    }
+
+
+    private static void doCopy(InputStream is, OutputStream os) throws IOException {
+        byte[] bytes = new byte[64];
+        int numBytes;
+        while ((numBytes = is.read(bytes)) != -1) {
+            os.write(bytes, 0, numBytes);
+        }
+        os.flush();
+        os.close();
+        is.close();
+    }
+    private static byte[] decryptByte(byte[] bytes, byte[] key) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, toKey(key));
+            return cipher.doFinal(bytes);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+    private static String bytesToHexString(byte[] bytes) {
+        StringBuilder builder = new StringBuilder();
+        for (byte b : bytes) {
+            builder.append(String.format("%02X", b));
+        }
+        return builder.toString();
+    }
+
+    private static void decryptByte(byte[] key, InputStream is, OutputStream os) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULTALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, toKey(key));
+            CipherOutputStream out = new CipherOutputStream(os, cipher);
+            doCopy(is, out);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+    private static SecretKey toKey(byte[] keybyte) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        SecretKeySpec key = new SecretKeySpec(keybyte, DEFAULTALGORITHM);
+        SecretKeyFactory skf = SecretKeyFactory.getInstance(DEFAULTALGORITHM);
+        return skf.generateSecret(key);
+    }
+
+    private static String decodeConfusedNameByCode(String code){
+        StringBuilder builder = new StringBuilder();
+        for(char input:code.toCharArray()){
+            builder.append(CONFUSEDSTRS[Integer.parseInt(String.valueOf(input))-1]);
+        }
+        return builder.toString();
+    }
+}
diff --git a/core/src/main/java/org/springframework/boot/loader/CustomJarLauncher.java b/core/src/main/java/org/springframework/boot/loader/CustomJarLauncher.java
new file mode 100644
index 00000000..1b103f4f
--- /dev/null
+++ b/core/src/main/java/org/springframework/boot/loader/CustomJarLauncher.java
@@ -0,0 +1,24 @@
+package org.springframework.boot.loader;
+
+
+import java.net.URL;
+
+public class CustomJarLauncher extends JarLauncher{
+
+    public CustomJarLauncher(){
+
+    }
+    public static void main(String[] args) throws Exception {
+        (new CustomJarLauncher()).launch(args);
+    }
+
+    @Override
+    protected ClassLoader createClassLoader(URL[] urls) throws Exception {
+        System.out.println("--begin to init ---");
+        System.out.println(this.getClass().getClassLoader());
+        CustomerClassLoader classLoader1=new CustomerClassLoader(urls,this.getClass().getClassLoader());
+        return new LaunchedURLClassLoader(this.isExploded(), this.getArchive(),urls, classLoader1);
+    }
+
+
+}
diff --git a/core/src/main/java/org/springframework/boot/loader/CustomerClassLoader.java b/core/src/main/java/org/springframework/boot/loader/CustomerClassLoader.java
new file mode 100644
index 00000000..f009a544
--- /dev/null
+++ b/core/src/main/java/org/springframework/boot/loader/CustomerClassLoader.java
@@ -0,0 +1,242 @@
+package org.springframework.boot.loader;
+
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.*;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class CustomerClassLoader extends URLClassLoader {
+    private ClassLoader superloader;
+    private Map<String, Class> loadedClassPool = new HashMap<>();
+    private Map<String, String> encryptKeyMap = new HashMap<>();
+    private String machineCode;
+    private Long expireTs;
+    private static final String DEFAULTALGORITHM = "AES";
+    private static final String[] CONFUSEDSTRS = {"i", "I", "l", "O", "0", "1"};
+    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS7Padding";
+    private static final byte[] m_datapadding = {0x7F};
+    private static final byte[] mzHeader = {0x4D, 0x5A, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+
+    public CustomerClassLoader(URL[] urls, ClassLoader parent) {
+        super(urls, parent);
+        this.superloader = parent;
+        init();
+    }
+
+    public CustomerClassLoader(ClassLoader loader) {
+        super(null, CustomerClassLoader.class.getClassLoader());
+        this.superloader = loader;
+        init();
+    }
+
+    private void init() {
+        System.err.println("---begin to init---");
+        try (DataInputStream dInput = new DataInputStream(superloader.getResourceAsStream("META-INF/config.bin"))) {
+            dInput.read(mzHeader);
+            byte[] paddingbyte = new byte[1];
+            dInput.read(paddingbyte);
+            //checkPadding(paddingbyte);
+            byte[] machineCodeByte = new byte[16];
+            dInput.read(machineCodeByte);
+            machineCode = bytesToHexString(machineCodeByte);
+            expireTs = dInput.readLong();
+            checkExpire();
+            int classNameBytesLen = 0;
+            System.out.println("get machineId "+machineCode+" expire "+expireTs);
+            while (dInput.available() > 0) {
+                dInput.read(paddingbyte);
+                //checkPadding(paddingbyte);
+                classNameBytesLen = dInput.readInt();
+                byte[] classNameEncryptBytes = new byte[classNameBytesLen];
+                dInput.read(classNameEncryptBytes);
+                byte[] decryptClassNameBytes = decryptByte(classNameEncryptBytes, machineCode.getBytes());
+                String className = new String(decryptClassNameBytes);
+                String confusedName = decodeConfusedNameByCode(String.valueOf(dInput.readLong()));
+                int keyLength = dInput.readInt();
+                byte[] keyEncryptByte = new byte[keyLength];
+                dInput.read(keyEncryptByte);
+                byte[] keyDecryptByte = decryptByte(keyEncryptByte, machineCode.getBytes());
+                String key = new String(keyDecryptByte);
+                System.out.println(className+" "+confusedName +"  "+key);
+                encryptKeyMap.put(className, confusedName+"|"+key);
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private void checkPadding(byte[] paddingbyte) {
+        if (paddingbyte != m_datapadding) {
+            System.err.println("jar package corrupted");
+            System.exit(1);
+        }
+    }
+
+    private void checkExpire() {
+        if (System.currentTimeMillis() > expireTs) {
+            System.err.println("you license expired!");
+            System.exit(1);
+        }
+    }
+
+    private static URL[] getUrls(String... paths) {
+        if (paths != null && paths.length > 0) {
+            return Stream.of(paths).map(f -> {
+                try {
+                    return new File(f).toURI().toURL();
+                } catch (Exception ex) {
+
+                }
+                return null;
+            }).collect(Collectors.toList()).toArray(new URL[]{});
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    protected synchronized Class<?> loadClass(String name, boolean resolve)
+            throws ClassNotFoundException {
+        String classname = name;
+
+        try {
+            Class clazz = null;
+            if (loadedClassPool.containsKey(name)) {
+                clazz = loadedClassPool.get(name);
+            } else {
+                try {
+                    if (classname.endsWith("BeanInfo")) {
+                        classname = classname.substring(0, classname.length() - 8);
+                    }
+                } catch (Exception e) {
+
+                }
+                try {
+                    clazz = findLoadedClass(name);
+                    if (clazz == null) {
+                        clazz = findSystemClass(name);
+                    }
+                } catch (Exception ex) {
+                    ex.printStackTrace();
+                }
+                try {
+                    if (encryptKeyMap.containsKey(classname)) {
+                        System.out.println("begin to load class "+classname);
+                        String[] arr=encryptKeyMap.get(classname).split("\\|");
+                        InputStream in = loadEncryptDataStream(arr[0]);
+                        if (in != null) {
+                            ByteArrayOutputStream out = new ByteArrayOutputStream();
+                            decryptByte(machineCode.getBytes(), in, out);
+                            byte[] bytes = out.toByteArray();
+                            byte[] decrypt=decryptByte(bytes,arr[1].getBytes());
+                            if (bytes != null) {
+                                clazz = defineClass(name, decrypt, 0, bytes.length);
+                            }
+                        }
+                    }
+                } catch (Exception ex) {
+                    System.out.println("encounter error when load class" + classname);
+                }
+
+                if (clazz != null) {
+                    loadedClassPool.put(name, clazz);
+                }
+            }
+            return clazz;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+
+
+    private byte[] loadClassData(String name) {
+        try {
+            String tmpname = name;
+            if (tmpname.contains(".")) {
+                tmpname = tmpname.replaceAll("\\.", "/");
+            }
+            if (!tmpname.endsWith(".class")) {
+                tmpname += ".class";
+            }
+            InputStream in = superloader.getResourceAsStream(tmpname);
+            byte[] bytes = new byte[in.available()];
+            in.read(bytes);
+            return bytes;
+        } catch (Exception ex) {
+            System.out.println(name);
+            ex.printStackTrace();
+            return null;
+        }
+    }
+
+    private InputStream loadEncryptDataStream(String confusedName) {
+        return superloader.getResourceAsStream("META-INF/ext/" + confusedName);
+    }
+
+
+    private static byte[] decryptByte(byte[] bytes, byte[] key) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, toKey(key));
+            return cipher.doFinal(bytes);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+    private static void decryptByte(byte[] key, InputStream is, OutputStream os) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULTALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, toKey(key));
+            //CipherInputStream cis=new CipherInputStream(is, cipher);
+            CipherOutputStream out = new CipherOutputStream(os, cipher);
+            doCopy(is, out);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+    private static String decodeConfusedNameByCode(String code){
+        StringBuilder builder = new StringBuilder();
+        for(char input:code.toCharArray()){
+            builder.append(CONFUSEDSTRS[Integer.parseInt(String.valueOf(input))]);
+        }
+        return builder.toString();
+    }
+    private static String bytesToHexString(byte[] bytes) {
+        StringBuilder builder = new StringBuilder();
+        for (byte b : bytes) {
+            builder.append(String.format("%02X", b));
+        }
+        return builder.toString();
+    }
+    private static SecretKey toKey(byte[] keybyte) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        SecretKeySpec key = new SecretKeySpec(keybyte, DEFAULTALGORITHM);
+        SecretKeyFactory skf = SecretKeyFactory.getInstance(DEFAULTALGORITHM);
+        return skf.generateSecret(key);
+    }
+    protected static void doCopy(InputStream is, OutputStream os) throws IOException {
+        byte[] bytes = new byte[64];
+        int numBytes;
+        while ((numBytes = is.read(bytes)) != -1) {
+            os.write(bytes, 0, numBytes);
+        }
+        os.flush();
+        os.close();
+        is.close();
+    }
+}
diff --git a/core/src/main/resources/keyword.dat b/core/src/main/resources/keyword.dat
index 9588e652..b2549656 100644
Binary files a/core/src/main/resources/keyword.dat and b/core/src/main/resources/keyword.dat differ
diff --git a/core/src/test/java/com/robin/core/test/db/JdbcDaoTest.java b/core/src/test/java/com/robin/core/test/db/JdbcDaoTest.java
index d8fcc707..db80edff 100644
--- a/core/src/test/java/com/robin/core/test/db/JdbcDaoTest.java
+++ b/core/src/test/java/com/robin/core/test/db/JdbcDaoTest.java
@@ -246,7 +246,7 @@ public void testQueryWithEntity() {
         tobj.setId(4L);
         TestMutilPK obj = service.getEntity(tobj);
         assertNotNull(obj);
-        List<TestMutilPK> list = service.queryByFieldOrderBy("time desc", "outputval", Const.OPERATOR.EQ, 1.1);
+        List<TestMutilPK> list = service.queryByFieldOrderBy("time desc",false , "outputval", Const.OPERATOR.EQ, 1.1);
         List<TestMutilPK> list1 = service.queryAll();
         assertNotNull(list);
     }
diff --git a/decryptagent/pom.xml b/decryptagent/pom.xml
new file mode 100644
index 00000000..596eef72
--- /dev/null
+++ b/decryptagent/pom.xml
@@ -0,0 +1,60 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.robin</groupId>
+        <artifactId>frame</artifactId>
+        <version>1.0</version>
+    </parent>
+    <artifactId>decryptagent</artifactId>
+    <packaging>jar</packaging>
+    <name>decryptagent</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+       
+        
+    </dependencies>
+
+
+    <build>
+        <sourceDirectory>src/main/java</sourceDirectory>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestEntries>
+                            <Premain-Class>com.robin.agent.CustomAgent</Premain-Class>
+                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
+                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <configuration>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            
+        </plugins>
+    </build>
+</project>
diff --git a/decryptagent/src/main/java/com/robin/agent/ClassTransformer.java b/decryptagent/src/main/java/com/robin/agent/ClassTransformer.java
new file mode 100644
index 00000000..d21cd90e
--- /dev/null
+++ b/decryptagent/src/main/java/com/robin/agent/ClassTransformer.java
@@ -0,0 +1,166 @@
+package com.robin.agent;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.*;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ClassTransformer implements ClassFileTransformer {
+    private Map<String, byte[]> loadedClassPool = new HashMap<>();
+    private Map<String, String> encryptKeyMap = new HashMap<>();
+    private String machineCode;
+    private Long expireTs;
+    private final String DEFAULTALGORITHM = "AES";
+    private final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
+    private final byte[] m_datapadding = {0x7F};
+
+    private final String[] CONFUSEDSTRS = {"i", "I", "l", "O", "0", "1"};
+
+    private final byte[] mzHeader = new byte[19];
+    private final char spacebyteVal=20;
+
+    public ClassTransformer() {
+        init();
+    }
+
+    private void init() {
+        try (DataInputStream dInput = new DataInputStream(getClass().getClassLoader().getResourceAsStream("META-INF/config.bin"))) {
+            dInput.read(mzHeader);
+            byte[] paddingbyte = new byte[1];
+            dInput.read(paddingbyte);
+            checkPadding(paddingbyte);
+            byte[] machineCodeByte = new byte[16];
+            dInput.read(machineCodeByte);
+            machineCode = bytesToHexString(machineCodeByte);
+            expireTs = dInput.readLong();
+            checkExpire();
+            int classNameBytesLen;
+            while (dInput.available() > 0) {
+                dInput.read(paddingbyte);
+                checkPadding(paddingbyte);
+                classNameBytesLen = dInput.readInt();
+                byte[] classNameEncryptBytes = new byte[classNameBytesLen];
+                dInput.read(classNameEncryptBytes);
+                byte[] decryptClassNameBytes = decryptByte(classNameEncryptBytes, machineCode.getBytes());
+                String className = new String(decryptClassNameBytes);
+                byte[] posByte = new byte[16];
+                dInput.read(posByte);
+                String confusedName = decodeConfusedNameByCode(posByte);
+                int keyLength = dInput.readInt();
+                byte[] keyEncryptByte = new byte[keyLength];
+                dInput.read(keyEncryptByte);
+                byte[] keyDecryptByte = decryptByte(keyEncryptByte, machineCode.getBytes());
+                String key = new String(keyDecryptByte);
+                encryptKeyMap.put(className, confusedName + "|" + key);
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    private void checkPadding(byte[] paddingbyte) {
+        if (paddingbyte[0] != m_datapadding[0]) {
+            System.err.println("jar package corrupted");
+            System.exit(1);
+        }
+    }
+
+    private void checkExpire() {
+        if (System.currentTimeMillis() > expireTs) {
+            System.err.println("you license expired!");
+            System.exit(1);
+        }
+    }
+
+    private byte[] loadEncryptDataStream(String confusedName) throws IOException {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        doCopy(getClass().getClassLoader().getResourceAsStream("META-INF/ext/" + confusedName), outputStream);
+        return outputStream.toByteArray();
+    }
+
+
+    private void doCopy(InputStream is, OutputStream os) throws IOException {
+        byte[] bytes = new byte[2048];
+        int numBytes;
+        try {
+            while ((numBytes = is.read(bytes)) != -1) {
+                os.write(bytes, 0, numBytes);
+            }
+        }catch (IOException ex){
+            throw ex;
+        }finally {
+            os.close();
+            is.close();
+        }
+
+    }
+
+    private byte[] decryptByte(byte[] bytes, byte[] key) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, toKey(key));
+            return cipher.doFinal(bytes);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+    private String bytesToIndex(byte[] bytes){
+        StringBuilder builder=new StringBuilder();
+        for(byte bytes1:bytes){
+            builder.append((char)((int)bytes1+spacebyteVal));
+        }
+        return builder.toString();
+    }
+    private String bytesToHexString(byte[] bytes) {
+        StringBuilder builder = new StringBuilder();
+        for (byte b : bytes) {
+            builder.append(String.format("%02X", b));
+        }
+        return builder.toString();
+    }
+
+
+    private SecretKeySpec toKey(byte[] keybyte) {
+        return new SecretKeySpec(keybyte, DEFAULTALGORITHM);
+    }
+
+    private String decodeConfusedNameByCode(byte[] bytes) {
+        String index=bytesToIndex(bytes);
+        StringBuilder builder = new StringBuilder();
+        for (char input : index.toCharArray()) {
+            builder.append(CONFUSEDSTRS[Integer.parseInt(String.valueOf(input)) - 1]);
+        }
+        return builder.toString();
+    }
+
+    @Override
+    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+        try {
+            String loadClass = className.replace("/", ".");
+            if (encryptKeyMap.containsKey(loadClass)) {
+                System.out.println("load class "+className);
+                if (loadedClassPool.containsKey(loadClass)) {
+                    return loadedClassPool.get(loadClass);
+                }
+                String[] arr = encryptKeyMap.get(loadClass).split("\\|");
+                byte[] encryptBytes = loadEncryptDataStream(arr[0]);
+                byte[] machineDecr = decryptByte(encryptBytes, machineCode.getBytes());
+                byte[] decryptByte = decryptByte(machineDecr, arr[1].getBytes());
+                if (decryptByte != null && decryptByte[0] == -54 && decryptByte[1] == -2 && decryptByte[2] == -70 && decryptByte[3] == -66) {
+                    loadedClassPool.put(loadClass, decryptByte);
+                    return decryptByte;
+                } else {
+                    throw new RuntimeException("decrypt error!");
+                }
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return classfileBuffer;
+    }
+}
diff --git a/decryptagent/src/main/java/com/robin/agent/CustomAgent.java b/decryptagent/src/main/java/com/robin/agent/CustomAgent.java
new file mode 100644
index 00000000..e25d184b
--- /dev/null
+++ b/decryptagent/src/main/java/com/robin/agent/CustomAgent.java
@@ -0,0 +1,9 @@
+package com.robin.agent;
+
+import java.lang.instrument.Instrumentation;
+
+public class CustomAgent {
+    public static void premain(String args, Instrumentation instrumentation){
+        instrumentation.addTransformer(new ClassTransformer());
+    }
+}
diff --git a/decryptagent/src/main/resources/META-INF/ext/README b/decryptagent/src/main/resources/META-INF/ext/README
new file mode 100644
index 00000000..e69de29b
diff --git a/estool/pom.xml b/estool/pom.xml
index b42a83fd..61937fc6 100644
--- a/estool/pom.xml
+++ b/estool/pom.xml
@@ -36,7 +36,7 @@
         <dependency>
             <groupId>org.mongodb</groupId>
             <artifactId>mongo-java-driver</artifactId>
-            <version>3.2.2</version>
+            <version>3.12.8</version>
             <optional>true</optional>
             <exclusions>
                 <exclusion>
@@ -115,6 +115,11 @@
             <artifactId>guava</artifactId>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <optional>true</optional>
+        </dependency>
        
 
     </dependencies>
diff --git a/estool/src/main/java/com/robin/es/service/ESRepositoryService.java b/estool/src/main/java/com/robin/es/service/ESRepositoryService.java
index 0d478319..da6d2ae3 100644
--- a/estool/src/main/java/com/robin/es/service/ESRepositoryService.java
+++ b/estool/src/main/java/com/robin/es/service/ESRepositoryService.java
@@ -1,5 +1,6 @@
 package com.robin.es.service;
 
+import cn.hutool.core.util.StrUtil;
 import com.google.gson.Gson;
 import com.robin.comm.util.json.GsonUtil;
 import com.robin.core.base.dao.util.AnnotationRetriever;
@@ -10,10 +11,10 @@
 import com.robin.core.base.service.IBaseAnnotationJdbcService;
 import com.robin.core.base.spring.SpringContextHolder;
 import com.robin.core.base.util.Const;
-import com.robin.core.convert.util.ConvertUtil;
 import com.robin.core.query.util.PageQuery;
 import com.robin.core.sql.util.FilterCondition;
 import com.robin.core.sql.util.FilterConditionBuilder;
+import com.robin.es.util.BaseObjectWrapper;
 import com.robin.es.util.CommEsQueryUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.elasticsearch.action.index.IndexRequest;
@@ -51,7 +52,6 @@
 import java.io.IOException;
 import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.*;
@@ -186,7 +186,7 @@ public V getEntity(P id) throws ServiceException {
                 obj = type.getDeclaredConstructor().newInstance();
                 while (citer.hasNext()) {
                     Map.Entry<String, Object> entry = citer.next();
-                    extractValue(obj, entry);
+                    BaseObjectWrapper.extractValue(obj, entry,fieldsMap,fieldContents);
                 }
 
             }
@@ -196,19 +196,7 @@ public V getEntity(P id) throws ServiceException {
         return obj;
     }
 
-    private void extractValue(V obj, Map.Entry<String, Object> entry) throws Exception {
-        String key = entry.getKey();
-        if (fieldsMap.containsKey(key)) {
-            Method method = fieldsMap.get(key).getSetMethod();
-            Class<?> paramType = method.getParameterTypes()[0];
-            method.invoke(obj, ConvertUtil.parseParameter(paramType, entry.getValue()));
-        }
-        if (key.equalsIgnoreCase("_id")) {
-            Method method = AnnotationRetriever.getPrimaryField(fieldContents).getSetMethod();
-            Class<?> paramType = method.getParameterTypes()[0];
-            method.invoke(obj, ConvertUtil.parseParameter(paramType, entry.getValue()));
-        }
-    }
+
 
     @Override
     public void queryBySelectId(PageQuery<Map<String, Object>> query) throws ServiceException {
@@ -262,7 +250,7 @@ public List<V> queryByField(String fieldName, Const.OPERATOR oper, Object... fie
                         V obj = type.getDeclaredConstructor().newInstance();
                         while (citer.hasNext()) {
                             Map.Entry<String, Object> entry = citer.next();
-                            extractValue(obj, entry);
+                            BaseObjectWrapper.extractValue(obj, entry,fieldsMap,fieldContents);
                         }
                         retList.add(obj);
                     }
@@ -282,13 +270,20 @@ public List<V> queryByField(PropertyFunction<V, ?> function, Const.OPERATOR oper
     }
 
     @Override
-    public List<V> queryByFieldOrderBy(String orderByStr, String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
+    public List<V> queryByFieldOrderBy(String orderField, boolean ascDesc, String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
         return null;
     }
 
     @Override
-    public List<V> queryByFieldOrderBy(String orderByStr, PropertyFunction<V, ?> function, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
-        return null;
+    public List<V> queryByFieldOrderBy(PropertyFunction<V, ?> orderField, boolean ascDesc, PropertyFunction<V, ?> queryField, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
+        String orderFieldName = AnnotationRetriever.getFieldName(orderField);
+        String queryFieldName = AnnotationRetriever.getFieldName(queryField);
+        if(!StrUtil.isNotBlank(orderFieldName) || !StrUtil.isNotBlank(queryFieldName)){
+            return queryByFieldOrderBy(orderFieldName,ascDesc,queryFieldName,oper,fieldValues);
+        }else{
+            throw new ServiceException("");
+        }
+
     }
 
     @Override
@@ -383,7 +378,7 @@ private void doQuery(PageQuery<Map<String, Object>> page, List<V> retList, Searc
                     V obj = type.getDeclaredConstructor().newInstance();
                     while (citer.hasNext()) {
                         Map.Entry<String, Object> entry = citer.next();
-                        extractValue(obj, entry);
+                        BaseObjectWrapper.extractValue(obj, entry,fieldsMap,fieldContents);
                     }
                     retList.add(obj);
                 }
@@ -561,4 +556,5 @@ protected boolean indexExists() {
         }
         return Boolean.FALSE;
     }
+
 }
diff --git a/estool/src/main/java/com/robin/es/util/BaseObjectWrapper.java b/estool/src/main/java/com/robin/es/util/BaseObjectWrapper.java
new file mode 100644
index 00000000..b357522d
--- /dev/null
+++ b/estool/src/main/java/com/robin/es/util/BaseObjectWrapper.java
@@ -0,0 +1,25 @@
+package com.robin.es.util;
+
+import com.robin.core.base.dao.util.AnnotationRetriever;
+import com.robin.core.base.dao.util.FieldContent;
+import com.robin.core.convert.util.ConvertUtil;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+
+public class BaseObjectWrapper {
+    public static <V> void extractValue(V obj, Map.Entry<String, Object> entry, Map<String, FieldContent> fieldsMap, List<FieldContent> fieldContents) throws Exception {
+        String key = entry.getKey();
+        if (fieldsMap.containsKey(key)) {
+            Method method = fieldsMap.get(key).getSetMethod();
+            Class<?> paramType = method.getParameterTypes()[0];
+            method.invoke(obj, ConvertUtil.parseParameter(paramType, entry.getValue()));
+        }
+        if (key.equalsIgnoreCase("_id")) {
+            Method method = AnnotationRetriever.getPrimaryField(fieldContents).getSetMethod();
+            Class<?> paramType = method.getParameterTypes()[0];
+            method.invoke(obj, ConvertUtil.parseParameter(paramType, entry.getValue()));
+        }
+    }
+}
diff --git a/estool/src/main/java/com/robin/es/util/CommEsQueryUtils.java b/estool/src/main/java/com/robin/es/util/CommEsQueryUtils.java
index c14e73ac..b3376a7b 100644
--- a/estool/src/main/java/com/robin/es/util/CommEsQueryUtils.java
+++ b/estool/src/main/java/com/robin/es/util/CommEsQueryUtils.java
@@ -331,7 +331,7 @@ private static Object parseValue(FieldType fieldType, String value) {
         return value;
     }
 
-    private static Object parseValue(@NonNull String columnType, String value) {
+    public static Object parseValue(@NonNull String columnType, String value) {
         Object retVal = null;
         if (!ObjectUtils.isEmpty(value)) {
             switch (columnType) {
diff --git a/estool/src/main/java/com/robin/es/util/MongoQueryUtils.java b/estool/src/main/java/com/robin/es/util/MongoQueryUtils.java
new file mode 100644
index 00000000..80a4081f
--- /dev/null
+++ b/estool/src/main/java/com/robin/es/util/MongoQueryUtils.java
@@ -0,0 +1,53 @@
+package com.robin.es.util;
+
+import com.robin.core.base.dao.util.AnnotationRetriever;
+import com.robin.core.base.dao.util.FieldContent;
+import com.robin.core.base.util.Const;
+import org.bson.conversions.Bson;
+import org.springframework.util.Assert;
+
+import static com.mongodb.client.model.Filters.*;
+
+public class MongoQueryUtils {
+    public static Bson getCondition(FieldContent content, Const.OPERATOR operator, Object[] value) {
+        String columnName = content.getPropertyName();
+        String columnType = AnnotationRetriever.getFieldType(content);
+        Assert.isTrue(value!=null && value.length>1,"");
+        Bson filter=null;
+        switch (operator) {
+            case GE:
+                filter=gte(columnName, CommEsQueryUtils.parseValue(columnType, value[0].toString()));
+                break;
+            case GT:
+                filter=gt(columnName,CommEsQueryUtils.parseValue(columnType, value[0].toString()));
+                break;
+            case LE:
+                filter=lte(columnName,CommEsQueryUtils.parseValue(columnType, value[0].toString()));
+                break;
+            case LT:
+                filter=lt(columnName,CommEsQueryUtils.parseValue(columnType, value[0].toString()));
+                break;
+            case NE:
+                filter=ne(columnName,CommEsQueryUtils.parseValue(columnType, value[0].toString()));
+                break;
+            case NULL:
+                filter=eq(columnName,null);
+                break;
+            case NOTNULL:
+                filter=ne(columnName,null);
+                break;
+            case LLIKE:
+            case RLIKE:
+            case LIKE:
+                filter=regex(columnName,".*?\\" +value[0].toString()+ ".*");
+                break;
+            case BETWEEN:
+                Assert.isTrue(value.length==2,"between must have two parameters");
+                filter=and(lte(columnName,CommEsQueryUtils.parseValue(columnType, value[1].toString())),gte(columnName,CommEsQueryUtils.parseValue(columnType, value[0].toString())));
+                break;
+            default:
+                filter=eq(columnName,CommEsQueryUtils.parseValue(columnType, value[0].toString()));
+        }
+        return filter;
+    }
+}
diff --git a/estool/src/main/java/com/robin/mongodb/service/MongoRepositoryService.java b/estool/src/main/java/com/robin/mongodb/service/MongoRepositoryService.java
index bcf1d676..fc90911d 100644
--- a/estool/src/main/java/com/robin/mongodb/service/MongoRepositoryService.java
+++ b/estool/src/main/java/com/robin/mongodb/service/MongoRepositoryService.java
@@ -1,9 +1,12 @@
 package com.robin.mongodb.service;
 
+import cn.hutool.core.util.StrUtil;
 import com.google.gson.Gson;
+import com.mongodb.BasicDBObject;
 import com.mongodb.MongoClient;
-import com.mongodb.client.MongoCollection;
-import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.*;
+import com.mongodb.client.result.DeleteResult;
+import com.mongodb.client.result.UpdateResult;
 import com.robin.comm.util.json.GsonUtil;
 import com.robin.core.base.dao.util.AnnotationRetriever;
 import com.robin.core.base.dao.util.FieldContent;
@@ -17,30 +20,35 @@
 import com.robin.core.query.util.PageQuery;
 import com.robin.core.sql.util.FilterCondition;
 import com.robin.core.sql.util.FilterConditionBuilder;
+import com.robin.es.util.BaseObjectWrapper;
+import com.robin.es.util.MongoQueryUtils;
 import org.bson.Document;
+import org.bson.conversions.Bson;
 import org.bson.types.ObjectId;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.BeanUtils;
 import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
 import org.springframework.util.ObjectUtils;
 
 import java.io.Serializable;
+import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-public class MongoRepositoryService <V extends BaseObject, P extends Serializable> implements IBaseAnnotationJdbcService<V, P> {
+import static com.mongodb.client.model.Filters.*;
+
+public abstract class MongoRepositoryService <V extends BaseObject, P extends Serializable> implements IBaseAnnotationJdbcService<V, P> {
     private MongoClient client;
     protected Class<V> type;
     protected Class<P> pkType;
-    protected Logger logger = LoggerFactory.getLogger(getClass());
     protected AnnotationRetriever.EntityContent<V> entityContent;
-    protected Gson gson = GsonUtil.getGson();
     protected Map<String, FieldContent> fieldsMap;
     protected List<FieldContent> fieldContents;
+
     public MongoRepositoryService(){
         Type genericSuperClass = getClass().getGenericSuperclass();
         ParameterizedType parametrizedType;
@@ -63,114 +71,262 @@ public MongoRepositoryService(){
 
     @Override
     public P saveEntity(V vo) throws ServiceException {
-        try {
+        try(ClientSession session=client.startSession()) {
+            session.startTransaction();
             String databaseName = entityContent.getSchema();
             String collectionName = entityContent.getTableName();
-            MongoDatabase database = client.getDatabase(databaseName);
-            Assert.notNull(database, "database is null");
-            MongoCollection<Document> mongoCollection = database.getCollection(collectionName);
-            Assert.notNull(mongoCollection, "");
+            MongoCollection<Document> mongoCollection = getCollection(databaseName, collectionName);
 
-            Document document =null;
             Map<String, Object> objectMap = new HashMap<>();
+            Document document=parse(vo,objectMap);
+            document.putAll(objectMap);
+            mongoCollection.insertOne(session,document);
+            ObjectId id=document.getObjectId("_id");
+            session.commitTransaction();
+            return (P)id.toString();
+        }catch (Exception ex){
+            throw new ServiceException(ex);
+        }
+    }
+    private Document parse(V vo,Map<String, Object> objectMap) throws Exception{
+        Document document =null;
+
+        for(FieldContent content:fieldContents){
+            if(content.isPrimary()){
+                Object pkObj=content.getGetMethod().invoke(vo);
+                if (!ObjectUtils.isEmpty(pkObj)) {
+                    document=new Document("_id",pkObj.toString());
+                }
+            }else{
+                Object obj=content.getGetMethod().invoke(vo);
+                if(!ObjectUtils.isEmpty(obj)) {
+                    objectMap.put(content.getPropertyName(), obj);
+                }
+            }
+        }
+        if(document==null){
+            document=new Document();
+        }
+        return document;
+    }
+    private MongoCollection<Document> getCollection(String databaseName, String collectionName) {
+        MongoDatabase database = client.getDatabase(databaseName);
+
+        Assert.notNull(database, "database is null");
+        MongoCollection<Document> mongoCollection = database.getCollection(collectionName);
+        Assert.notNull(mongoCollection, "");
+        return mongoCollection;
+    }
+
+    @Override
+    public int updateEntity(V vo) throws ServiceException {
+        try(ClientSession session=client.startSession()){
+            session.startTransaction();
+            String databaseName = entityContent.getSchema();
+            String collectionName = entityContent.getTableName();
+            MongoCollection<Document> mongoCollection = getCollection(databaseName, collectionName);
+            BasicDBObject filter=new BasicDBObject();
+            BasicDBObject updates=new BasicDBObject();
+
             for(FieldContent content:fieldContents){
                 if(content.isPrimary()){
                     Object pkObj=content.getGetMethod().invoke(vo);
                     if (!ObjectUtils.isEmpty(pkObj)) {
-                        document=new Document("_id",pkObj.toString());
+                        filter.put("_id",new ObjectId(pkObj.toString()));
                     }
                 }else{
                     Object obj=content.getGetMethod().invoke(vo);
                     if(!ObjectUtils.isEmpty(obj)) {
-                        objectMap.put(content.getPropertyName(), obj);
+                        updates.put(content.getPropertyName(), obj);
                     }
                 }
             }
-            if(ObjectUtils.isEmpty(document)) {
-                document = new Document();
+            List<Document> documents= findBy(mongoCollection,filter,null);
+            if(CollectionUtils.isEmpty(documents)){
+                throw new ServiceException("_id "+filter.get("_id").toString()+" doesn't Exists");
             }
-            document.putAll(objectMap);
-            mongoCollection.insertOne(document);
-            ObjectId id=document.getObjectId("_id");
-            return (P)id.toString();
+            UpdateResult result= mongoCollection.updateOne(session, filter, updates);
+            session.commitTransaction();
+            return Long.valueOf(result.getMatchedCount()).intValue();
         }catch (Exception ex){
-            throw new ServiceException(ex);
-        }
-    }
 
-    @Override
-    public int updateEntity(V vo) throws ServiceException {
+        }
         return 0;
     }
 
     @Override
-    public int deleteEntity(P[] vo) throws ServiceException {
+    public int deleteEntity(P[] ids) throws ServiceException {
+        try(ClientSession session=client.startSession()) {
+            String databaseName = entityContent.getSchema();
+            String collectionName = entityContent.getTableName();
+            MongoCollection<Document> mongoCollection = getCollection(databaseName, collectionName);
+            Bson filter=in("_id", Stream.of(ids).map(f->new ObjectId(f.toString())).collect(Collectors.toList()));
+            DeleteResult result= mongoCollection.deleteMany(session,filter);
+            session.commitTransaction();
+            return Long.valueOf(result.getDeletedCount()).intValue();
+        }catch (Exception ex){
+
+        }
         return 0;
     }
 
     @Override
     public int deleteByField(String field, Object value) throws ServiceException {
-        return 0;
+        try(ClientSession session=client.startSession()){
+            String databaseName = entityContent.getSchema();
+            String collectionName = entityContent.getTableName();
+            MongoCollection<Document> mongoCollection = getCollection(databaseName, collectionName);
+            if(fieldsMap.containsKey(field)) {
+                Bson filter = eq(field, value);
+                DeleteResult result=mongoCollection.deleteMany(session,filter);
+                session.commitTransaction();
+                return Long.valueOf(result.getDeletedCount()).intValue();
+            }else {
+                throw new ServiceException("field not exists");
+            }
+        }catch (Exception ex){
+            throw new ServiceException(ex);
+        }
     }
 
     @Override
     public int deleteByField(PropertyFunction<V, ?> function, Object value) throws ServiceException {
-        return 0;
+        String fieldName = AnnotationRetriever.getFieldName(function);
+        return deleteByField(fieldName,value);
     }
 
     @Override
     public V getEntity(P id) throws ServiceException {
-        return null;
+        try {
+            String databaseName = entityContent.getSchema();
+            String collectionName = entityContent.getTableName();
+            MongoCollection<Document> mongoCollection = getCollection(databaseName, collectionName);
+            List<Document> documents = findBy(mongoCollection,eq("_id",new ObjectId(id.toString())),null);
+            V vo=type.getDeclaredConstructor().newInstance();
+            if(!CollectionUtils.isEmpty(documents)){
+                if(documents.size()>1){
+                    throw new ServiceException("find more than one");
+                }
+                Document document=documents.get(0);
+                Iterator<Map.Entry<String,Object>> citer=document.entrySet().iterator();
+                while (citer.hasNext()) {
+                    Map.Entry<String, Object> entry = citer.next();
+                    BaseObjectWrapper.extractValue(vo, entry,fieldsMap,fieldContents);
+                }
+            }
+            return vo;
+        }catch (Exception ex){
+            throw new ServiceException(ex);
+        }
     }
 
     @Override
     public void queryBySelectId(PageQuery<Map<String, Object>> query) throws ServiceException {
-
+        throw new ServiceException("operate not supported!");
     }
 
     @Override
     public List<Map<String, Object>> queryByPageSql(String sql, PageQuery<Map<String, Object>> pageQuery) throws ServiceException {
-        return null;
+        throw new ServiceException("operate not supported!");
     }
 
     @Override
     public void executeBySelectId(PageQuery<Map<String, Object>> query) throws ServiceException {
-
+        throw new ServiceException("operate not supported!");
     }
 
     @Override
     public void queryBySql(String querySQL, String countSql, String[] displayname, PageQuery<Map<String, Object>> pageQuery) throws ServiceException {
-
+        throw new ServiceException("operate not supported!");
     }
 
     @Override
     public List<Map<String, Object>> queryBySql(String sqlstr, Object... objects) throws ServiceException {
-        return null;
+        throw new ServiceException("operate not supported!");
     }
 
     @Override
     public int queryByInt(String querySQL, Object... objects) throws ServiceException {
-        return 0;
+        throw new ServiceException("operate not supported!");
     }
 
     @Override
     public List<V> queryByField(String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
-        return null;
+        try{
+            if(!fieldsMap.containsKey(fieldName)){
+                throw new ServiceException("");
+            }
+            String databaseName = entityContent.getSchema();
+            String collectionName = entityContent.getTableName();
+            MongoCollection<Document> mongoCollection = getCollection(databaseName, collectionName);
+            Bson filter= MongoQueryUtils.getCondition(fieldsMap.get(fieldName),oper,fieldValues);
+            BasicDBObject dbObject=new BasicDBObject();
+            dbObject.put("_id",1);
+            List<Document> list=findBy(mongoCollection,filter,dbObject);
+            List<V> retList=new ArrayList<>();
+            if(!CollectionUtils.isEmpty(list)){
+                V obj = type.getDeclaredConstructor().newInstance();
+                for(Document document:list) {
+                    Iterator<Map.Entry<String, Object>> citer = document.entrySet().iterator();
+                    while (citer.hasNext()) {
+                        Map.Entry<String, Object> entry = citer.next();
+                        BaseObjectWrapper.extractValue(obj, entry, fieldsMap, fieldContents);
+                    }
+                }
+                retList.add(obj);
+            }
+            return retList;
+        }catch (Exception ex){
+            throw new ServiceException(ex);
+        }
     }
 
     @Override
     public List<V> queryByField(PropertyFunction<V, ?> function, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
-        return null;
+        String fieldName = AnnotationRetriever.getFieldName(function);
+        return queryByField(fieldName, oper, fieldValues);
     }
 
     @Override
-    public List<V> queryByFieldOrderBy(String orderByStr, String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
-        return null;
+    public List<V> queryByFieldOrderBy(String orderField, boolean ascDesc, String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
+        try{
+            if(!fieldsMap.containsKey(fieldName)){
+                throw new ServiceException("");
+            }
+            String databaseName = entityContent.getSchema();
+            String collectionName = entityContent.getTableName();
+            MongoCollection<Document> mongoCollection = getCollection(databaseName, collectionName);
+            Bson filter= MongoQueryUtils.getCondition(fieldsMap.get(fieldName),oper,fieldValues);
+            BasicDBObject dbObject=new BasicDBObject();
+            dbObject.put(orderField,ascDesc?1:-1);
+            List<Document> list=findBy(mongoCollection,filter,dbObject);
+            List<V> retList=new ArrayList<>();
+            if(!CollectionUtils.isEmpty(list)){
+                V obj = type.getDeclaredConstructor().newInstance();
+                for(Document document:list) {
+                    Iterator<Map.Entry<String, Object>> citer = document.entrySet().iterator();
+                    while (citer.hasNext()) {
+                        Map.Entry<String, Object> entry = citer.next();
+                        BaseObjectWrapper.extractValue(obj, entry, fieldsMap, fieldContents);
+                    }
+                }
+                retList.add(obj);
+            }
+            return retList;
+        }catch (Exception ex){
+            throw new ServiceException(ex);
+        }
     }
 
     @Override
-    public List<V> queryByFieldOrderBy(String orderByStr, PropertyFunction<V, ?> function, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
-        return null;
+    public List<V> queryByFieldOrderBy(PropertyFunction<V, ?> orderField, boolean ascDesc, PropertyFunction<V, ?> queryField, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
+        String orderFieldName = AnnotationRetriever.getFieldName(orderField);
+        String queryFieldName = AnnotationRetriever.getFieldName(queryField);
+        if(!StrUtil.isNotBlank(orderFieldName) || !StrUtil.isNotBlank(queryFieldName)){
+            return queryByFieldOrderBy(orderFieldName,ascDesc,queryFieldName,oper,fieldValues);
+        }else{
+            throw new ServiceException("");
+        }
     }
 
     @Override
@@ -180,41 +336,69 @@ public List<V> queryAll() throws ServiceException {
 
     @Override
     public List<V> queryByVO(V vo, String orderByStr) throws ServiceException {
-        return null;
+        throw new ServiceException("");
     }
 
     @Override
     public void queryByCondition(FilterCondition filterCondition, PageQuery<V> pageQuery) {
-
+        throw new ServiceException("operate not supported!");
     }
 
     @Override
     public void queryByCondition(FilterConditionBuilder filterConditions, PageQuery<V> pageQuery) {
-
+        throw new ServiceException("operate not supported!");
     }
 
     @Override
     public List<V> queryByCondition(FilterCondition filterCondition) {
-        return null;
+        throw new ServiceException("operate not supported!");
     }
 
     @Override
     public V getByField(String fieldName, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
-        return null;
+        List<V> list=queryByField(fieldName,oper,fieldValues);
+        Assert.isTrue(!CollectionUtils.isEmpty(list) && list.size()==1,"");
+        return list.get(0);
     }
 
     @Override
     public V getByField(PropertyFunction<V, ?> function, Const.OPERATOR oper, Object... fieldValues) throws ServiceException {
-        return null;
+        List<V> list=queryByField(function,oper,fieldValues);
+        Assert.isTrue(!CollectionUtils.isEmpty(list) && list.size()==1,"");
+        return list.get(0);
     }
 
     @Override
     public int countByCondition(FilterCondition filterCondition) {
-        return 0;
+        throw new ServiceException("operate not supported!");
     }
 
     @Override
     public int batchUpdate(List<V> list) {
-        return 0;
+        throw new ServiceException("operate not supported!");
+    }
+    private void extractValue(V obj, Map.Entry<String, Object> entry) throws Exception {
+        String key = entry.getKey();
+        if (fieldsMap.containsKey(key)) {
+            Method method = fieldsMap.get(key).getSetMethod();
+            Class<?> paramType = method.getParameterTypes()[0];
+            method.invoke(obj, ConvertUtil.parseParameter(paramType, entry.getValue()));
+        }
+        if (key.equalsIgnoreCase("_id")) {
+            Method method = AnnotationRetriever.getPrimaryField(fieldContents).getSetMethod();
+            Class<?> paramType = method.getParameterTypes()[0];
+            method.invoke(obj, ConvertUtil.parseParameter(paramType, entry.getValue()));
+        }
+    }
+
+    public static List<Document> findBy(MongoCollection collection, Bson filter,Bson sort) {
+        List<Document> results = new ArrayList<>();
+        FindIterable<Document> iterables =sort==null?collection.find(filter):collection.find(filter).sort(sort);
+        MongoCursor<Document> cursor = iterables.iterator();
+        while (cursor.hasNext()) {
+            results.add(cursor.next());
+        }
+        return results;
     }
+
 }
diff --git a/example/base-example/src/main/java/com/robin/basis/model/user/SysUser.java b/example/base-example/src/main/java/com/robin/basis/model/user/SysUser.java
index 6f6cdb4c..20bfa93b 100644
--- a/example/base-example/src/main/java/com/robin/basis/model/user/SysUser.java
+++ b/example/base-example/src/main/java/com/robin/basis/model/user/SysUser.java
@@ -55,6 +55,4 @@ public class SysUser extends BaseObject {
     private String avatar;
     private String nickName;
     private String sex;
-    private LocalDateTime createTime;
-    private LocalDateTime updateTime;
 }
diff --git a/example/base-example/src/main/java/com/robin/basis/service/system/LoginService.java b/example/base-example/src/main/java/com/robin/basis/service/system/LoginService.java
index eb195e31..4e1b1615 100644
--- a/example/base-example/src/main/java/com/robin/basis/service/system/LoginService.java
+++ b/example/base-example/src/main/java/com/robin/basis/service/system/LoginService.java
@@ -142,7 +142,7 @@ public SysUser getUserInfo(String userName) {
         return users.get(0);
     }
 
-    public List<Long> getUserOrgs(Long userId) {
+    public List<Long> getUserRoles(Long userId) {
         FilterConditionBuilder builder = new FilterConditionBuilder();
         builder.addEq(SysUserRole::getUserId, userId).addEq(SysUserRole::getStatus, Const.VALID);
         List<SysUserRole> roles = sysUserRoleService.queryByCondition(builder.build());
diff --git a/example/base-example/src/main/java/com/robin/basis/service/system/SysResourceService.java b/example/base-example/src/main/java/com/robin/basis/service/system/SysResourceService.java
index 40f5b98b..7e06cf89 100644
--- a/example/base-example/src/main/java/com/robin/basis/service/system/SysResourceService.java
+++ b/example/base-example/src/main/java/com/robin/basis/service/system/SysResourceService.java
@@ -93,13 +93,13 @@ public Map<String, Object> getUserRights(Long userId) {
         if (!query1.getRecordSet().isEmpty()) {
             try {
                 Map<String, List<Map<String, Object>>> resTypeMap = CollectionMapConvert.convertToMapByParentMapKey(query1.getRecordSet(), "assignType");
-                Map<String, Map<String, Object>> accessResMap = resTypeMap.get("NULL").stream().collect(Collectors.toMap(f -> f.get("id").toString(), f -> f));
+                Map<String, Map<String, Object>> accessResMap = resTypeMap.get("0").stream().collect(Collectors.toMap(f -> f.get("id").toString(), f -> f));
                 if (!CollectionUtils.isEmpty(resTypeMap.get(Const.RESOURCE_ASSIGN_ACCESS))) {
                     accessResMap.putAll(resTypeMap.get(Const.RESOURCE_ASSIGN_ACCESS).stream().collect(Collectors.toMap(f -> f.get("id").toString(), f -> f)));
                 }
                 //positive assign
                 if (resTypeMap.containsKey(Const.RESOURCE_ASSIGN_ACCESS)) {
-                    for (Map<String, Object> tmap : resTypeMap.get(Const.RESOURCE_ASSIGN_DENIED)) {
+                    for (Map<String, Object> tmap : resTypeMap.get(Const.RESOURCE_ASSIGN_ACCESS)) {
                         if (!accessResMap.containsKey(tmap.get("id").toString())) {
                             accessResMap.put(tmap.get("id").toString(), tmap);
                         }
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/AbstractCloudStorageFileSystemAccessor.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/AbstractCloudStorageFileSystemAccessor.java
index f367c09e..d41d219e 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/AbstractCloudStorageFileSystemAccessor.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/AbstractCloudStorageFileSystemAccessor.java
@@ -36,13 +36,13 @@ public void init(DataCollectionMeta meta) {
     @Override
     public synchronized Pair<BufferedReader, InputStream> getInResourceByReader(String resourcePath) throws IOException {
         InputStream inputStream = getInputStreamByConfig(resourcePath);
-        return Pair.of(getReaderByPath(resourcePath, inputStream, colmeta.getEncode()), inputStream);
+        return Pair.of(getReaderByPath(resourcePath, inputStream, getEncode()), inputStream);
     }
 
     @Override
     public synchronized Pair<BufferedWriter, OutputStream> getOutResourceByWriter(String resourcePath) throws IOException {
         OutputStream outputStream = getOutputStream(resourcePath);
-        return Pair.of(getWriterByPath(resourcePath, outputStream, colmeta.getEncode()), outputStream);
+        return Pair.of(getWriterByPath(resourcePath, outputStream, getEncode()), outputStream);
     }
 
     @Override
@@ -93,7 +93,10 @@ protected String getBucketName(DataCollectionMeta meta) {
      * @throws IOException
      */
     protected abstract OutputStream getOutputStream(String path) throws IOException;
-
+    protected abstract OutputStream getOutputStream(String path,int uploadPartSize) throws IOException;
+    public String getEncode(){
+        return colmeta==null?"UTF8":colmeta.getEncode();
+    }
 
     protected String getContentType(DataCollectionMeta meta) {
         return !ObjectUtils.isEmpty(meta.getContent()) && !ObjectUtils.isEmpty(meta.getContent().getContentType()) ? meta.getContent().getContentType() : ResourceConst.DEFAULTCONTENTTYPE;
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/BOSFileSystemAccessor.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/BOSFileSystemAccessor.java
index 047bbd25..f462d828 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/BOSFileSystemAccessor.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/BOSFileSystemAccessor.java
@@ -112,7 +112,12 @@ public boolean putObject(String bucketName, DataCollectionMeta meta, InputStream
 
     @Override
     protected OutputStream getOutputStream(String path) throws IOException {
-        return new BOSOutputStream(client, colmeta,bucketName, path);
+        return new BOSOutputStream(client, colmeta,bucketName, path,0);
+    }
+
+    @Override
+    protected OutputStream getOutputStream(String path, int uploadPartSize) throws IOException {
+        return new BOSOutputStream(client, colmeta,bucketName, path,uploadPartSize);
     }
 
     public static class Builder{
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/COSFileSystemAccessor.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/COSFileSystemAccessor.java
index 9fe0af65..8221c0aa 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/COSFileSystemAccessor.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/COSFileSystemAccessor.java
@@ -172,7 +172,12 @@ public boolean createBucket(String name, Map<String,String> paramMap, Map<String
 
     @Override
     protected OutputStream getOutputStream(String path) throws IOException {
-        return new COSOutputStream(cosClient, colmeta,getBucketName(colmeta),path,regionName);
+        return new COSOutputStream(cosClient, colmeta,getBucketName(colmeta),path,regionName,0);
+    }
+
+    @Override
+    protected OutputStream getOutputStream(String path, int uploadPartSize) throws IOException {
+        return new COSOutputStream(cosClient, colmeta,getBucketName(colmeta),path,regionName,uploadPartSize);
     }
 
     public static class Builder{
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/GCSFileSystemAccessor.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/GCSFileSystemAccessor.java
index 3ba28a32..ff080cd3 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/GCSFileSystemAccessor.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/GCSFileSystemAccessor.java
@@ -184,4 +184,9 @@ protected OutputStream getOutputStream(String path) throws IOException {
         }
         return outputStream;
     }
+
+    @Override
+    protected OutputStream getOutputStream(String path, int uploadPartSize) throws IOException {
+        return getOutputStream(path);
+    }
 }
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/MinioFileSystemAccessor.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/MinioFileSystemAccessor.java
index 4032a437..92c119b1 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/MinioFileSystemAccessor.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/MinioFileSystemAccessor.java
@@ -107,10 +107,13 @@ public void init(){
 
     @Override
     protected synchronized OutputStream getOutputStream(String path) throws IOException {
-        return new MinioOutputStream(new CustomMinioClient(client), colmeta,bucketName,path,region);
+        return new MinioOutputStream(new CustomMinioClient(client), colmeta,bucketName,path,region,0);
     }
 
-
+    @Override
+    protected OutputStream getOutputStream(String path, int uploadPartSize) throws IOException {
+        return new MinioOutputStream(new CustomMinioClient(client), colmeta,bucketName,path,region,uploadPartSize);
+    }
 
     @Override
     public boolean exists(String resourcePath) throws IOException {
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/OBSFileSystemAccessor.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/OBSFileSystemAccessor.java
index 278fad17..878531dd 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/OBSFileSystemAccessor.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/OBSFileSystemAccessor.java
@@ -150,7 +150,11 @@ public OBSFileSystemAccessor build() {
 
     @Override
     protected OutputStream getOutputStream(String path) throws IOException {
-        return new OBSOutputStream(client,colmeta,bucketName,path);
+        return new OBSOutputStream(client,colmeta,bucketName,path,0);
+    }
+    @Override
+    protected OutputStream getOutputStream(String path,int uploadPartSize) throws IOException {
+        return new OBSOutputStream(client,colmeta,bucketName,path,uploadPartSize);
     }
 
     public ObsClient getClient() {
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/OSSFileSystemAccessor.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/OSSFileSystemAccessor.java
index 00a5cc0a..e886dbdf 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/OSSFileSystemAccessor.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/OSSFileSystemAccessor.java
@@ -70,7 +70,11 @@ public void init() {
 
     @Override
     protected synchronized OutputStream getOutputStream(String path) throws IOException {
-        return new OSSOutputStream(ossClient, colmeta, getBucketName(colmeta), path, region);
+        return new OSSOutputStream(ossClient, colmeta, getBucketName(colmeta), path, region,0);
+    }
+    @Override
+    protected synchronized OutputStream getOutputStream(String path,int uploadPartSize) throws IOException {
+        return new OSSOutputStream(ossClient, colmeta, getBucketName(colmeta), path, region,uploadPartSize);
     }
 
     @Override
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/QiniuFileSystemAccessor.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/QiniuFileSystemAccessor.java
index d918df4a..641ceab9 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/QiniuFileSystemAccessor.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/QiniuFileSystemAccessor.java
@@ -138,7 +138,11 @@ public boolean putObject(String bucketName, DataCollectionMeta meta, InputStream
 
     @Override
     protected synchronized OutputStream getOutputStream(String path) throws IOException {
-        return new QiniuOutputStream(client, uploadManager, colmeta, auth, getBucketName(colmeta), path, urlPrefix);
+        return new QiniuOutputStream(client, uploadManager, colmeta, auth, getBucketName(colmeta), path, urlPrefix,0);
+    }
+    @Override
+    protected synchronized OutputStream getOutputStream(String path,int uploadPartSize) throws IOException {
+        return new QiniuOutputStream(client, uploadManager, colmeta, auth, getBucketName(colmeta), path, urlPrefix,uploadPartSize);
     }
 
     public InputStream getObject(@NonNull String bucketName, @NonNull String key) {
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/S3FileSystemAccessor.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/S3FileSystemAccessor.java
index 61529e2a..ec02f053 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/S3FileSystemAccessor.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/S3FileSystemAccessor.java
@@ -88,7 +88,11 @@ public boolean putObject(String bucketName, DataCollectionMeta meta, InputStream
 
     @Override
     protected synchronized OutputStream getOutputStream(String path) throws IOException {
-        return new S3OutputStream(client, colmeta,getBucketName(colmeta),path);
+        return new S3OutputStream(client, colmeta,getBucketName(colmeta),path,0);
+    }
+    @Override
+    protected synchronized OutputStream getOutputStream(String path,int uploadPartSize) throws IOException {
+        return new S3OutputStream(client, colmeta,getBucketName(colmeta),path,uploadPartSize);
     }
 
     @Override
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/AbstractUploadPartOutputStream.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/AbstractUploadPartOutputStream.java
index 6108492b..771b47da 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/AbstractUploadPartOutputStream.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/AbstractUploadPartOutputStream.java
@@ -4,6 +4,7 @@
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
+import com.robin.core.base.util.FileUtils;
 import com.robin.core.base.util.ResourceConst;
 import com.robin.core.fileaccess.meta.DataCollectionMeta;
 import lombok.extern.slf4j.Slf4j;
@@ -48,6 +49,7 @@ public abstract class AbstractUploadPartOutputStream extends OutputStream {
     protected ListeningExecutorService guavaExecutor;
     protected int uploadThread = ResourceConst.DEFAULTSTORAGEUPLOADTHREAD;
     protected List<ListenableFuture<Boolean>> futures = new ArrayList<>();
+    protected int defaultUploadPartSize =ResourceConst.DEFAULTCACHEOFFHEAPSIZE;
 
     protected void init() {
         if (!asyncTag && !ObjectUtils.isEmpty(meta) && !CollectionUtils.isEmpty(meta.getResourceCfgMap()) && !ObjectUtils.isEmpty(meta.getResourceCfgMap().get(ResourceConst.USEASYNCUPLOAD)) && "true".equalsIgnoreCase(meta.getResourceCfgMap().get(ResourceConst.USEASYNCUPLOAD).toString())) {
@@ -172,12 +174,16 @@ private void doUploadPart() throws IOException {
     }
 
     protected String getContentType(DataCollectionMeta meta) {
-        return !ObjectUtils.isEmpty(meta.getContent()) && !ObjectUtils.isEmpty(meta.getContent().getContentType()) ? meta.getContent().getContentType() : ResourceConst.DEFAULTCONTENTTYPE;
+        if(!ObjectUtils.isEmpty(meta)) {
+            return !ObjectUtils.isEmpty(meta.getContent()) && !ObjectUtils.isEmpty(meta.getContent().getContentType()) ? meta.getContent().getContentType() : ResourceConst.DEFAULTCONTENTTYPE;
+        }else{
+            return FileUtils.parseFile(path).getContentType();
+        }
     }
 
     protected void initHeap() {
         int initLength =!ObjectUtils.isEmpty(meta) && !ObjectUtils.isEmpty(meta.getResourceCfgMap().get(ResourceConst.DEFAULTCACHEOFFHEAPSIZEKEY))
-                ? Integer.parseInt(meta.getResourceCfgMap().get(ResourceConst.DEFAULTCACHEOFFHEAPSIZEKEY).toString()) : ResourceConst.DEFAULTCACHEOFFHEAPSIZE;
+                ? Integer.parseInt(meta.getResourceCfgMap().get(ResourceConst.DEFAULTCACHEOFFHEAPSIZEKEY).toString()) : defaultUploadPartSize;
         segment = MemorySegmentFactory.allocateOffHeapUnsafeMemory(initLength, this, new Thread() {
         });
         buffer = segment.getOffHeapBuffer();
@@ -236,4 +242,10 @@ protected void free() {
 
         protected abstract boolean uploadPartAsync() throws IOException;
     }
+
+    void setDefaultUploadPartSize(int defaultUploadPartSize) {
+        if(defaultUploadPartSize>0) {
+            this.defaultUploadPartSize = defaultUploadPartSize;
+        }
+    }
 }
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/BOSOutputStream.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/BOSOutputStream.java
index 8d2917de..52dbe4f9 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/BOSOutputStream.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/BOSOutputStream.java
@@ -23,11 +23,12 @@ private BOSOutputStream(){
 
     }
 
-    public BOSOutputStream(BosClient client, DataCollectionMeta meta, String bucketName, String path) {
+    public BOSOutputStream(BosClient client, DataCollectionMeta meta, String bucketName, String path,int defaultPartSize) {
         this.client = client;
         this.meta = meta;
         this.bucketName = bucketName;
         this.path = path;
+        setDefaultUploadPartSize(defaultPartSize);
         init();
     }
 
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/COSOutputStream.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/COSOutputStream.java
index a1e7006c..1a46f84c 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/COSOutputStream.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/COSOutputStream.java
@@ -25,12 +25,13 @@ private COSOutputStream(){
 
     }
 
-    public COSOutputStream(COSClient client, DataCollectionMeta meta, String bucketName, String path, String region) {
+    public COSOutputStream(COSClient client, DataCollectionMeta meta, String bucketName, String path, String region,int defaultPartSize) {
         this.client = client;
         this.meta = meta;
         this.bucketName = bucketName;
         this.path = path;
         this.region = region;
+        setDefaultUploadPartSize(defaultPartSize);
         init();
     }
 
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/MinioOutputStream.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/MinioOutputStream.java
index cb389d3b..fa924cb7 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/MinioOutputStream.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/MinioOutputStream.java
@@ -31,12 +31,13 @@ private MinioOutputStream(){
 
     }
 
-    public MinioOutputStream(CustomMinioClient client, DataCollectionMeta meta, String bucketName, String path, String region) {
+    public MinioOutputStream(CustomMinioClient client, DataCollectionMeta meta, String bucketName, String path, String region,int defaultPartSize) {
         this.client = client;
         this.bucketName = bucketName;
         this.path = path;
         this.region=region;
         this.meta=meta;
+        setDefaultUploadPartSize(defaultPartSize);
         init();
     }
     protected void initiateUpload() throws IOException{
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/OBSOutputStream.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/OBSOutputStream.java
index 0c751575..a042b366 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/OBSOutputStream.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/OBSOutputStream.java
@@ -18,11 +18,12 @@ public class OBSOutputStream extends AbstractUploadPartOutputStream{
     private OBSOutputStream(){
 
     }
-    public OBSOutputStream(ObsClient client, DataCollectionMeta meta, String bucketName, String path) {
+    public OBSOutputStream(ObsClient client, DataCollectionMeta meta, String bucketName, String path,int defaultPartSize) {
         this.client = client;
         this.meta = meta;
         this.bucketName = bucketName;
         this.path = path;
+        setDefaultUploadPartSize(defaultPartSize);
         init();
     }
     @Override
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/OSSOutputStream.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/OSSOutputStream.java
index b0221140..f29aa6e9 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/OSSOutputStream.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/OSSOutputStream.java
@@ -25,12 +25,13 @@ private OSSOutputStream(){
 
     }
 
-    public OSSOutputStream(OSS client, DataCollectionMeta meta, String bucketName, String path, String region) {
+    public OSSOutputStream(OSS client, DataCollectionMeta meta, String bucketName, String path, String region,int defaultPartSize) {
         this.client = client;
         this.meta = meta;
         this.bucketName = bucketName;
         this.path = path;
         this.region = region;
+        setDefaultUploadPartSize(defaultPartSize);
         init();
     }
 
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/QiniuOutputStream.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/QiniuOutputStream.java
index a1ecac35..70710a20 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/QiniuOutputStream.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/QiniuOutputStream.java
@@ -36,7 +36,7 @@ private QiniuOutputStream(){
 
     }
 
-    public QiniuOutputStream(Client client, UploadManager manager, DataCollectionMeta colmeta, Auth auth, String bucketName, String path, String urlPrefix) {
+    public QiniuOutputStream(Client client, UploadManager manager, DataCollectionMeta colmeta, Auth auth, String bucketName, String path, String urlPrefix,int defaultPartSize) {
         this.client = client;
         this.meta = colmeta;
         this.bucketName = bucketName;
@@ -45,6 +45,7 @@ public QiniuOutputStream(Client client, UploadManager manager, DataCollectionMet
         this.auth = auth;
         this.manager = manager;
         log.info("using urlPrefix {}", urlPrefix);
+        setDefaultUploadPartSize(defaultPartSize);
         initHeap();
     }
 
diff --git a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/S3OutputStream.java b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/S3OutputStream.java
index 33e7f5d8..118d51a3 100644
--- a/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/S3OutputStream.java
+++ b/hadooptool/src/main/java/com/robin/comm/fileaccess/fs/outputstream/S3OutputStream.java
@@ -17,11 +17,12 @@ private S3OutputStream() {
 
     }
 
-    public S3OutputStream(S3Client client, DataCollectionMeta meta, String bucketName, String path) {
+    public S3OutputStream(S3Client client, DataCollectionMeta meta, String bucketName, String path,int defaultPartSize) {
         this.client = client;
         this.bucketName = bucketName;
         this.path = path;
         this.meta = meta;
+        setDefaultUploadPartSize(defaultPartSize);
         init();
     }
 
diff --git a/mybatisproj/pom.xml b/mybatisproj/pom.xml
index 4adf2348..31e355e5 100644
--- a/mybatisproj/pom.xml
+++ b/mybatisproj/pom.xml
@@ -84,6 +84,46 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>com.qiniu</groupId>
+            <artifactId>qiniu-java-sdk</artifactId>
+            <version>7.16.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.squareup.okhttp3</groupId>
+                    <artifactId>okhttp</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>io.minio</groupId>
+            <artifactId>minio</artifactId>
+            <version>8.4.0</version>
+            <optional>true</optional>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.robin</groupId>
+            <artifactId>hadooptool</artifactId>
+            <version>1.0</version>
+        </dependency>
 
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -92,7 +132,7 @@
 		 <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-boot-starter</artifactId>
-            <version>3.4.2</version>
+            <version>3.4.3.4</version>
         </dependency>
 
         <dependency>
diff --git a/mybatisproj/src/main/java/com/robin/basis/controller/biz/CustomerController.java b/mybatisproj/src/main/java/com/robin/basis/controller/biz/CustomerController.java
new file mode 100644
index 00000000..f66ea280
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/controller/biz/CustomerController.java
@@ -0,0 +1,34 @@
+package com.robin.basis.controller.biz;
+
+import com.robin.basis.dto.CustomerDTO;
+import com.robin.basis.dto.query.CustomerQueryDTO;
+import com.robin.basis.mapper.biz.CustomerMapper;
+import com.robin.basis.service.biz.ICustomerService;
+import com.robin.basis.utils.WebUtils;
+import com.robin.biz.model.Customer;
+import com.robin.core.web.controller.AbstractMyBatisController;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/customer")
+public class CustomerController extends AbstractMyBatisController<ICustomerService, CustomerMapper, Customer,Long> {
+    @GetMapping
+    public Map<String,Object> list(CustomerQueryDTO dto){
+        return WebUtils.toPageVO(queryPage(dto, CustomerDTO.class),null);
+    }
+    @PostMapping
+    public Map<String,Object> save(@RequestBody Map<String,Object> reqMap){
+        return doSave(reqMap,null);
+    }
+    @PutMapping
+    public Map<String,Object> update(@RequestBody Map<String,Object> reqMap){
+        return doUpdate(reqMap,Long.valueOf(reqMap.get("id").toString()));
+    }
+    @DeleteMapping
+    public Map<String,Object> delete(@RequestBody List<Long> ids ){
+        return doDeleteLogic(ids);
+    }
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/controller/system/SysCodeSetController.java b/mybatisproj/src/main/java/com/robin/basis/controller/system/SysCodeSetController.java
index ae94f964..880bae2a 100644
--- a/mybatisproj/src/main/java/com/robin/basis/controller/system/SysCodeSetController.java
+++ b/mybatisproj/src/main/java/com/robin/basis/controller/system/SysCodeSetController.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.robin.basis.dto.SysCodeDTO;
+import com.robin.basis.dto.SysCodeSetDTO;
 import com.robin.basis.mapper.SysCodeSetMapper;
 import com.robin.basis.model.AbstractMybatisModel;
 import com.robin.basis.model.system.SysCode;
@@ -25,10 +26,15 @@
 import java.util.stream.Collectors;
 
 @RestController
-@RequestMapping("/system/dict/")
+@RequestMapping("/system/dict")
 public class SysCodeSetController extends AbstractMyBatisController<ISysCodeSetService, SysCodeSetMapper,SysCodeSet,Long> {
     @Resource
-     private ISysCodeService sysCodeService;
+    private ISysCodeService sysCodeService;
+
+    @GetMapping
+    public Map<String,Object> list(SysCodeSetDTO dto){
+        return wrapObject(service.list(dto));
+    }
 
     @GetMapping("/data/{id}")
     public Map<String,Object> getById(@PathVariable Long id){
diff --git a/mybatisproj/src/main/java/com/robin/basis/controller/system/SysRoleContorller.java b/mybatisproj/src/main/java/com/robin/basis/controller/system/SysRoleContorller.java
index 9d7e47f5..4498e130 100644
--- a/mybatisproj/src/main/java/com/robin/basis/controller/system/SysRoleContorller.java
+++ b/mybatisproj/src/main/java/com/robin/basis/controller/system/SysRoleContorller.java
@@ -52,7 +52,7 @@ public Map<String, Object> updateRole(@RequestBody SysRoleDTO dto){
 	@GetMapping("/all")
 	public Map<String,Object> showAllRole(){
 		try{
-			List<SysRole> roles=service.queryByField(SysRole::getStatus, Const.OPERATOR.EQ,Const.VALID);
+			List<SysRole> roles=service.queryValid();
 			return wrapObject(roles.stream().map(SysRoleDTO::fromVO).collect(Collectors.toList()));
 		}catch (Exception ex){
 			return wrapError(ex);
diff --git a/mybatisproj/src/main/java/com/robin/basis/controller/system/TenantInfoController.java b/mybatisproj/src/main/java/com/robin/basis/controller/system/TenantInfoController.java
index 9c993e62..3d04117c 100644
--- a/mybatisproj/src/main/java/com/robin/basis/controller/system/TenantInfoController.java
+++ b/mybatisproj/src/main/java/com/robin/basis/controller/system/TenantInfoController.java
@@ -14,6 +14,7 @@
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.annotation.security.PermitAll;
 import java.util.List;
 import java.util.Map;
 
@@ -23,7 +24,7 @@ public class TenantInfoController extends AbstractMyBatisController<ITenantInfoS
     @PostMapping
     @PreAuthorize("@checker.isSuperAdmin()")
     public Map<String,Object> save(@RequestPart("tenant") TenantInfoDTO dto,@RequestPart(required = false) MultipartFile logo){
-        int count=service.lambdaQuery().eq(TenantInfo::getTenantCode,dto.getTenantCode()).eq(TenantInfo::getStatus, Const.VALID).count();
+        long count=service.lambdaQuery().eq(TenantInfo::getTenantCode,dto.getTenantCode()).eq(TenantInfo::getStatus, Const.VALID).count();
         if(count>0){
             return wrapFailedMsg("存在编码相同的企业!");
         }
@@ -78,5 +79,11 @@ public Map<String,Object> activeTenant(Map<String,Object> reqMap){
         }
 
     }
+    @GetMapping("/attendTenant")
+    @PermitAll
+    public Map<String,Object> attendTenant(Map<String,Object> reqMap){
+
+        return null;
+    }
 
 }
diff --git a/mybatisproj/src/main/java/com/robin/basis/controller/user/LoginController.java b/mybatisproj/src/main/java/com/robin/basis/controller/user/LoginController.java
index 6092ebce..f72689b9 100644
--- a/mybatisproj/src/main/java/com/robin/basis/controller/user/LoginController.java
+++ b/mybatisproj/src/main/java/com/robin/basis/controller/user/LoginController.java
@@ -103,7 +103,9 @@ public Map<String, Object> login(HttpServletRequest request, HttpServletResponse
             map.put("token", token);
             if(ObjectUtils.isEmpty(loginUser.getTenantId())){
                 map.put("selectTenant",true);
-                map.put("tenants",tenantInfoService.queryTenantByUser(loginUser.getId()));
+                List<TenantInfoDTO> dtos=tenantInfoService.queryTenantByUser(loginUser.getId());
+                filterListByCodeSet(dtos,"type","typeName","TENANTUSERTYPE");
+                map.put("tenants",dtos);
             }else{
                 map.put("selectTenant",false);
             }
@@ -174,7 +176,7 @@ public Map<String, Object> getUserInfo(HttpServletRequest request) throws Except
             retMap.put("roles", roles.stream().map(f-> RoleDTO.fromVO(f,loginUser.getTenantId())).collect(Collectors.toList()));
         }
         List<TenantInfoDTO> tenantInfoDTOS=tenantInfoService.queryTenantByUser(loginUser.getId());
-        filterListByCodeSet(tenantInfoDTOS,"type","typeName","");
+        filterListByCodeSet(tenantInfoDTOS,"type","typeName","TENANTUSERTYPE");
         if(!CollectionUtils.isEmpty(tenantInfoDTOS) && tenantInfoDTOS.size()>1){
             retMap.put("tenants",tenantInfoDTOS);
         }
@@ -215,8 +217,8 @@ public Map<String,Object> showTenantInfo(HttpServletResponse response, @PathVari
             if (optional.isPresent()) {
                 TenantInfoDTO dto=optional.get();
                 SysUser sysUser=sysUserService.getById(user.getId());
-                sysUser.setTenantId(tenantId);
-                sysUser.setAccountType(WebConstant.TENANT_TYPE.ORGADMIN.toString().equals(dto.getType())?WebConstant.ACCOUNT_TYPE.ORGADMIN.toString():WebConstant.ACCOUNT_TYPE.ORDINARY.toString());
+                user.setTenantId(tenantId);
+                user.setAccountType(WebConstant.TENANT_TYPE.ORGADMIN.toString().equals(dto.getType())?WebConstant.ACCOUNT_TYPE.ORGADMIN.toString():WebConstant.ACCOUNT_TYPE.ORDINARY.toString());
                 Map<String, Object> retMap = new HashMap<>();
                 List<String> permissions = new ArrayList<>();
                 List<SysResourceDTO> resources = sysResourceService.queryUserPermission(sysUser, tenantId);
diff --git a/mybatisproj/src/main/java/com/robin/basis/dto/CustomerDTO.java b/mybatisproj/src/main/java/com/robin/basis/dto/CustomerDTO.java
new file mode 100644
index 00000000..0c263a6a
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/dto/CustomerDTO.java
@@ -0,0 +1,17 @@
+package com.robin.basis.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class CustomerDTO implements Serializable {
+    private Long id;
+    private String name;
+    private String district;
+    private String phone;
+    private String creditNo;
+    private String gender;
+    private String birthDay;
+    private String type;
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/dto/EmployeeUserTenantDTO.java b/mybatisproj/src/main/java/com/robin/basis/dto/EmployeeUserTenantDTO.java
index e7b7751e..afb3f55f 100644
--- a/mybatisproj/src/main/java/com/robin/basis/dto/EmployeeUserTenantDTO.java
+++ b/mybatisproj/src/main/java/com/robin/basis/dto/EmployeeUserTenantDTO.java
@@ -8,7 +8,9 @@
 public class EmployeeUserTenantDTO implements Serializable {
     private Long id;
     private String name;
+    private String contactPhone;
     private Long userId;
     private Long tenantId;
     private String status;
+    private String userName;
 }
diff --git a/mybatisproj/src/main/java/com/robin/basis/dto/SysCodeSetDTO.java b/mybatisproj/src/main/java/com/robin/basis/dto/SysCodeSetDTO.java
new file mode 100644
index 00000000..6d54181e
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/dto/SysCodeSetDTO.java
@@ -0,0 +1,9 @@
+package com.robin.basis.dto;
+
+import com.robin.core.base.dto.PageDTO;
+import lombok.Data;
+
+@Data
+public class SysCodeSetDTO extends PageDTO {
+    private String nameOrDesc;
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/dto/biz/MerchantMemberDTO.java b/mybatisproj/src/main/java/com/robin/basis/dto/biz/MerchantMemberDTO.java
new file mode 100644
index 00000000..0c9e92ee
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/dto/biz/MerchantMemberDTO.java
@@ -0,0 +1,19 @@
+package com.robin.basis.dto.biz;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class MerchantMemberDTO implements Serializable {
+    private Long id;
+    private Long custId;
+    private String code;
+    private String name;
+    private String gender;
+    private String creditNo;
+    private String phone;
+    private String type;
+    private Integer level;
+    private Long scores;
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/dto/query/CustomerQueryDTO.java b/mybatisproj/src/main/java/com/robin/basis/dto/query/CustomerQueryDTO.java
new file mode 100644
index 00000000..dbeea58e
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/dto/query/CustomerQueryDTO.java
@@ -0,0 +1,13 @@
+package com.robin.basis.dto.query;
+
+import com.robin.core.base.dto.PageDTO;
+import lombok.Data;
+
+@Data
+public class CustomerQueryDTO extends PageDTO {
+    private String phone;
+    private String name;
+    private String creditNo;
+    private String districtId;
+    private String address;
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/mapper/SysResourceMapper.java b/mybatisproj/src/main/java/com/robin/basis/mapper/SysResourceMapper.java
index fe9f6506..3f0c7037 100644
--- a/mybatisproj/src/main/java/com/robin/basis/mapper/SysResourceMapper.java
+++ b/mybatisproj/src/main/java/com/robin/basis/mapper/SysResourceMapper.java
@@ -16,12 +16,13 @@ public interface SysResourceMapper extends BaseMapper<SysResource> {
     List<SysResourceDTO> queryByRole(@Param(value = "roleId") Long roleId);
     @Select("<script>"
             +"select id,permission,res_type as resType,res_name as resName,url,is_leaf as leafTag,res_code as resCode,pid,seq_no as seqNo,assign_type as assignType,is_leaf as leafTag,icon,router_path as routerPath,component_name as componentName "
-            +"from (select a.*,0 as assign_type from t_sys_resource_info a,t_sys_resource_role_r b,t_sys_role_info c,t_sys_user_role_r d where a.status='1' and b.status='1' and a.ID=b.RES_ID and b.role_id=c.id and c.id=d.role_id "
+            +"from (select a.*,0 as assign_type from t_sys_resource_info a,t_sys_resource_role_r b,t_sys_role_info c,t_sys_user_role_r d where a.status='1' and b.status='1' and c.status='1' and d.status='1' and a.ID=b.RES_ID and b.role_id=c.id and c.id=d.role_id "
             +"<when test='tenantId!=null'>"
-            +" and (a.tenant_id=#{tenantId} or b.tenant_id=#{tenantId} or b.tenant_id=0)"
+            +" and ((a.tenant_id=#{tenantId} and d.tenant_id=#{tenantId}) or(a.tenant_id=0 and b.tenant_id=0 and c.tenant_id=0))"
             +"</when>"
-            +" and d.user_id=${userId} and a.STATUS='1' and b.status='1' " +
+            +" and d.user_id=${userId} " +
             "  union select c.*,d.assign_type from t_sys_resource_info c,t_sys_resource_user_r d where c.id=d.res_id and d.USER_ID=#{userId} and c.STATUS='1' and d.status='1' )e order by res_code,seq_no,assign_type desc"
             +"</script>")
     List<SysResourceDTO> queryUserPermission(@Param(value = "userId") Long userId,@Param(value = "tenantId") Long tenantId);
+
 }
diff --git a/mybatisproj/src/main/java/com/robin/basis/mapper/TenantInfoMapper.java b/mybatisproj/src/main/java/com/robin/basis/mapper/TenantInfoMapper.java
index 3ff6387a..36b15f9e 100644
--- a/mybatisproj/src/main/java/com/robin/basis/mapper/TenantInfoMapper.java
+++ b/mybatisproj/src/main/java/com/robin/basis/mapper/TenantInfoMapper.java
@@ -12,7 +12,7 @@
 @Mapper
 public interface TenantInfoMapper extends BaseMapper<TenantInfo> {
     @Select("<script>"
-            +"select a.user_id as userId,b.id as id,b.tenant_name as tenantName,b.tenant_code as tenantCode,b.org_id as orgId,c.org_name as orgName,c.org_code as orgCode,a.type from t_tenant_user_r a,t_tenant_info b,t_sys_org_info c "
+            +"select a.user_id as userId,b.id as id,b.tenant_name as tenantName,b.tenant_code as tenantCode,b.org_id as orgId,c.org_name as orgName,c.org_code as orgCode,a.type,b.logo from t_tenant_user_r a,t_tenant_info b,t_sys_org_info c "
             +" where a.status='1' and b.status='1' and c.status='1' and a.TENANT_ID=b.id and c.id=b.org_id and a.user_id=${userId}"
     +"</script>")
     List<TenantInfoDTO> queryTenantByUser(@Param(value = "userId") Long userId);
diff --git a/mybatisproj/src/main/java/com/robin/basis/mapper/TenantUserInviteMapper.java b/mybatisproj/src/main/java/com/robin/basis/mapper/TenantUserInviteMapper.java
new file mode 100644
index 00000000..8bff5119
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/mapper/TenantUserInviteMapper.java
@@ -0,0 +1,9 @@
+package com.robin.basis.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.robin.basis.model.user.TenantUserInvite;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface TenantUserInviteMapper extends BaseMapper<TenantUserInvite> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/mapper/TenantUserMapper.java b/mybatisproj/src/main/java/com/robin/basis/mapper/TenantUserMapper.java
index 6bf4737e..def9cfdd 100644
--- a/mybatisproj/src/main/java/com/robin/basis/mapper/TenantUserMapper.java
+++ b/mybatisproj/src/main/java/com/robin/basis/mapper/TenantUserMapper.java
@@ -18,6 +18,6 @@ public interface TenantUserMapper extends BaseMapper<TenantUser> {
     List<EmployeeUserTenantDTO> getTenantEmpUser(@Param(Constants.WRAPPER) QueryWrapper<EmployeeUserTenantDTO> wrapper);
 
     @Select("<script>"+
-            "select * from (select a.id,name,u.id as userId from t_sys_employee a,t_sys_user_info u where a.id=u.employee_id) t ${ew.customSqlSegment}"+"</script>")
+            "select * from (select a.id,a.name,a.contact_phone as contactPhone,u.id as userId,u.user_account as userName from t_sys_employee a,t_sys_user_info u where a.id=u.employee_id and a.status='1' and b.status='1') t ${ew.customSqlSegment}"+"</script>")
     List<EmployeeUserTenantDTO> getEmployeeUser(@Param(Constants.WRAPPER) QueryWrapper<EmployeeUserTenantDTO> wrapper);
 }
diff --git a/mybatisproj/src/main/java/com/robin/basis/mapper/biz/BrandMapper.java b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/BrandMapper.java
new file mode 100644
index 00000000..c65ade10
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/BrandMapper.java
@@ -0,0 +1,9 @@
+package com.robin.basis.mapper.biz;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.robin.biz.model.Brand;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface BrandMapper extends BaseMapper<Brand> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/mapper/biz/CustomerMapper.java b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/CustomerMapper.java
new file mode 100644
index 00000000..1d239adf
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/CustomerMapper.java
@@ -0,0 +1,9 @@
+package com.robin.basis.mapper.biz;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.robin.biz.model.Customer;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface CustomerMapper  extends BaseMapper<Customer> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/mapper/biz/MemberConsumptionMapper.java b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/MemberConsumptionMapper.java
new file mode 100644
index 00000000..56f0a497
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/MemberConsumptionMapper.java
@@ -0,0 +1,9 @@
+package com.robin.basis.mapper.biz;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.robin.biz.model.MemberConsumption;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MemberConsumptionMapper extends BaseMapper<MemberConsumption> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/mapper/biz/MerchantMapper.java b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/MerchantMapper.java
new file mode 100644
index 00000000..203ced96
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/MerchantMapper.java
@@ -0,0 +1,9 @@
+package com.robin.basis.mapper.biz;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.robin.biz.model.Merchant;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MerchantMapper extends BaseMapper<Merchant> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/mapper/biz/MerchantMemberMapper.java b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/MerchantMemberMapper.java
new file mode 100644
index 00000000..9f44d1e4
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/MerchantMemberMapper.java
@@ -0,0 +1,9 @@
+package com.robin.basis.mapper.biz;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.robin.biz.model.MerchantMember;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MerchantMemberMapper extends BaseMapper<MerchantMember> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/mapper/biz/ProductsMapper.java b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/ProductsMapper.java
new file mode 100644
index 00000000..b0a5ccae
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/mapper/biz/ProductsMapper.java
@@ -0,0 +1,10 @@
+package com.robin.basis.mapper.biz;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.robin.biz.model.Products;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ProductsMapper extends BaseMapper<Products> {
+
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/model/system/SysResourceTenant.java b/mybatisproj/src/main/java/com/robin/basis/model/system/SysResourceTenant.java
new file mode 100644
index 00000000..5f450ea3
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/model/system/SysResourceTenant.java
@@ -0,0 +1,13 @@
+package com.robin.basis.model.system;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.robin.basis.model.AbstractMybatisModel;
+import lombok.Data;
+
+@Data
+@TableName("t_sys_resource_tenant_r")
+public class SysResourceTenant extends AbstractMybatisModel {
+    private Long id;
+    private Long resId;
+
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/model/system/TenantConfig.java b/mybatisproj/src/main/java/com/robin/basis/model/system/TenantConfig.java
index 44c7a3a1..fcd00fec 100644
--- a/mybatisproj/src/main/java/com/robin/basis/model/system/TenantConfig.java
+++ b/mybatisproj/src/main/java/com/robin/basis/model/system/TenantConfig.java
@@ -1,16 +1,46 @@
 package com.robin.basis.model.system;
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.robin.core.base.model.BaseObject;
+import com.robin.core.base.util.Const;
 import lombok.Data;
 
+import java.time.LocalDateTime;
+
 @Data
 @TableName("t_tenant_config")
-public class TenantConfig {
+public class TenantConfig extends BaseObject {
     @TableId(type = IdType.AUTO)
     private Long id;
     private Long tenantId;
-    private String key;
-    private String value;
+    private String configKey;
+    private String configValue;
+    private LocalDateTime auditTime;
+    @TableField(value = "creator", fill = FieldFill.INSERT)
+    private Long creatorId;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @TableField(value = "create_tm", fill = FieldFill.INSERT)
+    private LocalDateTime createTm;
+
+    /**
+     * 修改人标识
+     */
+    @TableField(value = "modifier", fill = FieldFill.INSERT_UPDATE)
+    private Long modifierId;
+
+    /**
+     * 修改时间
+     */
+    @TableField(value = "modify_tm", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime modifyTm;
+
+
+    @TableField(value = "status", fill = FieldFill.INSERT)
+    private String status= Const.VALID;
 }
diff --git a/mybatisproj/src/main/java/com/robin/basis/model/user/TenantUserInvite.java b/mybatisproj/src/main/java/com/robin/basis/model/user/TenantUserInvite.java
new file mode 100644
index 00000000..db573d02
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/model/user/TenantUserInvite.java
@@ -0,0 +1,34 @@
+package com.robin.basis.model.user;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.robin.core.base.model.BaseObject;
+import lombok.Data;
+
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+
+@TableName("t_tenant_user_invite")
+@Data
+public class TenantUserInvite extends BaseObject {
+    private Long id;
+    private Long tenantId;
+    private Long empId;
+    private String phone;
+    private String inviteCode;
+    private String acceptable;
+    private Timestamp acceptTime;
+    private String acceptIp;
+    @TableField(value = "creator", fill = FieldFill.INSERT)
+    private Long creatorId;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @TableField(value = "create_tm", fill = FieldFill.INSERT)
+    private LocalDateTime createTm;
+
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/biz/IBrandService.java b/mybatisproj/src/main/java/com/robin/basis/service/biz/IBrandService.java
new file mode 100644
index 00000000..af0285de
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/biz/IBrandService.java
@@ -0,0 +1,7 @@
+package com.robin.basis.service.biz;
+
+import com.robin.biz.model.Brand;
+import com.robin.core.base.service.IMybatisBaseService;
+
+public interface IBrandService extends IMybatisBaseService<Brand,Long> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/biz/ICustomerService.java b/mybatisproj/src/main/java/com/robin/basis/service/biz/ICustomerService.java
new file mode 100644
index 00000000..23915c84
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/biz/ICustomerService.java
@@ -0,0 +1,7 @@
+package com.robin.basis.service.biz;
+
+import com.robin.biz.model.Customer;
+import com.robin.core.base.service.IMybatisBaseService;
+
+public interface ICustomerService extends IMybatisBaseService<Customer,Long> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/biz/IMemberConsumptionService.java b/mybatisproj/src/main/java/com/robin/basis/service/biz/IMemberConsumptionService.java
new file mode 100644
index 00000000..6a00b7d7
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/biz/IMemberConsumptionService.java
@@ -0,0 +1,7 @@
+package com.robin.basis.service.biz;
+
+import com.robin.biz.model.MemberConsumption;
+import com.robin.core.base.service.IMybatisBaseService;
+
+public interface IMemberConsumptionService extends IMybatisBaseService<MemberConsumption,Long> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/biz/IMerchantMemberService.java b/mybatisproj/src/main/java/com/robin/basis/service/biz/IMerchantMemberService.java
new file mode 100644
index 00000000..83a76f34
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/biz/IMerchantMemberService.java
@@ -0,0 +1,9 @@
+package com.robin.basis.service.biz;
+
+import com.robin.basis.dto.biz.MerchantMemberDTO;
+import com.robin.biz.model.MerchantMember;
+import com.robin.core.base.service.IMybatisBaseService;
+
+public interface IMerchantMemberService extends IMybatisBaseService<MerchantMember,Long> {
+    boolean saveMember(MerchantMemberDTO dto);
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/biz/IMerchantService.java b/mybatisproj/src/main/java/com/robin/basis/service/biz/IMerchantService.java
new file mode 100644
index 00000000..4f01761d
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/biz/IMerchantService.java
@@ -0,0 +1,7 @@
+package com.robin.basis.service.biz;
+
+import com.robin.biz.model.Merchant;
+import com.robin.core.base.service.IMybatisBaseService;
+
+public interface IMerchantService extends IMybatisBaseService<Merchant,Long> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/BrandServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/BrandServiceImpl.java
new file mode 100644
index 00000000..9537b098
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/BrandServiceImpl.java
@@ -0,0 +1,11 @@
+package com.robin.basis.service.biz.impl;
+
+import com.robin.basis.mapper.biz.BrandMapper;
+import com.robin.basis.service.biz.IBrandService;
+import com.robin.biz.model.Brand;
+import com.robin.core.base.service.AbstractMybatisService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class BrandServiceImpl extends AbstractMybatisService<BrandMapper, Brand,Long> implements IBrandService {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/CustomerServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/CustomerServiceImpl.java
new file mode 100644
index 00000000..fba0524e
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/CustomerServiceImpl.java
@@ -0,0 +1,11 @@
+package com.robin.basis.service.biz.impl;
+
+import com.robin.basis.mapper.biz.CustomerMapper;
+import com.robin.basis.service.biz.ICustomerService;
+import com.robin.biz.model.Customer;
+import com.robin.core.base.service.AbstractMybatisService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class CustomerServiceImpl extends AbstractMybatisService<CustomerMapper, Customer,Long> implements ICustomerService {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/MemberConsumptionServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/MemberConsumptionServiceImpl.java
new file mode 100644
index 00000000..182e1418
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/MemberConsumptionServiceImpl.java
@@ -0,0 +1,11 @@
+package com.robin.basis.service.biz.impl;
+
+import com.robin.basis.mapper.biz.MemberConsumptionMapper;
+import com.robin.basis.service.biz.IMemberConsumptionService;
+import com.robin.biz.model.MemberConsumption;
+import com.robin.core.base.service.AbstractMybatisService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class MemberConsumptionServiceImpl  extends AbstractMybatisService<MemberConsumptionMapper, MemberConsumption,Long> implements IMemberConsumptionService {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/MerchantMemberServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/MerchantMemberServiceImpl.java
new file mode 100644
index 00000000..f0df6bdf
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/MerchantMemberServiceImpl.java
@@ -0,0 +1,65 @@
+package com.robin.basis.service.biz.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.robin.basis.dto.biz.MerchantMemberDTO;
+import com.robin.basis.mapper.biz.MerchantMemberMapper;
+import com.robin.basis.model.AbstractMybatisModel;
+import com.robin.basis.service.biz.ICustomerService;
+import com.robin.basis.service.biz.IMerchantMemberService;
+import com.robin.basis.utils.IdCardNoIdentifier;
+import com.robin.basis.utils.SecurityUtils;
+import com.robin.biz.model.Customer;
+import com.robin.biz.model.MerchantMember;
+import com.robin.core.base.exception.ServiceException;
+import com.robin.core.base.service.AbstractMybatisService;
+import com.robin.core.base.util.Const;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.ObjectUtils;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Map;
+
+@Service
+public class MerchantMemberServiceImpl extends AbstractMybatisService<MerchantMemberMapper, MerchantMember,Long> implements IMerchantMemberService {
+    @Resource
+    private ICustomerService customerService;
+    private static final DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+    @Transactional(rollbackFor = RuntimeException.class)
+    public boolean saveMember(MerchantMemberDTO dto){
+        Long custId=null;
+        if(ObjectUtils.isEmpty(dto.getCustId())){
+            if(customerService.lambdaQuery().eq(Customer::getPhone,dto.getPhone()).eq(AbstractMybatisModel::getStatus, Const.VALID).exists()){
+                throw new ServiceException("手机号码已存在");
+            }else{
+                Customer customer=new Customer();
+                if(StrUtil.isNotBlank(dto.getCreditNo())){
+                    Map<String,Object> map= IdCardNoIdentifier.identifyByCode(dto.getCreditNo());
+                    if((Boolean) map.get("success")){
+                        customer.setCreditNo(dto.getCreditNo());
+                        customer.setBrithDay(LocalDate.parse(map.get("birthDay").toString()));
+                        customer.setGender(map.get("gender").toString());
+                        customer.setDistrictId(map.get("districtId").toString());
+                    }
+                    customer.setName(dto.getName());
+                    customer.setPhone(dto.getPhone());
+                    customer.setRegTime(LocalDateTime.now());
+                    customer.setRegOrgId(SecurityUtils.getLoginUser().getOrgId());
+                    customerService.save(customer);
+                    custId=customer.getId();
+                }
+            }
+        }else{
+            custId=dto.getCustId();
+        }
+        MerchantMember member=new MerchantMember();
+        BeanUtils.copyProperties(dto,member);
+        member.setCustId(custId);
+        return this.save(member);
+    }
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/MerchantServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/MerchantServiceImpl.java
new file mode 100644
index 00000000..7624401f
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/biz/impl/MerchantServiceImpl.java
@@ -0,0 +1,13 @@
+package com.robin.basis.service.biz.impl;
+
+import com.robin.basis.mapper.biz.MerchantMapper;
+import com.robin.basis.service.biz.IMerchantService;
+import com.robin.biz.model.Merchant;
+import com.robin.core.base.service.AbstractMybatisService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class MerchantServiceImpl extends AbstractMybatisService<MerchantMapper, Merchant,Long> implements IMerchantService {
+
+
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/ISysCodeSetService.java b/mybatisproj/src/main/java/com/robin/basis/service/system/ISysCodeSetService.java
index a5171e91..bdd19031 100644
--- a/mybatisproj/src/main/java/com/robin/basis/service/system/ISysCodeSetService.java
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/ISysCodeSetService.java
@@ -1,7 +1,11 @@
 package com.robin.basis.service.system;
 
+import com.robin.basis.dto.SysCodeSetDTO;
 import com.robin.basis.model.system.SysCodeSet;
 import com.robin.core.base.service.IMybatisBaseService;
 
+import java.util.Map;
+
 public interface ISysCodeSetService extends IMybatisBaseService<SysCodeSet,Long> {
+    Map<String,Object> list(SysCodeSetDTO dto);
 }
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/ISysOrgService.java b/mybatisproj/src/main/java/com/robin/basis/service/system/ISysOrgService.java
index cc1e21d8..b83d0055 100644
--- a/mybatisproj/src/main/java/com/robin/basis/service/system/ISysOrgService.java
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/ISysOrgService.java
@@ -20,7 +20,7 @@ public interface ISysOrgService extends IMybatisBaseService<SysOrg,Long> {
     boolean removeOrg(Long orgId,List<Long> uids);
     List<SysOrgVO> queryOrg(SysOrgQueryDTO dto);
     IPage<EmployeeDTO> queryOrgUser(SysOrgQueryDTO dto);
-    TenantInfo getTopOrgTenant(Long orgId);
+    Pair<TenantInfo, SysOrg> getTopOrgTenant(Long orgId);
     IPage<EmployeeDTO> selectEmployeeInOrg(Page<SysUserQueryDTO> page, QueryWrapper wrapper, List<Long> orgIds);
     IPage<EmployeeDTO> selectEmployeeNotInOrg(Page<SysUserQueryDTO> page,  QueryWrapper wrapper,List<Long> orgIds);
     Pair<Integer,Integer> deleteOrg(List<Long> orgIds);
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/ISysRoleService.java b/mybatisproj/src/main/java/com/robin/basis/service/system/ISysRoleService.java
index e9ce2edd..5e4904b1 100644
--- a/mybatisproj/src/main/java/com/robin/basis/service/system/ISysRoleService.java
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/ISysRoleService.java
@@ -17,4 +17,5 @@ public interface ISysRoleService extends IMybatisBaseService<SysRole,Long> {
     boolean saveRole(SysRoleDTO dto) throws ServiceException;
     boolean updateRole(SysRoleDTO dto) throws ServiceException;
     boolean deleteRoles(List<Long> ids) throws ServiceException;
+    List<SysRole> queryValid();
 }
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/ITenantInfoService.java b/mybatisproj/src/main/java/com/robin/basis/service/system/ITenantInfoService.java
index c32f3a25..b8b39bee 100644
--- a/mybatisproj/src/main/java/com/robin/basis/service/system/ITenantInfoService.java
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/ITenantInfoService.java
@@ -13,5 +13,6 @@ public interface ITenantInfoService extends IMybatisBaseService<TenantInfo,Long>
     boolean activeTenant(Long tenantId,Long managerId);
     boolean closeTenant(Long tenantId);
     boolean insertTenant(TenantInfoDTO dto, MultipartFile logo);
+    boolean inviteEmployees(Long tenantId,List<Long> empIds);
     //TenantInfo getManagedTenant(Long useId);
 }
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/ITenantUserInviteService.java b/mybatisproj/src/main/java/com/robin/basis/service/system/ITenantUserInviteService.java
new file mode 100644
index 00000000..aebb51ce
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/ITenantUserInviteService.java
@@ -0,0 +1,7 @@
+package com.robin.basis.service.system;
+
+import com.robin.basis.model.user.TenantUserInvite;
+import com.robin.core.base.service.IMybatisBaseService;
+
+public interface ITenantUserInviteService extends IMybatisBaseService<TenantUserInvite,Long> {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/EmployeeServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/EmployeeServiceImpl.java
index c06a8b20..13ad9d64 100644
--- a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/EmployeeServiceImpl.java
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/EmployeeServiceImpl.java
@@ -53,9 +53,9 @@ public Map<String,Object> list(SysEmployeeQueryDTO queryDTO){
         }
     }
     public boolean saveEmployee(EmployeeDTO dto) throws ServiceException{
-        int count=this.lambdaQuery().eq(StrUtil.isNotBlank(dto.getCreditNo()),Employee::getCreditNo,dto.getCreditNo())
+        long count=this.lambdaQuery().eq(StrUtil.isNotBlank(dto.getCreditNo()),Employee::getCreditNo,dto.getCreditNo())
                 .or(orwrapper->orwrapper.eq(StrUtil.isNotBlank(dto.getName()),Employee::getName,dto.getName())).count();
-        if(count>0){
+        if(count>0L){
             throw new ServiceException("employee exists!");
         }
         Employee employee=new Employee();
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysCodeSetServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysCodeSetServiceImpl.java
index 453c10ff..880711fe 100644
--- a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysCodeSetServiceImpl.java
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysCodeSetServiceImpl.java
@@ -1,12 +1,25 @@
 package com.robin.basis.service.system.impl;
 
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.robin.basis.dto.SysCodeSetDTO;
 import com.robin.basis.mapper.SysCodeSetMapper;
 import com.robin.basis.model.system.SysCodeSet;
 import com.robin.basis.service.system.ISysCodeSetService;
+import com.robin.basis.utils.WebUtils;
 import com.robin.core.base.service.AbstractMybatisService;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+import java.util.Map;
+
 @Service
-public class SysCodeSetServiceImpl  extends AbstractMybatisService<SysCodeSetMapper, SysCodeSet,Long> implements ISysCodeSetService {
+public class SysCodeSetServiceImpl extends AbstractMybatisService<SysCodeSetMapper, SysCodeSet,Long> implements ISysCodeSetService {
+    public Map<String,Object> list(SysCodeSetDTO dto){
+        IPage<SysCodeSet> page=this.lambdaQuery().like(StrUtil.isNotBlank(dto.getNameOrDesc()),SysCodeSet::getEnName,dto.getNameOrDesc()).or()
+                .like(StrUtil.isNotBlank(dto.getNameOrDesc()),SysCodeSet::getCnName,dto.getNameOrDesc())
+                .page(getPage(dto));
+        return WebUtils.toPageVO(page,null);
+    }
 
 }
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysOrgServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysOrgServiceImpl.java
index e6ca70a0..8bc7f97e 100644
--- a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysOrgServiceImpl.java
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysOrgServiceImpl.java
@@ -6,6 +6,7 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.collect.Lists;
 import com.robin.basis.dto.EmployeeDTO;
+import com.robin.basis.dto.EmployeeUserTenantDTO;
 import com.robin.basis.dto.query.SysOrgQueryDTO;
 import com.robin.basis.dto.query.SysUserQueryDTO;
 import com.robin.basis.mapper.SysOrgMapper;
@@ -19,10 +20,12 @@
 import com.robin.basis.model.user.TenantUser;
 import com.robin.basis.service.region.IRegionService;
 import com.robin.basis.service.system.*;
+import com.robin.basis.utils.SecurityUtils;
 import com.robin.basis.vo.SysOrgVO;
 import com.robin.core.base.exception.ServiceException;
 import com.robin.core.base.service.AbstractMybatisService;
 import com.robin.core.base.util.Const;
+import com.robin.core.web.util.WebConstant;
 import lombok.NonNull;
 import org.apache.commons.lang3.tuple.Pair;
 import org.springframework.stereotype.Service;
@@ -50,14 +53,18 @@ public class SysOrgServiceImpl extends AbstractMybatisService<SysOrgMapper,SysOr
     private IRegionService regionService;
     @Resource
     private ITenantUserService tenantUserService;
+    @Resource
+    private IEmployeeService employeeService;
+
     @Transactional(readOnly = true)
     public List<SysOrgVO> queryOrg(SysOrgQueryDTO dto){
         List<SysOrgVO> orgList=queryValid(new QueryWrapper<SysOrg>().lambda(), AbstractMybatisModel::getStatus).stream().map(SysOrgVO::fromVO).collect(Collectors.toList());
         Map<Long,List<SysOrgVO>> orgMap=orgList.stream().collect(Collectors.groupingBy(SysOrgVO::getPid));
-        List<SysOrgVO> topList=orgMap.get(!ObjectUtils.isEmpty(dto.getPid())?dto.getPid():0L);
+        List<SysOrgVO> topList=orgMap.get(!ObjectUtils.isEmpty(dto.getPid())?dto.getPid():SecurityUtils.isLoginUserSystemAdmin()?0L:SecurityUtils.getLoginUser().getOrgId());
+
         if(!StrUtil.isBlank(dto.getName())){
             Map<Long,SysOrgVO> idMap=orgList.stream().collect(Collectors.toMap(SysOrgVO::getId,Function.identity()));
-            List<SysOrg> orgs= this.lambdaQuery().and(wrapper->
+            List<SysOrg> orgs= this.lambdaQuery().eq(!SecurityUtils.isLoginUserSystemAdmin(),SysOrg::getPid,SecurityUtils.getLoginUser().getOrgId()).and(wrapper->
                 wrapper.like(SysOrg::getOrgName,dto.getName())
                         .or(orwapper->orwapper.like(SysOrg::getOrgCode,dto.getName()))
             ).list();
@@ -109,7 +116,7 @@ public List<Long> getSubIdByParentOrgId(Long orgId) {
     }
     @Override
     @Transactional(readOnly = true)
-    public TenantInfo getTopOrgTenant(Long orgId){
+    public Pair<TenantInfo, SysOrg> getTopOrgTenant(Long orgId){
         List<SysOrg> list=queryByField(AbstractMybatisModel::getStatus, Const.OPERATOR.EQ,Const.VALID);
         Map<Long,SysOrg> map=list.stream().collect(Collectors.toMap(SysOrg::getId,Function.identity()));
         SysOrg current=map.get(orgId);
@@ -123,7 +130,7 @@ public TenantInfo getTopOrgTenant(Long orgId){
                 tenantInfo=tList.get(0);
             }
         }
-        return tenantInfo;
+        return Pair.of(tenantInfo,current);
     }
     private void walkOrgTree(Map<Long,List<SysOrg>> map, @NonNull Long id, List<Long> idList){
         idList.add(id);
@@ -134,32 +141,64 @@ private void walkOrgTree(Map<Long,List<SysOrg>> map, @NonNull Long id, List<Long
     @Transactional(rollbackFor = RuntimeException.class)
     public boolean joinOrg(Long orgId,List<Long> uids){
         Assert.isTrue(!CollectionUtils.isEmpty(uids),"");
-        int existCount=sysUserService.lambdaQuery().in(SysUser::getId,uids).eq(AbstractMybatisModel::getStatus,Const.VALID).count();
-        Assert.isTrue(existCount==uids.size(),"");
+        long existCount=employeeService.lambdaQuery().in(Employee::getId,uids).eq(AbstractMybatisModel::getStatus,Const.VALID).count();
+        Assert.isTrue(Long.valueOf(existCount).intValue()==uids.size(),"");
         List<SysOrgEmployee> list=new ArrayList<>();
-        TenantInfo topOrgTenant= getTopOrgTenant(orgId);
-        if(ObjectUtils.isEmpty(topOrgTenant)){
+        List<TenantUser> tenantUsers=new ArrayList<>();
+        Pair<TenantInfo,SysOrg> pair= getTopOrgTenant(orgId);
+        if(ObjectUtils.isEmpty(pair.getLeft())){
             throw new ServiceException("orgId "+orgId+" has not any owned tenant");
         }
+        QueryWrapper<EmployeeUserTenantDTO> queryWrapper1=new QueryWrapper<>();
+        queryWrapper1.in("a.id",uids);
+        List<EmployeeUserTenantDTO> userEmps=tenantUserService.getEmployeeUser(queryWrapper1);
+        Map<Long,EmployeeUserTenantDTO> userEmpMap=new HashMap<>();
+        if(!CollectionUtils.isEmpty(userEmps)){
+            userEmpMap.putAll(userEmps.stream().collect(Collectors.toMap(EmployeeUserTenantDTO::getId,Function.identity())));
+        }
         for(Long uid:uids){
             SysOrgEmployee userOrg=new SysOrgEmployee();
             userOrg.setEmpId(uid);
             userOrg.setOrgId(orgId);
             userOrg.setStatus(Const.VALID);
-            userOrg.setTargetTenantId(topOrgTenant.getId());
+            userOrg.setTargetTenantId(pair.getLeft().getId());
             list.add(userOrg);
+            //tenant_user 表
+            if(userEmpMap.containsKey(uid)) {
+                TenantUser tenantUser = new TenantUser();
+                tenantUser.setTenantId(pair.getLeft().getId());
+                tenantUser.setUserId(userEmpMap.get(uid).getUserId());
+                tenantUser.setType(WebConstant.TENANT_TYPE.EMPLOYEE.getValue());
+                tenantUsers.add(tenantUser);
+            }
         }
-        return sysOrgEmployeeService.insertBatch(list);
+        sysOrgEmployeeService.insertBatch(list);
+        tenantUserService.insertBatch(tenantUsers);
+        return true;
     }
     @Transactional(rollbackFor = RuntimeException.class)
     public boolean removeOrg(Long orgId,List<Long> uids){
         Assert.isTrue(!CollectionUtils.isEmpty(uids),"");
         Map<String,Object> map=new HashMap<>();
         map.put("ids",uids);
-        int existCount=sysUserService.lambdaQuery().in(SysUser::getId,uids).eq(AbstractMybatisModel::getStatus,Const.VALID).count();
-        Assert.isTrue(existCount==uids.size(),"");
-        return userOrgService.lambdaUpdate().set(AbstractMybatisModel::getStatus,Const.INVALID)
-                .in(SysUserOrg::getUserId,uids).eq(SysUserOrg::getOrgId,orgId).eq(AbstractMybatisModel::getStatus,Const.VALID).update();
+        long existCount=employeeService.lambdaQuery().in(Employee::getId,uids).eq(AbstractMybatisModel::getStatus,Const.VALID).count();
+        Assert.isTrue(Long.valueOf(existCount).intValue()==uids.size(),"");
+        QueryWrapper<EmployeeUserTenantDTO> queryWrapper1=new QueryWrapper<>();
+        queryWrapper1.in("a.id",uids);
+        List<EmployeeUserTenantDTO> userEmps=tenantUserService.getEmployeeUser(queryWrapper1);
+        List<Long> userIds=new ArrayList<>();
+        if(!CollectionUtils.isEmpty(userEmps)){
+            userIds.addAll(userEmps.stream().map(EmployeeUserTenantDTO::getUserId).collect(Collectors.toList()));
+        }
+        boolean executeTag=sysOrgEmployeeService.lambdaUpdate().set(AbstractMybatisModel::getStatus, Const.INVALID)
+                .in(SysOrgEmployee::getEmpId, uids).eq(SysOrgEmployee::getOrgId, orgId).eq(AbstractMybatisModel::getStatus, Const.VALID).update();
+        if(!CollectionUtils.isEmpty(userIds) && executeTag) {
+            Pair<TenantInfo,SysOrg> pair= getTopOrgTenant(orgId);
+             return tenantUserService.lambdaUpdate().set(TenantUser::getStatus,Const.INVALID)
+                     .eq(TenantUser::getTenantId,pair.getLeft().getId()).in(TenantUser::getUserId,userIds)
+                     .eq(TenantUser::getStatus,Const.INVALID).update();
+        }
+        return false;
     }
     @Transactional(readOnly = true)
     public IPage<EmployeeDTO> queryOrgUser(SysOrgQueryDTO dto){
@@ -174,7 +213,7 @@ public IPage<EmployeeDTO> queryOrgUser(SysOrgQueryDTO dto){
                 .and(!StrUtil.isBlank(dto.getUserName()), wrapper -> wrapper.like(Employee::getName, dto.getUserName())
                         .or(orWrapper -> orWrapper.like(Employee::getAddress, dto.getUserName())));
         IPage<EmployeeDTO>  page=null;
-        if("1".equals(dto.getSelType())){
+        if(Const.VALID.equals(dto.getSelType())){
             page= baseMapper.selectEmployeeInOrg(new Page<>(dto.getPage(),dto.getSize()),queryWrapper,subIds);
         }else{
             page= baseMapper.selectEmployeeNotInOrg(new Page<>(dto.getPage(),dto.getSize()),queryWrapper,subIds);
@@ -227,8 +266,8 @@ private boolean deleteOrgEmployee(List<Long> orgIds){
                 .in(SysOrgEmployee::getOrgId,orgIds).eq(AbstractMybatisModel::getStatus,Const.VALID).update();
     }
     private boolean adjustTenantClosed(Long orgId){
-        int count=tenantInfoService.lambdaQuery().eq(TenantInfo::getOrgId,orgId).eq(TenantInfo::getStatus,Const.VALID).count();
-        return count==0;
+        long count=tenantInfoService.lambdaQuery().eq(TenantInfo::getOrgId,orgId).eq(TenantInfo::getStatus,Const.VALID).count();
+        return count==0L;
     }
     private boolean deleteOrgTenant(Long orgId){
         //查找机构对应租户是否存在
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysResourceServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysResourceServiceImpl.java
index 443886e9..15a42d50 100644
--- a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysResourceServiceImpl.java
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysResourceServiceImpl.java
@@ -76,10 +76,12 @@ public void updateUserResourceRight(Long userId,Long tenantId, List<Long> newLis
             }
         }
         if(!CollectionUtils.isEmpty(insertList)){
-            sysResourceUserService.lambdaUpdate().set(AbstractMybatisModel::getStatus,Const.INVALID)
-                    .eq(SysResourceUser::getUserId,userId).eq(AbstractMybatisModel::getStatus,Const.VALID).update();
             sysResourceUserService.insertBatch(insertList);
         }
+        if(!CollectionUtils.isEmpty(delList)){
+            sysResourceUserService.lambdaUpdate().set(AbstractMybatisModel::getStatus,Const.INVALID)
+                    .eq(SysResourceUser::getUserId,userId).in(SysResourceUser::getResId,delList).eq(AbstractMybatisModel::getStatus,Const.VALID).update();
+        }
     }
     public List<SysResourceDTO> getByRole(Long roleId){
         return baseMapper.queryByRole(roleId);
@@ -89,9 +91,11 @@ public List<SysResourceVO> search(SysResourceQueryDTO dto){
         boolean useQuery=!StrUtil.isAllBlank(dto.getCondition(),dto.getType());
         List<SysResource> allList=queryByField(SysResource::getStatus, Const.OPERATOR.EQ,Const.VALID);
         Map<Long,List<SysResource>> pidMap=allList.stream().collect(Collectors.groupingBy(SysResource::getPid));
+
         List<SysResource> queryList= this.lambdaQuery()
                 .eq(!useQuery,SysResource::getPid,0L)
                 .eq(ObjectUtil.isNotNull(dto.getType()),SysResource::getResType,dto.getType())
+                .eq(!SecurityUtils.isLoginUserSystemAdmin(),SysResource::getTenantId,SecurityUtils.getLoginUser().getTenantId())
                 .and(StrUtil.isNotBlank(dto.getCondition()),wrapper->wrapper.like(SysResource::getResName,dto.getCondition())
                         .or(orwrapper->orwrapper.like(SysResource::getCode,dto.getCondition())))
                 .orderByAsc(SysResource::getSeqNo).list();
@@ -119,8 +123,6 @@ private void recusionResourceTree(Map<Long,List<SysResource>> pidMap, SysResourc
         }
     }
 
-
-
     public List<SysResource> getAllValidate() {
         SysResource queryVO = new SysResource();
         queryVO.setStatus(Const.VALID);
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysRoleServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysRoleServiceImpl.java
index 185c32e9..cbe38c18 100644
--- a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysRoleServiceImpl.java
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/SysRoleServiceImpl.java
@@ -57,7 +57,7 @@ public Map<String,Object> search(SysRoleQueryDTO dto){
         SysLoginUser user= SecurityUtils.getLoginUser();
         IPage<SysRole> roles= this.lambdaQuery().eq(AbstractMybatisModel::getStatus,!ObjectUtils.isEmpty(dto.getStatus())?dto.getStatus():Const.VALID)
                 .like(StrUtil.isNotBlank(dto.getCode()),SysRole::getRoleCode,dto.getCode())
-                .eq(user.getTenantId()!=0L,SysRole::getTenantId,user.getTenantId())
+                .eq(!SecurityUtils.isLoginUserSystemAdmin(),SysRole::getTenantId,user.getTenantId())
                 .and(StrUtil.isNotBlank(dto.getName()),wrapper->
                     wrapper.like(SysRole::getRoleName,dto.getName()).or(
                             orWrapper-> orWrapper.like(SysRole::getDescription,dto.getName())
@@ -73,9 +73,15 @@ public Map<String,Object> search(SysRoleQueryDTO dto){
         });
 
     }
+    @Override
+    public List<SysRole> queryValid(){
+        SysLoginUser user= SecurityUtils.getLoginUser();
+        return this.lambdaQuery().eq(AbstractMybatisModel::getStatus,Const.VALID)
+                .eq(!SecurityUtils.isLoginUserSystemAdmin(),SysRole::getTenantId,user.getTenantId()).list();
+    }
     public boolean saveRole(SysRoleDTO dto) throws ServiceException{
        try {
-           boolean exist = this.lambdaQuery().eq(AbstractMybatisModel::getStatus, Const.VALID).eq(SysRole::getRoleCode, dto.getRoleCode()).count() > 0;
+           boolean exist = this.lambdaQuery().eq(AbstractMybatisModel::getStatus, Const.VALID).eq(AbstractMybatisModel::getTenantId,SecurityUtils.getLoginUser().getTenantId()).eq(SysRole::getRoleCode, dto.getRoleCode()).count() > 0;
            if (exist) {
                throw new ServiceException("role exists");
            }
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/TenantInfoServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/TenantInfoServiceImpl.java
index fadd0bdf..0827b162 100644
--- a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/TenantInfoServiceImpl.java
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/TenantInfoServiceImpl.java
@@ -1,5 +1,6 @@
 package com.robin.basis.service.system.impl;
 
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.google.common.collect.Lists;
@@ -7,10 +8,12 @@
 import com.robin.basis.dto.EmployeeUserTenantDTO;
 import com.robin.basis.dto.TenantInfoDTO;
 import com.robin.basis.mapper.TenantInfoMapper;
+import com.robin.basis.model.AbstractMybatisModel;
 import com.robin.basis.model.system.TenantInfo;
 import com.robin.basis.model.user.Employee;
 import com.robin.basis.model.user.SysUser;
 import com.robin.basis.model.user.TenantUser;
+import com.robin.basis.model.user.TenantUserInvite;
 import com.robin.basis.service.system.*;
 import com.robin.basis.utils.WebUtils;
 import com.robin.core.base.exception.MissingConfigException;
@@ -18,6 +21,7 @@
 import com.robin.core.base.service.AbstractMybatisService;
 import com.robin.core.base.spring.SpringContextHolder;
 import com.robin.core.base.util.Const;
+import com.robin.core.base.util.StringUtils;
 import com.robin.core.fileaccess.fs.AbstractFileSystemAccessor;
 import com.robin.core.web.util.WebConstant;
 import org.springframework.beans.BeanUtils;
@@ -30,7 +34,8 @@
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
-import java.util.List;
+import java.sql.Timestamp;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
@@ -45,6 +50,8 @@ public class TenantInfoServiceImpl extends AbstractMybatisService<TenantInfoMapp
     private ITenantUserService tenantUserService;
     @Resource
     private IEmployeeService employeeService;
+    @Resource
+    private ITenantUserInviteService tenantUserInviteService;
 
 
     @Transactional(rollbackFor = RuntimeException.class)
@@ -77,6 +84,8 @@ public boolean activeTenant(Long tenantId,Long managerId){
         QueryWrapper<EmployeeUserTenantDTO> queryWrapper=new QueryWrapper<>();
         queryWrapper.lambda().eq(EmployeeUserTenantDTO::getId,managerId).eq(EmployeeUserTenantDTO::getTenantId,tenantId);
         List<EmployeeUserTenantDTO> dtos=tenantUserService.getTenantEmpUser(queryWrapper);
+
+
         //雇员已与租户绑定
         if(!CollectionUtils.isEmpty(dtos)){
             EmployeeUserTenantDTO dto=dtos.get(0);
@@ -86,7 +95,7 @@ public boolean activeTenant(Long tenantId,Long managerId){
         }else{
             //查找雇员对应的用户
             QueryWrapper<EmployeeUserTenantDTO> queryWrapper1=new QueryWrapper<>();
-            queryWrapper1.lambda().eq(EmployeeUserTenantDTO::getId,managerId);
+            queryWrapper1.eq("u.id",managerId);
             List<EmployeeUserTenantDTO> userEmps=tenantUserService.getEmployeeUser(queryWrapper);
             if(!CollectionUtils.isEmpty(userEmps)){
                 //将第一个条对应用户关联为企业管理
@@ -160,9 +169,83 @@ public List<Long> getUserTenants(Long userId){
     public List<TenantInfoDTO> queryTenantByUser(Long userId){
         return baseMapper.queryTenantByUser(userId);
     }
-    /*public TenantInfo getManagedTenant(Long useId){
-        SysUser selectuser=sysUserService.getById(useId);
-        Assert.isTrue(!ObjectUtils.isEmpty(selectuser) && Const.VALID.equals(selectuser.getStatus()),"");
-        return this.getByField(TenantInfo::getOrgId, Const.OPERATOR.EQ,selectuser.getOrgId());
-    }*/
+    @Transactional(rollbackFor = RuntimeException.class)
+    public boolean inviteEmployees(Long tenantId,List<Long> empIds){
+        TenantInfo info=this.getById(tenantId);
+        Assert.isTrue(!ObjectUtils.isEmpty(info) && Const.VALID.equals(info.getStatus()),"tenant not exists");
+        Assert.isTrue(!CollectionUtils.isEmpty(empIds),"");
+        long count=employeeService.lambdaQuery().in(Employee::getId,empIds).eq(AbstractMybatisModel::getStatus,Const.VALID).count();
+        Assert.isTrue(Long.valueOf(count).intValue()==empIds.size(),"");
+        List<Employee> employees=employeeService.lambdaQuery().in(Employee::getId,empIds).eq(AbstractMybatisModel::getStatus,Const.VALID).list();
+        if(!CollectionUtils.isEmpty(employees)){
+            List<TenantUserInvite> invites=new ArrayList<>();
+            for(Employee employee:employees){
+                String inviteCode= UUID.randomUUID().toString();
+                TenantUserInvite invite=new TenantUserInvite();
+                invite.setPhone(employee.getContactPhone());
+                invite.setTenantId(tenantId);
+                invite.setInviteCode(inviteCode);
+                invite.setEmpId(employee.getId());
+                invites.add(invite);
+            }
+            return tenantUserInviteService.insertBatch(invites);
+        }
+        return false;
+    }
+    public Map<String,Object> showTenantInvite(String inviteCode){
+        List<TenantUserInvite> invites=tenantUserInviteService.lambdaQuery().eq(TenantUserInvite::getInviteCode,inviteCode)
+                .eq(TenantUserInvite::getAcceptable,Const.VALID).list();
+        Map<String,Object> retMap=new HashMap<>();
+        if(!CollectionUtils.isEmpty(invites)){
+            retMap.put("success",true);
+            TenantUserInvite invite=invites.get(0);
+            QueryWrapper<EmployeeUserTenantDTO> queryWrapper=new QueryWrapper<>();
+            queryWrapper.eq("a.id",invite.getEmpId());
+            List<EmployeeUserTenantDTO> emps= tenantUserService.getEmployeeUser(queryWrapper);
+            if(!CollectionUtils.isEmpty(emps)){
+                retMap.put("userId",emps.get(0).getUserId());
+                retMap.put("name",emps.get(0).getName());
+                retMap.put("phone",emps.get(0).getContactPhone());
+                retMap.put("userName",emps.get(0).getUserName());
+            }
+            retMap.put("tenantId",invite.getTenantId());
+        }else{
+            retMap.put("success",false);
+        }
+        return retMap;
+    }
+    public boolean acceptTenantInvite(String inviteCode,String ipAddress,String userName,String cnName,String password){
+        List<TenantUserInvite> invites=tenantUserInviteService.lambdaQuery().eq(TenantUserInvite::getInviteCode,inviteCode)
+                .eq(TenantUserInvite::getAcceptable,Const.VALID).list();
+        if(!CollectionUtils.isEmpty(invites)){
+            TenantUserInvite invite=invites.get(0);
+            QueryWrapper<EmployeeUserTenantDTO> queryWrapper=new QueryWrapper<>();
+            queryWrapper.eq("a.id",invite.getEmpId());
+            List<EmployeeUserTenantDTO> emps= tenantUserService.getEmployeeUser(queryWrapper);
+            Long userId;
+            if(!CollectionUtils.isEmpty(emps)){
+                userId=emps.get(0).getUserId();
+            }else{
+                Assert.isTrue(StrUtil.isNotBlank(userName) && StrUtil.isNotBlank(password));
+                SysUser user=new SysUser();
+                user.setUserAccount(userName);
+                if(!ObjectUtils.isEmpty(cnName)) {
+                    user.setUserName(cnName);
+                }
+                user.setUserPassword(SpringContextHolder.getBean(PasswordEncoder.class).encode(password));
+                user.setAccountType(WebConstant.ACCOUNT_TYPE.ORDINARY.toString());
+                sysUserService.save(user);
+                userId=user.getId();
+            }
+            TenantUser tuser=new TenantUser();
+            tuser.setTenantId(invite.getTenantId());
+            tuser.setUserId(userId);
+            tuser.setType(WebConstant.TENANT_TYPE.EMPLOYEE.getValue());
+            tenantUserService.save(tuser);
+            tenantUserInviteService.lambdaUpdate().set(TenantUserInvite::getAcceptTime,new Timestamp(System.currentTimeMillis())).set(TenantUserInvite::getAcceptIp,ipAddress).set(TenantUserInvite::getAcceptable,Const.INVALID)
+                    .eq(TenantUserInvite::getInviteCode,inviteCode).update();
+            return true;
+        }
+        return false;
+    }
 }
diff --git a/mybatisproj/src/main/java/com/robin/basis/service/system/impl/TenantUserInviteServiceImpl.java b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/TenantUserInviteServiceImpl.java
new file mode 100644
index 00000000..b5cdf30b
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/service/system/impl/TenantUserInviteServiceImpl.java
@@ -0,0 +1,11 @@
+package com.robin.basis.service.system.impl;
+
+import com.robin.basis.mapper.TenantUserInviteMapper;
+import com.robin.basis.model.user.TenantUserInvite;
+import com.robin.basis.service.system.ITenantUserInviteService;
+import com.robin.core.base.service.AbstractMybatisService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TenantUserInviteServiceImpl extends AbstractMybatisService<TenantUserInviteMapper, TenantUserInvite,Long> implements ITenantUserInviteService {
+}
diff --git a/mybatisproj/src/main/java/com/robin/basis/utils/IdCardNoIdentifier.java b/mybatisproj/src/main/java/com/robin/basis/utils/IdCardNoIdentifier.java
new file mode 100644
index 00000000..4237db4a
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/basis/utils/IdCardNoIdentifier.java
@@ -0,0 +1,66 @@
+package com.robin.basis.utils;
+
+import cn.hutool.core.util.StrUtil;
+import org.springframework.util.Assert;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.HashMap;
+import java.util.Map;
+
+public class IdCardNoIdentifier {
+    private static final DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+    public static Map<String,Object> identifyByCode(String code){
+        Assert.isTrue(StrUtil.isNotBlank(code) && (code.length()==15 || code.length()==18),"");
+        String year;
+        String month;
+        String day;
+        Map<String,Object> retMap=new HashMap<>();
+        boolean ifSuccess=false;
+        long diffYear=0L;
+        retMap.put("districtId",code.substring(0,6));
+        if(code.length()==18){
+            year=code.substring(6,10);
+            month=code.substring(10,12);
+            day=code.substring(12,14);
+            if(Integer.valueOf(month)>11 || Integer.valueOf(day)>31){
+                ifSuccess=false;
+            }else{
+                ifSuccess=true;
+                diffYear=getAge(year+"-"+month+"-"+day) ;
+                retMap.put("age",diffYear);
+                retMap.put("birthDay",year+"-"+month+"-"+day);
+            }
+            if(ifSuccess && Integer.parseInt(code.substring(16,17)) %2!=0){
+                retMap.put("gender","1");
+            }else{
+                retMap.put("gender","2");
+            }
+        }else{
+            year="19"+code.substring(6,8);
+            month=code.substring(8,10);
+            day=code.substring(10,12);
+            if(Integer.valueOf(month)>11 || Integer.valueOf(day)>31){
+                ifSuccess=false;
+            }else {
+                ifSuccess = true;
+                diffYear=getAge(year+"-"+month+"-"+day) ;
+                retMap.put("age",diffYear);
+                retMap.put("birthDay",year+"-"+month+"-"+day);
+            }
+            if(ifSuccess && Integer.parseInt(code.substring(14,15)) %2!=0){
+                retMap.put("gender","1");
+            }else{
+                retMap.put("gender","2");
+            }
+        }
+        retMap.put("success",ifSuccess);
+        return retMap;
+    }
+    private static Long getAge(String brithDay){
+        LocalDateTime birthTime= LocalDate.parse(brithDay,formatter).atStartOfDay();
+        return ChronoUnit.YEARS.between(birthTime,LocalDateTime.now());
+    }
+}
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/Brand.java b/mybatisproj/src/main/java/com/robin/biz/model/Brand.java
new file mode 100644
index 00000000..2976a780
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/biz/model/Brand.java
@@ -0,0 +1,10 @@
+package com.robin.biz.model;
+
+import com.robin.basis.model.AbstractMybatisModel;
+
+public class Brand extends AbstractMybatisModel {
+    private Long id;
+    private String name;
+    private String type;
+
+}
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/Customer.java b/mybatisproj/src/main/java/com/robin/biz/model/Customer.java
index 0b7d2d9a..592d1913 100644
--- a/mybatisproj/src/main/java/com/robin/biz/model/Customer.java
+++ b/mybatisproj/src/main/java/com/robin/biz/model/Customer.java
@@ -1,24 +1,27 @@
 package com.robin.biz.model;
 
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.robin.basis.model.AbstractMybatisModel;
 import lombok.Data;
 
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 
 @Data
+@TableName("t_biz_customer")
 public class Customer extends AbstractMybatisModel {
     private Long id;
     private String wxId;
 
     private String name;
     private String type;
-    private String sex;
-    private LocalDateTime brithDay;
+    private String gender;
+    private LocalDate brithDay;
     private String phone;
     private String creditNo;
     private String province;
     private String city;
-    private String district;
+    private String districtId;
     private String address;
     private LocalDateTime regTime;
     private Long regOrgId;
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/MemberConsumption.java b/mybatisproj/src/main/java/com/robin/biz/model/MemberConsumption.java
index cbed02c0..7385ae5d 100644
--- a/mybatisproj/src/main/java/com/robin/biz/model/MemberConsumption.java
+++ b/mybatisproj/src/main/java/com/robin/biz/model/MemberConsumption.java
@@ -1,9 +1,14 @@
 package com.robin.biz.model;
 
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.robin.basis.model.AbstractMybatisModel;
+import lombok.Data;
+
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
-
-public class MemberConsumption  {
+@Data
+@TableName("t_biz_member_consumption")
+public class MemberConsumption extends AbstractMybatisModel {
     private Long id;
     private Long memberId;
     private Long tenantId;
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/Merchant.java b/mybatisproj/src/main/java/com/robin/biz/model/Merchant.java
index 9da767a1..e78fc5ac 100644
--- a/mybatisproj/src/main/java/com/robin/biz/model/Merchant.java
+++ b/mybatisproj/src/main/java/com/robin/biz/model/Merchant.java
@@ -1,10 +1,12 @@
 package com.robin.biz.model;
 
-import com.robin.core.base.model.AbstractBaseModel;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.robin.basis.model.AbstractMybatisModel;
 import lombok.Data;
 
 @Data
-public class Merchant extends AbstractBaseModel {
+@TableName("t_biz_merchant")
+public class Merchant extends AbstractMybatisModel {
     private Long orgId;
     private String name;
     private String abbrName;
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/MerchantMember.java b/mybatisproj/src/main/java/com/robin/biz/model/MerchantMember.java
index 56e68a10..f0eb7ece 100644
--- a/mybatisproj/src/main/java/com/robin/biz/model/MerchantMember.java
+++ b/mybatisproj/src/main/java/com/robin/biz/model/MerchantMember.java
@@ -1,5 +1,6 @@
 package com.robin.biz.model;
 
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.robin.basis.model.AbstractMybatisModel;
 import lombok.Data;
 
@@ -7,6 +8,7 @@
 import java.time.LocalDateTime;
 
 @Data
+@TableName("t_biz_merchant_member")
 public class MerchantMember extends AbstractMybatisModel {
     private Long id;
     private String code;
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/Order.java b/mybatisproj/src/main/java/com/robin/biz/model/Order.java
index b8dd02b0..97dc5654 100644
--- a/mybatisproj/src/main/java/com/robin/biz/model/Order.java
+++ b/mybatisproj/src/main/java/com/robin/biz/model/Order.java
@@ -1,5 +1,6 @@
 package com.robin.biz.model;
 
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.robin.basis.model.AbstractMybatisModel;
 import lombok.Data;
 
@@ -7,6 +8,7 @@
 import java.time.LocalDateTime;
 
 @Data
+@TableName("t_biz_order")
 public class Order extends AbstractMybatisModel {
     private Long id;
     private Long memberId;
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/OrderDetail.java b/mybatisproj/src/main/java/com/robin/biz/model/OrderDetail.java
new file mode 100644
index 00000000..76216c19
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/biz/model/OrderDetail.java
@@ -0,0 +1,10 @@
+package com.robin.biz.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.robin.basis.model.AbstractMybatisModel;
+import lombok.Data;
+
+@Data
+@TableName("t_biz_order_detail")
+public class OrderDetail extends AbstractMybatisModel {
+}
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/ProductInventory.java b/mybatisproj/src/main/java/com/robin/biz/model/ProductInventory.java
new file mode 100644
index 00000000..3042142d
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/biz/model/ProductInventory.java
@@ -0,0 +1,20 @@
+package com.robin.biz.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.robin.basis.model.AbstractMybatisModel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+@TableName("t_biz_product_inventory")
+public class ProductInventory extends AbstractMybatisModel {
+    private Long id;
+    private String checkTag;
+    private Long productId;
+    private Long salesQuantity;
+    private Long stockQuantity;
+    private BigDecimal salesReceivable;
+    private BigDecimal salesRealReceive;
+
+}
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/ProductPurchase.java b/mybatisproj/src/main/java/com/robin/biz/model/ProductPurchase.java
new file mode 100644
index 00000000..909d0a5a
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/biz/model/ProductPurchase.java
@@ -0,0 +1,21 @@
+package com.robin.biz.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.robin.basis.model.AbstractMybatisModel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("t_biz_product_purchase")
+public class ProductPurchase extends AbstractMybatisModel {
+    private Long id;
+    private Long productId;
+    private Double price;
+    private BigDecimal total;
+    private LocalDateTime purchaseTm;
+    private String operator;
+    private Long receiver;
+    private Short type;
+}
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/ProductSales.java b/mybatisproj/src/main/java/com/robin/biz/model/ProductSales.java
new file mode 100644
index 00000000..2124a978
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/biz/model/ProductSales.java
@@ -0,0 +1,15 @@
+package com.robin.biz.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.robin.basis.model.AbstractMybatisModel;
+import lombok.Data;
+
+@Data
+@TableName("t_product_sales")
+public class ProductSales  extends AbstractMybatisModel {
+    private Long id;
+    private Long productId;
+    private Long orderId;
+    private Integer quantity;
+
+}
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/ProductStock.java b/mybatisproj/src/main/java/com/robin/biz/model/ProductStock.java
new file mode 100644
index 00000000..0820f573
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/biz/model/ProductStock.java
@@ -0,0 +1,14 @@
+package com.robin.biz.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.robin.basis.model.AbstractMybatisModel;
+import lombok.Data;
+
+@Data
+@TableName("t_biz_product_stock")
+public class ProductStock extends AbstractMybatisModel {
+    private Long id;
+    private Long productId;
+    private Long quantity;
+
+}
diff --git a/mybatisproj/src/main/java/com/robin/biz/model/Products.java b/mybatisproj/src/main/java/com/robin/biz/model/Products.java
new file mode 100644
index 00000000..700b7250
--- /dev/null
+++ b/mybatisproj/src/main/java/com/robin/biz/model/Products.java
@@ -0,0 +1,17 @@
+package com.robin.biz.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.robin.basis.model.AbstractMybatisModel;
+import lombok.Data;
+
+@TableName("t_biz_products")
+@Data
+public class Products extends AbstractMybatisModel {
+    private Long id;
+    private String name;
+    private String code;
+    private Double price;
+    private String type;
+    private Long brandId;
+
+}
diff --git a/mybatisproj/src/main/resources/application.yml b/mybatisproj/src/main/resources/application.yml
index 6e2741fb..2c800a76 100644
--- a/mybatisproj/src/main/resources/application.yml
+++ b/mybatisproj/src/main/resources/application.yml
@@ -137,8 +137,12 @@ project:
     appId: wx2b676f2108f5506d
     secretId: a5227884e44310f71e16188dd5b5dbc0
 
+oss:
+  type: file
+  startPath: file:///f:/tmp/
+
 login:
-  ignoreUrls: /index,/login,/logout,/captchaImage
+  ignoreUrls: /index,/login,/logout,/captchaImage,/ossres
   ignoreResources: gif,bmp,png,jpg,js,flash,css,swf,flv,metaget
 jwt:
   salt: 1234
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 72b313ef..eeb28532 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,6 +53,7 @@
         <module>estool</module>
         <module>tracer</module>
         <module>dataming</module>
+        <module>decryptagent</module>
     </modules>
     <!-- properties -->
     <properties>
@@ -131,7 +132,7 @@
         <cassandradriver.version>3.6.0</cassandradriver.version>
         <graal.version>1.0.0-rc7</graal.version>
         <calcite.version>1.34.0</calcite.version>
-        <mybatisplus.version>3.4.3</mybatisplus.version>
+        <mybatisplus.version>3.4.3.4</mybatisplus.version>
         <orc.version>1.7.1</orc.version>
         <spark.version>2.4.8</spark.version>
         <hutool.version>5.8.11</hutool.version>
diff --git a/rapidexcel/pom.xml b/rapidexcel/pom.xml
new file mode 100644
index 00000000..89a10bc7
--- /dev/null
+++ b/rapidexcel/pom.xml
@@ -0,0 +1,177 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.robin</groupId>
+        <artifactId>frame</artifactId>
+        <version>1.0</version>
+    </parent>
+    <artifactId>rapidexcel</artifactId>
+    <packaging>jar</packaging>
+    <name>rapidexcel</name>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <flink.version>1.20.0</flink.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.robin</groupId>
+            <artifactId>common</artifactId>
+            <version>${frm.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+       
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <optional>true</optional>
+        </dependency>
+        
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-dbutils</groupId>
+            <artifactId>commons-dbutils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-tx</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-orm</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-jdbc</artifactId>
+            <optional>true</optional>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+            <version>1.26</version>
+            <optional>true</optional>
+        </dependency>
+       
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.flink</groupId>
+            <artifactId>flink-core</artifactId>
+            <version>${flink.version}</version>
+            <optional>true</optional>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml</groupId>
+            <artifactId>aalto-xml</artifactId>
+            <version>1.3.3</version>
+            <optional>true</optional>
+        </dependency>
+        
+    </dependencies>
+    <build>
+        <sourceDirectory>src/main/java</sourceDirectory>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addClasspath>true</addClasspath>
+                            <classpathPrefix>lib/</classpathPrefix>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <configuration>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+
+        </plugins>
+    </build>
+</project>
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/elements/Cell.java b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/Cell.java
new file mode 100644
index 00000000..ce0e12e4
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/Cell.java
@@ -0,0 +1,34 @@
+package com.robin.rapidexcel.elements;
+
+import lombok.Getter;
+
+@Getter
+public class Cell {
+    private WorkBook workBook;
+    private CellType type;
+    private Object value;
+    private CellAddress address;
+    private String formula;
+    private String rawValue;
+    private String dataFormatId;
+    private String dataFormatString;
+    public Cell(WorkBook workbook, CellType type, Object value, CellAddress address, String formula, String rawValue) {
+        this(workbook, type, value, address, formula, rawValue, null, null);
+    }
+
+    public Cell(WorkBook workbook, CellType type, Object value, CellAddress address, String formula, String rawValue,
+         String dataFormatId, String dataFormatString) {
+        this.workBook = workbook;
+        this.type = type;
+        this.value = value;
+        this.address = address;
+        this.formula = formula;
+        this.rawValue = rawValue;
+        this.dataFormatId = dataFormatId;
+        this.dataFormatString = dataFormatString;
+    }
+
+    public void setValue(Object value) {
+        this.value = value;
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/elements/CellAddress.java b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/CellAddress.java
new file mode 100644
index 00000000..0c993bb8
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/CellAddress.java
@@ -0,0 +1,65 @@
+package com.robin.rapidexcel.elements;
+
+public class CellAddress {
+    private static final char ABSOLUTE_REFERENCE_MARKER = '$';
+    private static final int COL_RADIX = 'Z' - 'A' + 1;
+
+    private final int row;
+    private final int col;
+    public CellAddress(int row, int col){
+        this.row=row;
+        this.col=col;
+    }
+    public CellAddress(String address){
+        final int length = address.length();
+        if (length == 0) {
+            this.row = 0;
+            this.col = 0;
+        } else {
+            int offset = address.charAt(0) == ABSOLUTE_REFERENCE_MARKER ? 1 : 0;
+            int col = 0;
+            for (; offset < length; offset++) {
+                final char c = address.charAt(offset);
+                if (c == ABSOLUTE_REFERENCE_MARKER) {
+                    offset++;
+                    break; //next there must be digits
+                }
+                if (isAsciiDigit(c)) {
+                    break;
+                }
+                col = col * COL_RADIX + toUpperCase(c) - (int) 'A' + 1;
+            }
+            this.col = col - 1;
+            this.row = Integer.parseUnsignedInt(address.substring(offset)) - 1;
+        }
+    }
+
+    public int getRow() {
+        return row;
+    }
+
+    public int getColumn() {
+        return col;
+    }
+
+    private static final boolean isAsciiDigit(char c) {
+        return '0' <= c && c <= '9';
+    }
+
+    private final static char toUpperCase(char c) {
+        if (isAsciiUpperCase(c)) {
+            return c;
+        }
+        if (isAsciiLowerCase(c)) {
+            return (char) (c + ('A' - 'a'));
+        }
+        throw new IllegalArgumentException("Unexpected char: " + c);
+    }
+    private static final boolean isAsciiLowerCase(char c) {
+        return 'a' <= c && c <= 'z';
+    }
+
+    private static final boolean isAsciiUpperCase(char c) {
+        return 'A' <= c && c <= 'Z';
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/elements/CellType.java b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/CellType.java
new file mode 100644
index 00000000..4c7d635f
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/CellType.java
@@ -0,0 +1,10 @@
+package com.robin.rapidexcel.elements;
+
+public enum CellType {
+    NUMBER,
+    STRING,
+    FORMULA,
+    ERROR,
+    BOOLEAN,
+    EMPTY
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/elements/Font.java b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/Font.java
new file mode 100644
index 00000000..6b266d2a
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/Font.java
@@ -0,0 +1,52 @@
+package com.robin.rapidexcel.elements;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+public class Font {
+    public static Font DEFAULT = build(false, false, false, "Calibri", BigDecimal.valueOf(11.0), "FF000000", false);
+
+    /**
+     * Bold flag.
+     */
+    private final boolean bold;
+    /**
+     * Italic flag.
+     */
+    private final boolean italic;
+    /**
+     * Underlined flag.
+     */
+    private final boolean underlined;
+    /**
+     * Font name.
+     */
+    private final String name;
+    /**
+     * Font size.
+     */
+    private final BigDecimal size;
+    /**
+     * RGB font color.
+     */
+    private final String rgbColor;
+    /**
+     * Strikethrough flag.
+     */
+    private final boolean strikethrough;
+    Font(boolean bold, boolean italic, boolean underlined, String name, BigDecimal size, String rgbColor, boolean strikethrough) {
+        if (size.compareTo(BigDecimal.valueOf(409)) > 0 || size.compareTo(BigDecimal.valueOf(1)) < 0) {
+            throw new IllegalStateException("Font size must be between 1 and 409 points: " + size);
+        }
+        this.bold = bold;
+        this.italic = italic;
+        this.underlined = underlined;
+        this.name = name;
+        this.size = size.setScale(2, RoundingMode.HALF_UP);
+        this.rgbColor = rgbColor;
+        this.strikethrough = strikethrough;
+    }
+    public static Font build(Boolean bold, Boolean italic, Boolean underlined, String name, BigDecimal size, String rgbColor, Boolean strikethrough) {
+        return new Font(bold != null? bold : DEFAULT.bold, italic != null ? italic : DEFAULT.italic , underlined != null ? underlined : DEFAULT.underlined, name != null ? name : DEFAULT.name, size != null ?  size:DEFAULT.size, rgbColor != null ?  rgbColor: DEFAULT.rgbColor, strikethrough != null ? strikethrough : DEFAULT.strikethrough);
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/elements/RelationShip.java b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/RelationShip.java
new file mode 100644
index 00000000..bd9d9d4a
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/RelationShip.java
@@ -0,0 +1,23 @@
+package com.robin.rapidexcel.elements;
+
+import lombok.Data;
+
+@Data
+public class RelationShip {
+    private String id;
+    private String target;
+    private String type;
+    public RelationShip(String id,String target,String type){
+        this.id=id;
+        this.target=target;
+        this.type=type;
+    }
+
+    public String getTarget() {
+        return target;
+    }
+
+    public String getType() {
+        return type;
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/elements/Row.java b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/Row.java
new file mode 100644
index 00000000..74fb6f1e
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/Row.java
@@ -0,0 +1,17 @@
+package com.robin.rapidexcel.elements;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+public class Row {
+    private List<Cell> cells;
+    public Row(List<Cell> cells){
+        this.cells=cells;
+    }
+
+
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/elements/ShardingStrings.java b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/ShardingStrings.java
new file mode 100644
index 00000000..ddd668f1
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/ShardingStrings.java
@@ -0,0 +1,47 @@
+package com.robin.rapidexcel.elements;
+
+import com.robin.rapidexcel.reader.XMLReader;
+import com.robin.rapidexcel.utils.XMLFactoryUtils;
+
+import javax.xml.stream.XMLStreamException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ShardingStrings {
+    private List<String> values=new ArrayList<>();
+    private InputStream inputStream;
+    private ShardingStrings(InputStream inputStream){
+        this.inputStream=inputStream;
+    }
+    public static ShardingStrings formInputStream(InputStream inputStream) throws XMLStreamException,IOException {
+        ShardingStrings shardingStrings=new ShardingStrings(inputStream);
+        shardingStrings.construct();
+        return shardingStrings;
+    }
+    private void construct() throws XMLStreamException, IOException{
+        try(XMLReader reader=new XMLReader(XMLFactoryUtils.getDefaultInputFactory(),inputStream)){
+            while (reader.hasNext()) {
+                reader.goTo("si");
+                StringBuilder sb=new StringBuilder();
+                while (reader.goTo(() -> reader.isStartElement("t")
+                        || reader.isStartElement("rPh")
+                        || reader.isEndElement("si"))) {
+                    if (reader.isStartElement("t")) {
+                        sb.append(reader.getValueUntilEndElement("t"));
+                    } else if (reader.isEndElement("si")) {
+                        break;
+                    } else if (reader.isStartElement("rPh")) {
+                        reader.goTo(() -> reader.isEndElement("rPh"));
+                    }
+                }
+                values.add(sb.toString());
+            }
+        }
+    }
+
+    public List<String> getValues() {
+        return values;
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/elements/SheetVisibility.java b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/SheetVisibility.java
new file mode 100644
index 00000000..96976d5d
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/SheetVisibility.java
@@ -0,0 +1,7 @@
+package com.robin.rapidexcel.elements;
+
+public enum SheetVisibility {
+    VISIBLE,
+    HIDDEN,
+    VERY_HIDDEN
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/elements/WorkBook.java b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/WorkBook.java
new file mode 100644
index 00000000..58ca03b8
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/WorkBook.java
@@ -0,0 +1,213 @@
+package com.robin.rapidexcel.elements;
+
+import cn.hutool.core.io.FileUtil;
+import com.robin.comm.util.xls.ExcelSheetProp;
+import com.robin.rapidexcel.reader.XMLReader;
+import com.robin.rapidexcel.utils.MapSpliterator;
+import com.robin.rapidexcel.utils.OPCPackage;
+import com.robin.rapidexcel.utils.RowSpliterator;
+import com.robin.rapidexcel.utils.XMLFactoryUtils;
+import org.springframework.util.Assert;
+import org.springframework.util.ObjectUtils;
+
+import javax.xml.stream.XMLStreamException;
+import java.io.*;
+import java.util.*;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import java.util.zip.ZipOutputStream;
+
+public class WorkBook implements Closeable {
+    private Map<Integer, CellType> styleMap;
+    private int activeTab = 0;
+    private boolean finished = false;
+    private String applicationName="com.robin FastExcel";
+    private String applicationVersion;
+    private ZipOutputStream out;
+    private OPCPackage opcPackage;
+    private List<WorkSheet> sheets=new ArrayList<>();
+    private Map<String, WorkSheet> sheetMap=new HashMap<>();
+    private boolean date1904;
+    private ExcelSheetProp prop;
+    private ShardingStrings shardingStrings;
+
+    public WorkBook(File file,String applicationName,String applicationVersion){
+        this.applicationName=applicationName;
+        this.applicationVersion=applicationVersion;
+        opcPackage=OPCPackage.create(file);
+    }
+
+    public WorkBook(OutputStream cout,String applicationName,String applicationVersion){
+        this.out=new ZipOutputStream(cout);
+        this.applicationName=applicationName;
+        this.applicationVersion=applicationVersion;
+        opcPackage=OPCPackage.create(out);
+    }
+    public WorkBook(InputStream inputStream) throws XMLStreamException,IOException{
+        Assert.notNull(inputStream,"");
+        opcPackage=OPCPackage.open(inputStream);
+        beginRead();
+    }
+    public WorkBook(File file) throws XMLStreamException,IOException {
+        if(!FileUtil.exist(file)){
+            throw new IOException("file not found!");
+        }
+        opcPackage=OPCPackage.open(file);
+        beginRead();
+    }
+    public void setSheetProp(ExcelSheetProp prop){
+        this.prop=prop;
+    }
+
+    public ExcelSheetProp getSheetProp() {
+        return prop;
+    }
+
+    public List<String> getFormats(){
+        return opcPackage.getFormatIdList();
+    }
+    public Map<String,String> getNumFmtMap(){
+        return opcPackage.getFormatMap();
+    }
+
+    private void beginRead() throws XMLStreamException,IOException {
+        try(XMLReader reader=new XMLReader(XMLFactoryUtils.getDefaultInputFactory(),opcPackage.getWorkBookContent())){
+            while(reader.goTo(() -> reader.isStartElement("sheets") || reader.isStartElement("workbookPr") ||
+                    reader.isStartElement("workbookView") || reader.isEndElement("workbook"))){
+                if ("workbookView".equals(reader.getLocalName())) {
+                    String activeTab = reader.getAttribute("activeTab");
+                    if (activeTab != null) {
+                        this.activeTab = Integer.parseInt(activeTab);
+                    }
+                } else if ("sheets".equals(reader.getLocalName())) {
+                    reader.forEach("sheet", "sheets", this::createSheet);
+                } else if ("workbookPr".equals(reader.getLocalName())) {
+                    String date1904Value = reader.getAttribute("date1904");
+                    date1904 = Boolean.parseBoolean(date1904Value);
+                } else {
+                    break;
+                }
+            }
+        }
+        shardingStrings=ShardingStrings.formInputStream(opcPackage.getShardingStrings());
+    }
+    private void createSheet(XMLReader r){
+        String name = r.getAttribute("name");
+        String id = r.getAttribute("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id");
+        String sheetId = r.getAttribute("sheetId");
+        SheetVisibility sheetVisibility;
+        if ("veryHidden".equals(r.getAttribute("state"))) {
+            sheetVisibility = SheetVisibility.VERY_HIDDEN;
+        } else if ("hidden".equals(r.getAttribute("state"))) {
+            sheetVisibility = SheetVisibility.HIDDEN;
+        } else {
+            sheetVisibility = SheetVisibility.VISIBLE;
+        }
+        int index = sheets.size();
+        WorkSheet sheet=new WorkSheet(this,index,id,sheetId,name,sheetVisibility);
+        sheets.add(sheet);
+        sheetMap.put(name,sheet);
+    }
+    public Stream<Row> openStream(WorkSheet sheet) throws IOException{
+        try{
+            InputStream inputStream=opcPackage.getSheetContent(sheet);
+            Stream<Row> stream = StreamSupport.stream(new RowSpliterator(this, inputStream,prop), false);
+            return stream.onClose(asUncheckedRunnable(inputStream));
+        }catch (XMLStreamException ex){
+            throw new IOException(ex);
+        }
+    }
+    public Stream<Map<String,Object>> openMapStream(WorkSheet sheet) throws IOException{
+        try{
+            InputStream inputStream=opcPackage.getSheetContent(sheet);
+            Stream<Map<String,Object>> stream = StreamSupport.stream(new MapSpliterator(this, inputStream,prop), false);
+            return stream.onClose(asUncheckedRunnable(inputStream));
+        }catch (XMLStreamException ex){
+            throw new IOException(ex);
+        }
+    }
+    private static Runnable asUncheckedRunnable(Closeable c) {
+        return () -> {
+            try {
+                c.close();
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        };
+    }
+
+    public void finish(){
+
+    }
+    public ShardingStrings getShardingStrings(){
+        return shardingStrings;
+    }
+
+    public boolean isDate1904() {
+        return date1904;
+    }
+    public Optional<WorkSheet> getSheet(int index) {
+        return index < 0 || index >= sheets.size() ? Optional.empty() : Optional.of(sheets.get(index));
+    }
+    public int getSheetNum(){
+        return !ObjectUtils.isEmpty(sheets)?sheets.size():0;
+    }
+
+    public WorkSheet getFirstSheet() {
+        return sheets.get(0);
+    }
+
+    public Optional<WorkSheet> findSheet(String name) {
+        return sheets.stream().filter(sheet -> name.equals(sheet.getName())).findFirst();
+    }
+
+    @Override
+    public void close() throws IOException {
+        if(opcPackage!=null){
+            opcPackage.close();
+        }
+        if(out!=null){
+            out.closeEntry();
+            out.close();
+        }
+    }
+
+    public static class Builder{
+        private static Builder builder;
+        private static WorkBook workBook;
+        private boolean useWriter=false;
+        private static String applicationName;
+        private String applicationVersion;
+        private static InputStream inputStream;
+        private File file;
+        private OutputStream outputStream;
+
+        private Builder(){
+
+        }
+        public static Builder newBuilder(){
+            builder=new Builder();
+            return builder;
+        }
+        public Builder readWithInputStream(InputStream stream){
+            this.inputStream=stream;
+            return this;
+        }
+        public Builder readWithFile(File file){
+            this.file=file;
+            return this;
+        }
+        public Builder applicationName(String applicationName){
+            this.applicationName=applicationName;
+            return this;
+        }
+        public Builder applicationVersion(String applicationVersion){
+            this.applicationVersion=applicationVersion;
+            return this;
+        }
+
+
+
+    }
+
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/elements/WorkSheet.java b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/WorkSheet.java
new file mode 100644
index 00000000..462ba677
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/elements/WorkSheet.java
@@ -0,0 +1,34 @@
+package com.robin.rapidexcel.elements;
+
+import java.util.List;
+
+public class WorkSheet {
+    private String id;
+    private int index;
+    private String name;
+    private String sheetId;
+    private SheetVisibility visibility;
+    private WorkBook workBook;
+
+    private List<Row> rows;
+    public WorkSheet(WorkBook workBook,int index,String id,String sheetId,String name,SheetVisibility visibility){
+        this.index=index;
+        this.id=id;
+        this.name=name;
+        this.visibility=visibility;
+        this.sheetId=sheetId;
+        this.workBook=workBook;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/reader/XMLReader.java b/rapidexcel/src/main/java/com/robin/rapidexcel/reader/XMLReader.java
new file mode 100644
index 00000000..3b495d70
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/reader/XMLReader.java
@@ -0,0 +1,116 @@
+package com.robin.rapidexcel.reader;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.function.BooleanSupplier;
+import java.util.function.Consumer;
+
+public class XMLReader implements Closeable {
+    private XMLInputFactory factory;
+    private final InputStream inputStream;
+    private final XMLStreamReader reader;
+    public XMLReader(XMLInputFactory factory,InputStream inputStream) throws XMLStreamException {
+        this.factory=factory;
+        this.inputStream=inputStream;
+        this.reader=factory.createXMLStreamReader(inputStream);
+    }
+    public boolean goTo(BooleanSupplier predicate) throws XMLStreamException{
+        while (reader.hasNext()){
+            reader.next();
+            if(predicate.getAsBoolean()){
+                return true;
+            }
+        }
+        return false;
+    }
+    public boolean isStartElement(String elementName) {
+        return reader.isStartElement() && elementName.equals(reader.getLocalName());
+    }
+
+    public boolean isEndElement(String elementName) {
+        return reader.isEndElement() && elementName.equals(reader.getLocalName());
+    }
+
+    public boolean goTo(String elementName) throws XMLStreamException {
+        return goTo(() -> isStartElement(elementName));
+    }
+    public boolean hasNext() throws XMLStreamException{
+        return reader.hasNext();
+    }
+
+    public String getAttribute(String name) {
+        return reader.getAttributeValue(null, name);
+    }
+
+    public String getAttributeRequired(String name) throws XMLStreamException {
+        String value = getAttribute(name);
+        if(value == null) {
+            throw new XMLStreamException("missing required attribute "+name);
+        }
+        return value;
+    }
+
+    public String getAttribute(String namespace, String name) {
+        return reader.getAttributeValue(namespace, name);
+    }
+
+    public Optional<String> getOptionalAttribute(String name) {
+        return Optional.ofNullable(reader.getAttributeValue(null, name));
+    }
+    public String getValueUntilEndElement(String elementName) throws XMLStreamException {
+        return getValueUntilEndElement(elementName, "");
+    }
+
+    public String getValueUntilEndElement(String elementName, String skipping) throws XMLStreamException {
+        StringBuilder sb = new StringBuilder();
+        int childElement = 1;
+        while (reader.hasNext()) {
+            int type = reader.next();
+            if (type == XMLStreamReader.CDATA || type == XMLStreamReader.CHARACTERS || type == XMLStreamReader.SPACE) {
+                sb.append(reader.getText());
+            } else if (type == XMLStreamReader.START_ELEMENT) {
+                if(skipping.equals(reader.getLocalName())) {
+                    getValueUntilEndElement(reader.getLocalName());
+                }else {
+                    childElement++;
+                }
+            } else if (type == XMLStreamReader.END_ELEMENT) {
+                childElement--;
+                if (elementName.equals(reader.getLocalName()) && childElement == 0) {
+                    break;
+                }
+            }
+        }
+        return sb.toString();
+    }
+    public String getLocalName() {
+        return reader.getLocalName();
+    }
+    public void forEach(String startChildElement, String untilEndElement, Consumer<XMLReader> consumer) throws XMLStreamException {
+        while (goTo(() -> isStartElement(startChildElement) || isEndElement(untilEndElement))) {
+            if (untilEndElement.equals(getLocalName())) {
+                break;
+            }
+            consumer.accept(this);
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        try {
+            if (reader != null) {
+                reader.close();
+            }
+        }catch (XMLStreamException ex1){
+            throw new IOException(ex1);
+        }
+        if(inputStream!=null){
+            inputStream.close();
+        }
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/utils/BaseSpliterator.java b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/BaseSpliterator.java
new file mode 100644
index 00000000..b12c98c3
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/BaseSpliterator.java
@@ -0,0 +1,344 @@
+package com.robin.rapidexcel.utils;
+
+import com.robin.comm.util.xls.ExcelColumnProp;
+import com.robin.comm.util.xls.ExcelSheetProp;
+import com.robin.core.base.exception.OperationNotSupportException;
+import com.robin.core.base.util.Const;
+import com.robin.rapidexcel.elements.Cell;
+import com.robin.rapidexcel.elements.CellAddress;
+import com.robin.rapidexcel.elements.CellType;
+import com.robin.rapidexcel.elements.WorkBook;
+import com.robin.rapidexcel.reader.XMLReader;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+
+import javax.xml.stream.XMLStreamException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+
+abstract class BaseSpliterator<T> implements Spliterator<T> {
+    final XMLReader r;
+    static WorkBook workBook;
+    int trackedRowIndex = 0;
+    boolean containHeaders=false;
+    static ExcelSheetProp prop;
+    boolean multipleType=false;
+    boolean needIdentifyColumn=false;
+    List<Cell> cells=new ArrayList<>();
+
+
+    public BaseSpliterator(WorkBook workBook, InputStream stream, ExcelSheetProp prop) throws XMLStreamException {
+        this.workBook=workBook;
+        this.r =new XMLReader(XMLFactoryUtils.getDefaultInputFactory(),stream);
+        this.prop=prop;
+        if(prop!=null){
+            containHeaders=prop.isFillHeader();
+            if(CollectionUtils.isEmpty(prop.getColumnPropList())){
+                needIdentifyColumn=true;
+            }
+        }else{
+            containHeaders=true;
+            needIdentifyColumn=true;
+            prop=new ExcelSheetProp();
+        }
+        r.goTo("sheetData");
+    }
+
+    @Override
+    public boolean tryAdvance(Consumer<? super T> action) {
+        try {
+            if (hasNext()) {
+                action.accept(next());
+                return true;
+            } else {
+                return false;
+            }
+        } catch (XMLStreamException e) {
+            throw new OperationNotSupportException(e);
+        }
+    }
+
+    @Override
+    public Spliterator<T> trySplit() {
+        return null;
+    }
+
+    @Override
+    public long estimateSize() {
+        return Long.MAX_VALUE;
+    }
+
+    @Override
+    public int characteristics() {
+        return DISTINCT | IMMUTABLE | NONNULL | ORDERED;
+    }
+
+
+    boolean hasNext() throws XMLStreamException {
+        if(containHeaders){
+            readHeader();
+        }
+        if (r.goTo(() -> r.isStartElement("row") || r.isEndElement("sheetData"))) {
+            return "row".equals(r.getLocalName());
+        } else {
+            return false;
+        }
+    }
+    void readHeader() throws XMLStreamException{
+        int trackedColIndex=0;
+        while (r.goTo(() -> r.isStartElement("c") || r.isEndElement("row"))) {
+            if ("row".equals(r.getLocalName())) {
+                break;
+            }
+            CellAddress addr = getCellAddressWithFallback(trackedColIndex);
+            Cell cell = parseCell(trackedColIndex++,false);
+            if(needIdentifyColumn && !ObjectUtils.isEmpty(cell.getValue())){
+                prop.addColumnProp(new ExcelColumnProp(cell.getValue().toString(),cell.getValue().toString(), Const.META_TYPE_STRING));
+            }
+        }
+        initHeader();
+    }
+    abstract void initHeader();
+    CellAddress getCellAddressWithFallback(int trackedColIndex) {
+        String cellRefOrNull = r.getAttribute("r");
+        return cellRefOrNull != null ?
+                new CellAddress(cellRefOrNull) :
+                new CellAddress(trackedRowIndex, trackedColIndex);
+    }
+
+    T next() throws XMLStreamException {
+        if (!"row".equals(r.getLocalName())) {
+            throw new NoSuchElementException();
+        }
+        int trackedColIndex = 0;
+        while (r.goTo(() -> r.isStartElement("c") || r.isEndElement("row"))) {
+            if ("row".equals(r.getLocalName())) {
+                break;
+            }
+            processCell(trackedColIndex++);
+        }
+        return constructReturn();
+    }
+
+    CellType parseType(String type) {
+        switch (type) {
+            case "b":
+                return CellType.BOOLEAN;
+            case "e":
+                return CellType.ERROR;
+            case "n":
+                return CellType.NUMBER;
+            case "str":
+                return CellType.FORMULA;
+            case "s":
+            case "inlineStr":
+                return CellType.STRING;
+        }
+        throw new IllegalStateException("Unknown cell type : " + type);
+    }
+
+    BiFunction<String, CellAddress,?> getParserForType(CellType type) {
+        switch (type) {
+            case BOOLEAN:
+                return BaseSpliterator::parseBoolean;
+            case NUMBER:
+                return BaseSpliterator::parseNumber;
+            case FORMULA:
+            case ERROR:
+                return BaseSpliterator::defaultValue;
+        }
+        throw new IllegalStateException("No parser defined for type " + type);
+    }
+
+
+
+    private static Object parseNumber(String s,CellAddress address) {
+        try {
+            if(ObjectUtils.isEmpty(s)){
+                return null;
+            }
+            int column=address.getColumn();
+            String tmpVal=s;
+            Object retObj=null;
+            if(!CollectionUtils.isEmpty(prop.getColumnPropList()) && prop.getColumnPropList().get(column)!=null){
+                ExcelColumnProp columnProp=prop.getColumnPropList().get(column);
+                switch (columnProp.getColumnType()){
+                    case Const.META_TYPE_INTEGER:
+                        if(tmpVal.contains(".")){
+                            int pos=tmpVal.indexOf(".");
+                            tmpVal=tmpVal.substring(0,pos);
+                        }
+                        retObj=Integer.parseInt(tmpVal);
+                        break;
+                    case Const.META_TYPE_BIGINT:
+                        if(tmpVal.contains(".")){
+                            int pos=tmpVal.indexOf(".");
+                            tmpVal=tmpVal.substring(0,pos);
+                        }
+                        retObj=Long.parseLong(tmpVal);
+                        break;
+                    case Const.META_TYPE_FLOAT:
+                        retObj=Float.parseFloat(tmpVal);
+                        break;
+                    case Const.META_TYPE_DOUBLE:
+                    case Const.META_TYPE_NUMERIC:
+                        retObj=Double.parseDouble(tmpVal);
+                        break;
+                    case Const.META_TYPE_TIMESTAMP:
+                        retObj=DateUtils.getLocalDateTime(Double.valueOf(s),workBook.isDate1904(),false);
+                        break;
+                    default:
+                        retObj=new BigDecimal(s);
+                }
+            }else{
+                retObj=new BigDecimal(s);
+            }
+            return retObj;
+        } catch (NumberFormatException e) {
+            throw new OperationNotSupportException("Cannot parse number : " + s);
+        }
+    }
+    private static String defaultValue(String s,CellAddress address){
+        return s;
+    }
+
+    private static Boolean parseBoolean(String s,CellAddress address) {
+        if ("0".equals(s)) {
+            return Boolean.FALSE;
+        } else if ("1".equals(s)) {
+            return Boolean.TRUE;
+        } else {
+            throw new OperationNotSupportException("Invalid boolean cell value: '" + s + "'. Expecting '0' or '1'.");
+        }
+    }
+    Cell parseCell(int trackedColIndex,boolean isMultiplex) throws XMLStreamException {
+        CellAddress addr = getCellAddressWithFallback(trackedColIndex);
+        String type = r.getOptionalAttribute("t").orElse("n");
+        String styleString = r.getAttribute("s");
+        String formatId = null;
+        String formatString = null;
+        if (styleString != null) {
+            int index = Integer.parseInt(styleString);
+            if (index < workBook.getFormats().size()) {
+                formatId = workBook.getFormats().get(index);
+                formatString = workBook.getNumFmtMap().get(formatId);
+            }
+        }
+
+        if ("inlineStr".equals(type)) {
+            return parseInlineStr(addr,isMultiplex);
+        } else if ("s".equals(type)) {
+            return parseString(addr,isMultiplex);
+        } else {
+            return parseOther(addr, type, formatId, formatString,isMultiplex);
+        }
+    }
+
+    Cell parseInlineStr(CellAddress addr,boolean isMultiplex) throws XMLStreamException {
+        Object value = null;
+        String formula = null;
+        String rawValue = null;
+        while (r.goTo(() -> r.isStartElement("is") || r.isEndElement("c") || r.isStartElement("f"))) {
+            if ("is".equals(r.getLocalName())) {
+                rawValue = r.getValueUntilEndElement("is");
+                value = rawValue;
+            } else if ("f".equals(r.getLocalName())) {
+                formula = r.getValueUntilEndElement("f");
+            } else {
+                break;
+            }
+        }
+        CellType cellType = formula == null ? CellType.STRING : CellType.FORMULA;
+        return  returnCell(isMultiplex,workBook,cellType,value,addr,formula,rawValue);
+    }
+    Cell empty(CellAddress addr, CellType type) {
+        return new Cell(workBook, type, "", addr, null, "");
+    }
+    Cell parseString(CellAddress addr,boolean isMultiplex) throws XMLStreamException {
+        r.goTo(() -> r.isStartElement("v") || r.isEndElement("c"));
+        if (r.isEndElement("c")) {
+            return empty(addr, CellType.STRING);
+        }
+        String v = r.getValueUntilEndElement("v");
+        if (v.isEmpty()) {
+            return empty(addr, CellType.STRING);
+        }
+        int index = Integer.parseInt(v);
+        String sharedStringValue = workBook.getShardingStrings().getValues().get(index);
+        Object value = sharedStringValue;
+        String formula = null;
+        String rawValue = sharedStringValue;
+        return  returnCell(isMultiplex,workBook,CellType.STRING,value,addr,formula,rawValue);
+    }
+    Cell parseOther(CellAddress addr, String type, String dataFormatId, String dataFormatString,boolean isMultiplex)
+            throws XMLStreamException {
+        CellType definedType = parseType(type);
+        BiFunction<String,CellAddress, ?> parser = getParserForType(definedType);
+
+        Object value = null;
+        String formula = null;
+        String rawValue = null;
+        while (r.goTo(() -> r.isStartElement("v") || r.isEndElement("c") || r.isStartElement("f"))) {
+            if ("v".equals(r.getLocalName())) {
+                rawValue = r.getValueUntilEndElement("v");
+                try {
+                    value = "".equals(rawValue) ? null : parser.apply(rawValue,addr);
+                } catch (OperationNotSupportException e) {
+                    definedType = CellType.ERROR;
+                }
+            } else if ("f".equals(r.getLocalName())) {
+                String ref = r.getAttribute("ref");
+                String t = r.getAttribute("t");
+                String si = r.getAttribute("si");
+                Integer siInt = si == null ? null : Integer.parseInt(si);
+                formula = r.getValueUntilEndElement("f");
+
+            } else {
+                break;
+            }
+        }
+        if (formula == null && value == null && definedType == CellType.NUMBER) {
+            //return new Cell(workBook, CellType.EMPTY, null, addr, null, rawValue);
+            return returnCell(isMultiplex,workBook, CellType.EMPTY, null, addr, null, rawValue);
+        } else {
+            CellType cellType = (formula != null) ? CellType.FORMULA : definedType;
+            //return new Cell(workBook, cellType, value, addr, formula, rawValue, dataFormatId, dataFormatString);
+            return returnCell(isMultiplex,workBook, cellType, value, addr, formula, rawValue, dataFormatId, dataFormatString);
+        }
+    }
+    abstract T constructReturn();
+
+    Cell returnCell(boolean isMultiplex,WorkBook workBook, CellType type, Object value, CellAddress addr, String formula, String rawValue) {
+        if(!isMultiplex || valueAllEmpty() || cells.get(addr.getColumn())==null) {
+            return new Cell(workBook, type, value, addr, formula, rawValue);
+        }else{
+            Cell cell=cells.get(addr.getColumn());
+            if(value!=null){
+                cell.setValue(value);
+            }
+            return cell;
+        }
+    }
+
+    Cell returnCell(boolean isMultiplex,WorkBook workBook, CellType type, Object value, CellAddress addr, String formula, String rawValue, String dataFormatId, String dataFormatString) {
+        if(!isMultiplex || valueAllEmpty() || cells.get(addr.getColumn())==null) {
+            return new Cell(workBook, type, value, addr, formula, rawValue,dataFormatId,dataFormatString);
+        }else{
+            Cell cell=cells.get(addr.getColumn());
+            if(value!=null){
+                cell.setValue(value);
+            }
+            return cell;
+        }
+    }
+    boolean valueAllEmpty(){
+        return CollectionUtils.isEmpty(cells) || cells.stream().allMatch(ObjectUtils::isEmpty);
+    }
+    abstract void processCell(int trackedColIndex) throws XMLStreamException;
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/utils/DateUtils.java b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/DateUtils.java
new file mode 100644
index 00000000..8bcc3b75
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/DateUtils.java
@@ -0,0 +1,132 @@
+package com.robin.rapidexcel.utils;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.Calendar;
+import java.util.Date;
+
+public class DateUtils {
+    private static final BigDecimal BD_NANOSEC_DAY = BigDecimal.valueOf(8.64E13);
+    private static final BigDecimal BD_MILISEC_RND = BigDecimal.valueOf(500000.0);
+    private static final BigDecimal BD_SECOND_RND = BigDecimal.valueOf(5.0E8);
+    private static final int BAD_DATE = -1;
+    public static final int SECONDS_PER_MINUTE = 60;
+    public static final int MINUTES_PER_HOUR = 60;
+    public static final int HOURS_PER_DAY = 24;
+    public static final int SECONDS_PER_DAY = (HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
+    public static final long DAY_MILLISECONDS = SECONDS_PER_DAY * 1000L;
+
+    public static Double convertDate(Date date) {
+        Calendar calStart = Calendar.getInstance();
+        calStart.setTime(date);
+        int year = calStart.get(Calendar.YEAR);
+        int dayOfYear = calStart.get(Calendar.DAY_OF_YEAR);
+        int hour = calStart.get(Calendar.HOUR_OF_DAY);
+        int minute = calStart.get(Calendar.MINUTE);
+        int second = calStart.get(Calendar.SECOND);
+        int milliSecond = calStart.get(Calendar.MILLISECOND);
+        return internalGetExcelDate(year, dayOfYear, hour, minute, second, milliSecond);
+    }
+
+    public static Double convertDate(LocalDateTime date) {
+        int year = date.getYear();
+        int dayOfYear = date.getDayOfYear();
+        int hour = date.getHour();
+        int minute = date.getMinute();
+        int second = date.getSecond();
+        int milliSecond = date.getNano() / 1_000_000;
+        return internalGetExcelDate(year, dayOfYear, hour, minute, second, milliSecond);
+    }
+
+
+    public static Double convertDate(LocalDate date) {
+        int year = date.getYear();
+        int dayOfYear = date.getDayOfYear();
+        int hour = 0;
+        int minute = 0;
+        int second = 0;
+        int milliSecond = 0;
+        return internalGetExcelDate(year, dayOfYear, hour, minute, second, milliSecond);
+    }
+
+
+    public static Double convertZonedDateTime(ZonedDateTime zdt) {
+        return convertDate(zdt.toLocalDateTime());
+    }
+
+    private static double internalGetExcelDate(int year, int dayOfYear, int hour, int minute, int second, int milliSecond) {
+        if (year < 1900) {
+            return BAD_DATE;
+        }
+
+        // Because of daylight time saving we cannot use
+        //     date.getTime() - calStart.getTimeInMillis()
+        // as the difference in milliseconds between 00:00 and 04:00
+        // can be 3, 4 or 5 hours but Excel expects it to always
+        // be 4 hours.
+        // E.g. 2004-03-28 04:00 CEST - 2004-03-28 00:00 CET is 3 hours
+        // and 2004-10-31 04:00 CET - 2004-10-31 00:00 CEST is 5 hours
+        double fraction = (((hour * 60.0 + minute) * 60.0 + second) * 1000.0 + milliSecond) / DAY_MILLISECONDS;
+
+        double value = fraction + absoluteDay(year, dayOfYear);
+
+        if (value >= 60) {
+            value++;
+        }
+
+        return value;
+    }
+
+    private static int absoluteDay(int year, int dayOfYear) {
+        return dayOfYear + daysInPriorYears(year);
+    }
+
+    static int daysInPriorYears(int yr) {
+        if (yr < 1900) {
+            throw new IllegalArgumentException("'year' must be 1900 or greater");
+        }
+        int yr1 = yr - 1;
+        int leapDays = yr1 / 4   // plus julian leap days in prior years
+                - yr1 / 100 // minus prior century years
+                + yr1 / 400 // plus years divisible by 400
+                - 460;      // leap days in previous 1900 years
+
+        return 365 * (yr - 1900) + leapDays;
+    }
+
+    public static LocalDateTime getLocalDateTime(double date) {
+        return getLocalDateTime(date, false, false);
+    }
+
+
+
+    public static LocalDateTime getLocalDateTime(double date, boolean use1904windowing, boolean roundSeconds) {
+        if (!isValidExcelDate(date)) {
+            return null;
+        } else {
+            BigDecimal bd = new BigDecimal(date);
+            int wholeDays = bd.intValue();
+            int startYear = 1900;
+            int dayAdjust = -1;
+            if (use1904windowing) {
+                startYear = 1904;
+                dayAdjust = 1;
+            } else if (wholeDays < 61) {
+                dayAdjust = 0;
+            }
+
+            LocalDateTime ldt = LocalDateTime.of(startYear, 1, 1, 0, 0);
+            ldt = ldt.plusDays((long)(wholeDays + dayAdjust - 1));
+            long nanosTime = bd.subtract(BigDecimal.valueOf((long)wholeDays)).multiply(BD_NANOSEC_DAY).add(roundSeconds ? BD_SECOND_RND : BD_MILISEC_RND).longValue();
+            ldt = ldt.plusNanos(nanosTime);
+            ldt = ldt.truncatedTo(roundSeconds ? ChronoUnit.SECONDS : ChronoUnit.MILLIS);
+            return ldt;
+        }
+    }
+    public static boolean isValidExcelDate(double value) {
+        return value > -4.9E-324;
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/utils/MapSpliterator.java b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/MapSpliterator.java
new file mode 100644
index 00000000..485c896f
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/MapSpliterator.java
@@ -0,0 +1,59 @@
+package com.robin.rapidexcel.utils;
+
+import com.robin.comm.util.xls.ExcelSheetProp;
+import com.robin.rapidexcel.elements.Cell;
+import com.robin.rapidexcel.elements.CellAddress;
+import com.robin.rapidexcel.elements.WorkBook;
+
+import javax.xml.stream.XMLStreamException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MapSpliterator extends BaseSpliterator<Map<String,Object>> {
+    private Map<String,Object> valueMap=new HashMap<>();
+    private List<Cell> cells=new ArrayList<>();
+
+    public MapSpliterator(WorkBook workBook, InputStream stream, ExcelSheetProp prop) throws XMLStreamException {
+        super(workBook, stream, prop);
+        multipleType=false;
+    }
+
+    @Override
+    void initHeader() {
+        cells=new ArrayList<>(prop.getColumnList().size());
+        for(int i=0;i<prop.getColumnPropList().size();i++){
+            cells.add(null);
+        }
+    }
+
+    @Override
+    Map<String,Object> next() throws XMLStreamException {
+        return super.next();
+    }
+
+    @Override
+    void processCell(int trackedColIndex) throws XMLStreamException {
+        Cell cell = parseCell(trackedColIndex,true);
+        CellAddress addr = cell.getAddress();
+        cells.set(addr.getColumn(), cell);
+    }
+
+    @Override
+    Map constructReturn() {
+        if(!prop.isStreamMode()){
+            valueMap=new HashMap<>();
+        }
+        for(int i=0;i<prop.getColumnPropList().size();i++){
+            if(cells.get(i)!=null && cells.get(i).getValue()!=null){
+                valueMap.put(prop.getColumnPropList().get(i).getColumnCode(),cells.get(i).getValue());
+            }
+        }
+        return valueMap;
+    }
+
+
+
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/utils/OPCPackage.java b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/OPCPackage.java
new file mode 100644
index 00000000..b9295797
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/OPCPackage.java
@@ -0,0 +1,314 @@
+package com.robin.rapidexcel.utils;
+
+import com.robin.core.base.exception.OperationNotSupportException;
+import com.robin.core.base.util.FileUtils;
+import com.robin.rapidexcel.elements.RelationShip;
+import com.robin.rapidexcel.elements.WorkSheet;
+import com.robin.rapidexcel.reader.XMLReader;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
+import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.commons.io.FileExistsException;
+import org.springframework.util.Assert;
+import org.springframework.util.ObjectUtils;
+
+import javax.xml.stream.XMLStreamException;
+import java.io.*;
+import java.util.*;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.regex.Pattern;
+import java.util.zip.ZipOutputStream;
+
+import static java.lang.String.format;
+
+public class OPCPackage implements Closeable {
+    private static final Pattern filenameRegex = Pattern.compile("^(.*/)([^/]+)$");
+    private static final Map<String, String> IMPLICIT_NUM_FMTS = new HashMap<>() {{
+        put("1", "0");
+        put("2", "0.00");
+        put("3", "#,##0");
+        put("4", "#,##0.00");
+        put("9", "0%");
+        put("10", "0.00%");
+        put("11", "0.00E+00");
+        put("12", "# ?/?");
+        put("13", "# ??/??");
+        put("14", "mm-dd-yy");
+        put("15", "d-mmm-yy");
+        put("16", "d-mmm");
+        put("17", "mmm-yy");
+        put("18", "h:mm AM/PM");
+        put("19", "h:mm:ss AM/PM");
+        put("20", "h:mm");
+        put("21", "h:mm:ss");
+        put("22", "m/d/yy h:mm");
+        put("37", "#,##0 ;(#,##0)");
+        put("38", "#,##0 ;[Red](#,##0)");
+        put("39", "#,##0.00;(#,##0.00)");
+        put("40", "#,##0.00;[Red](#,##0.00)");
+        put("45", "mm:ss");
+        put("46", "[h]:mm:ss");
+        put("47", "mmss.0");
+        put("48", "##0.0E+0");
+        put("49", "@");
+    }};
+    private ZipFile zipFile;
+    private ZipArchiveInputStream zipStreams;
+
+    private ZipOutputStream zipOutStream;
+    private BufferedOutputStream bufferedStream;
+    private FileOutputStream fileOutputStream;
+    private static int DEFAULTBUFFEREDSIZE=4096;
+    private ZipStreamEntry entry;
+    private String workBookPath;
+    private String shardingStringsPath;
+    private String stylePath;
+    private String appPath;
+    public static final String WORKBOOK_MAIN_CONTENT_TYPE =
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
+    public static final String WORKBOOK_EXCEL_MACRO_ENABLED_MAIN_CONTENT_TYPE =
+            "application/vnd.ms-excel.sheet.macroEnabled.main+xml";
+    public static final String SHARED_STRINGS_CONTENT_TYPE =
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml";
+    public static final String STYLE_CONTENT_TYPE =
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml";
+
+    public static final String CORE_PROPERTIY_CONTENTTYPE="application/vnd.openxmlformats-package.core-properties+xml";
+    public static final String EXTEND_PROPERTY_CONTENTTYPE="application/vnd.openxmlformats-officedocument.extended-properties+xml";
+
+    private Map<String, String> formatMap =new HashMap<>();
+    private List<String> formatIdList=new ArrayList<>();
+    private Map<String, RelationShip> relationShipMap=new HashMap<>();
+    private Map<String,RelationShip> relationShipTypeMap=new HashMap<>();
+    private String applicationName;
+    private String appVersion;
+
+
+    private OPCPackage(File zipFile){
+        try{
+            this.zipFile =new ZipFile(zipFile);
+            readInit();
+        }catch (IOException ex){
+
+        }
+
+    }
+    private OPCPackage(FileOutputStream fileOutputStream){
+        this(fileOutputStream,DEFAULTBUFFEREDSIZE);
+    }
+    private OPCPackage(FileOutputStream fileOutputStream,int bufferedSize){
+        Assert.isTrue(bufferedSize>0,"");
+        this.fileOutputStream=fileOutputStream;
+        this.bufferedStream=new BufferedOutputStream(fileOutputStream,bufferedSize);
+    }
+    private OPCPackage(OutputStream outputStream,int bufferedSize){
+        this.bufferedStream=new BufferedOutputStream(outputStream,bufferedSize>0?bufferedSize:DEFAULTBUFFEREDSIZE);
+    }
+    private OPCPackage(InputStream stream,String encode){
+        zipStreams=new ZipArchiveInputStream(stream,encode);
+        readInit();
+    }
+    private OPCPackage(InputStream stream){
+        this(stream,"UTF8");
+    }
+    private void readInit() throws OperationNotSupportException {
+        try {
+            if (ObjectUtils.isEmpty(zipFile) && !ObjectUtils.isEmpty(zipStreams)) {
+                entry = new ZipStreamEntry(zipStreams);
+            }
+            extractParts();
+            extractStyle(stylePath);
+            extractRelationShip(relsNameFor(workBookPath));
+            extractExtendProperty(appPath);
+        }catch (IOException|XMLStreamException ex){
+            throw new OperationNotSupportException(ex.getMessage());
+        }
+    }
+    public static OPCPackage open(File zipFile){
+        return new OPCPackage(zipFile);
+    }
+    public static OPCPackage open(InputStream stream){
+        return new OPCPackage(stream);
+    }
+    public static OPCPackage create(File fileName){
+        return create(fileName,DEFAULTBUFFEREDSIZE);
+    }
+    public static OPCPackage create(OutputStream outputStream){
+        return create(outputStream,DEFAULTBUFFEREDSIZE);
+    }
+    public static OPCPackage create(OutputStream outputStream,int bufferedSize){
+        try{
+            OPCPackage opcPackage=new OPCPackage(outputStream,bufferedSize);
+            return opcPackage;
+        }catch (Exception ex){
+
+        }
+        return null;
+    }
+    public static OPCPackage create(File fileName,int bufferedSize){
+        try{
+            FileUtils.mkDirReclusive(fileName.getAbsolutePath());
+            OPCPackage opcPackage=new OPCPackage(new FileOutputStream(fileName),bufferedSize);
+            return opcPackage;
+
+        }catch (FileExistsException|FileNotFoundException ex){
+
+        }
+        return null;
+    }
+    private void extractParts() throws XMLStreamException,IOException{
+        final String contentTypesXml = "[Content_Types].xml";
+        try(XMLReader reader=new XMLReader(XMLFactoryUtils.getDefaultInputFactory(),getRequiredEntryContent(contentTypesXml))){
+            while (reader.goTo(() -> reader.isStartElement("Override"))) {
+                String contentType = reader.getAttributeRequired("ContentType");
+                if(WORKBOOK_MAIN_CONTENT_TYPE.equals(contentType) ||WORKBOOK_EXCEL_MACRO_ENABLED_MAIN_CONTENT_TYPE.equals(contentType)){
+                    workBookPath=reader.getAttributeRequired("PartName");
+                }else if(SHARED_STRINGS_CONTENT_TYPE.equals(contentType)){
+                    shardingStringsPath= reader.getAttributeRequired("PartName");
+                }else if(STYLE_CONTENT_TYPE.equals(contentType)){
+                    stylePath=reader.getAttributeRequired("PartName");
+                }else if(EXTEND_PROPERTY_CONTENTTYPE.equals(contentType)){
+                    appPath=reader.getAttributeRequired("PartName");
+                }
+                if(workBookPath!=null && shardingStringsPath!=null && stylePath!=null){
+                    break;
+                }
+            }
+            if(workBookPath==null){
+                workBookPath="/xl/workbook.xml";
+            }
+        }
+    }
+    private void extractStyle(String stylePath) throws XMLStreamException,IOException{
+        try(XMLReader reader=new XMLReader(XMLFactoryUtils.getDefaultInputFactory(),getRequiredEntryContent(stylePath))){
+            AtomicBoolean insideCellXfs = new AtomicBoolean(false);
+            while (reader.goTo(() -> reader.isStartElement("numFmt") || reader.isStartElement("xf") ||
+                    reader.isStartElement("cellXfs") || reader.isEndElement("cellXfs"))) {
+                if (reader.isStartElement("cellXfs")) {
+                    insideCellXfs.set(true);
+                } else if (reader.isEndElement("cellXfs")) {
+                    insideCellXfs.set(false);
+                }
+                if ("numFmt".equals(reader.getLocalName())) {
+                    String formatCode = reader.getAttributeRequired("formatCode");
+                    formatMap.put(reader.getAttributeRequired("numFmtId"), formatCode);
+                } else if (insideCellXfs.get() && reader.isStartElement("xf")) {
+                    String numFmtId = reader.getAttribute("numFmtId");
+                    formatIdList.add(numFmtId);
+                    if (IMPLICIT_NUM_FMTS.containsKey(numFmtId)) {
+                        formatMap.put(numFmtId, IMPLICIT_NUM_FMTS.get(numFmtId));
+                    }
+                }
+            }
+        }
+    }
+    private static String relsNameFor(String entryName) {
+        return filenameRegex.matcher(entryName).replaceFirst("$1_rels/$2.rels");
+    }
+    private void extractRelationShip(String relationPath) throws XMLStreamException,IOException{
+        String xlFolder = relationPath.substring(0, relationPath.indexOf("_rel"));
+        try(XMLReader reader=new XMLReader(XMLFactoryUtils.getDefaultInputFactory(),getRequiredEntryContent(relationPath))){
+            while(reader.goTo("Relationship")){
+                String id = reader.getAttribute("Id");
+                String target = reader.getAttribute("Target");
+                String type=reader.getAttribute("Type");
+                // if name does not start with /, it is a relative path
+                if (!target.startsWith("/")) {
+                    target = xlFolder + target;
+                } // else it is an absolute path
+                relationShipMap.put(id, new RelationShip(id,target,type));
+            }
+        }
+    }
+    private void extractExtendProperty(String extendPropPath) throws XMLStreamException,IOException{
+        try(XMLReader reader=new XMLReader(XMLFactoryUtils.getDefaultInputFactory(),getRequiredEntryContent(extendPropPath))){
+            while (reader.goTo(()->reader.isStartElement("Application") ||reader.isStartElement("AppVersion"))){
+                if("Application".equals(reader.getLocalName())){
+                    applicationName=reader.getValueUntilEndElement("Application");
+                }else if("AppVersion".equals(reader.getLocalName())){
+                    appVersion=reader.getValueUntilEndElement("AppVersion");
+                }
+            }
+        }
+    }
+    private InputStream getRequiredEntryContent(String name) throws IOException {
+        return Optional.ofNullable(getEntryContent(name))
+                .orElseThrow(() -> new IOException(name + " not found"));
+    }
+    private InputStream getEntryContent(String name) throws IOException{
+        Assert.notNull(name,"");
+        String tname=name;
+        if (tname.startsWith("/")) {
+            tname = tname.substring(1);
+        }
+        if(!ObjectUtils.isEmpty(zipFile)){
+            ZipArchiveEntry entry1=zipFile.getEntry(tname);
+            if(entry1==null){
+                Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
+                while (entries.hasMoreElements()) {
+                    ZipArchiveEntry e = entries.nextElement();
+                    if (e.getName().equalsIgnoreCase(tname)) {
+                        return zipFile.getInputStream(e);
+                    }
+                }
+                return null;
+            }
+            return zipFile.getInputStream(entry1);
+        }else if(!ObjectUtils.isEmpty(entry)){
+            return entry.getInputStream(tname);
+        }else{
+            throw new IOException("init incorrect!");
+        }
+
+    }
+    public InputStream getWorkBookContent() throws IOException{
+        return getRequiredEntryContent(workBookPath);
+    }
+    public InputStream getSheetContent(WorkSheet sheet) throws IOException {
+        RelationShip ship = this.relationShipMap.get(sheet.getId());
+        if (ship==null || ship.getTarget() == null) {
+            String msg = format("Sheet#%s '%s' is missing an entry in workbook rels (for id: '%s')",
+                    sheet.getIndex(), sheet.getName(), sheet.getId());
+            throw new IOException(msg);
+        }
+        return getRequiredEntryContent(ship.getTarget());
+    }
+    public InputStream getShardingStrings() throws IOException{
+        return getRequiredEntryContent(shardingStringsPath);
+    }
+
+    @Override
+    public void close() throws IOException {
+        if(zipFile!=null){
+            zipFile.close();
+        }
+        if(entry!=null){
+            entry.close();
+        }
+        if(bufferedStream!=null){
+            bufferedStream.flush();
+            if(fileOutputStream!=null){
+                fileOutputStream.close();
+            }
+            if(zipOutStream!=null){
+                zipOutStream.closeEntry();
+                zipOutStream.close();
+            }
+        }
+    }
+
+    public String getApplicationName() {
+        return applicationName;
+    }
+
+    public String getAppVersion() {
+        return appVersion;
+    }
+    public List<String> getFormatIdList(){
+        return formatIdList;
+    }
+    public Map<String,String> getFormatMap(){
+        return formatMap;
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/utils/RowSpliterator.java b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/RowSpliterator.java
new file mode 100644
index 00000000..07376b77
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/RowSpliterator.java
@@ -0,0 +1,47 @@
+package com.robin.rapidexcel.utils;
+
+import com.robin.comm.util.xls.ExcelSheetProp;
+import com.robin.rapidexcel.elements.Cell;
+import com.robin.rapidexcel.elements.CellAddress;
+import com.robin.rapidexcel.elements.Row;
+import com.robin.rapidexcel.elements.WorkBook;
+
+import javax.xml.stream.XMLStreamException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+public class RowSpliterator extends BaseSpliterator<Row> {
+
+    private Row row;
+
+    public RowSpliterator(WorkBook workBook, InputStream stream,ExcelSheetProp prop) throws XMLStreamException {
+        super(workBook, stream, prop);
+    }
+
+
+    @Override
+    void initHeader() {
+        cells=new ArrayList<>(prop.getColumnList().size());
+        for(int i=0;i<prop.getColumnPropList().size();i++){
+            cells.add(null);
+        }
+    }
+
+    @Override
+    void processCell(int trackedColIndex) throws XMLStreamException {
+        Cell cell = parseCell(trackedColIndex,prop.isStreamMode());
+        CellAddress addr = cell.getAddress();
+        cells.set(addr.getColumn(), cell);
+    }
+
+
+    @Override
+    Row constructReturn() {
+        if(!prop.isStreamMode()){
+            row=new Row(cells);
+        }else{
+            row.setCells(cells);
+        }
+        return row;
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/utils/XMLFactoryUtils.java b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/XMLFactoryUtils.java
new file mode 100644
index 00000000..363884fb
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/XMLFactoryUtils.java
@@ -0,0 +1,26 @@
+package com.robin.rapidexcel.utils;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+
+public class XMLFactoryUtils {
+    private static XMLInputFactory inputFactory=defaultInput();
+    private static XMLOutputFactory outputFactory=defaultOutput();
+    private static XMLInputFactory defaultInput(){
+        XMLInputFactory factory  = new com.fasterxml.aalto.stax.InputFactoryImpl();
+        // To prevent XML External Entity (XXE) attacks
+        factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
+        factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
+        return factory;
+    }
+    private static XMLOutputFactory defaultOutput(){
+        XMLOutputFactory factory  = new com.fasterxml.aalto.stax.OutputFactoryImpl();
+        return factory;
+    }
+    public static XMLInputFactory getDefaultInputFactory(){
+        return inputFactory;
+    }
+    public static XMLOutputFactory getDefaultOutputFactory(){
+        return outputFactory;
+    }
+}
diff --git a/rapidexcel/src/main/java/com/robin/rapidexcel/utils/ZipStreamEntry.java b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/ZipStreamEntry.java
new file mode 100644
index 00000000..d166b48c
--- /dev/null
+++ b/rapidexcel/src/main/java/com/robin/rapidexcel/utils/ZipStreamEntry.java
@@ -0,0 +1,89 @@
+package com.robin.rapidexcel.utils;
+
+import com.robin.core.fileaccess.util.ByteBufferInputStream;
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
+import org.apache.commons.io.IOUtils;
+import org.apache.flink.core.memory.MemorySegment;
+import org.apache.flink.core.memory.MemorySegmentFactory;
+import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ZipStreamEntry implements Closeable {
+    private Map<String, InputStream> zipEntrys=new HashMap<>();
+    private List<MemorySegment> segmentList=new ArrayList<>();
+
+    private ZipArchiveInputStream stream;
+    private static final long DEFAULTINMEMORYSIZE=50*1024*1024L;
+
+    public ZipStreamEntry(ZipArchiveInputStream inputStream) throws IOException{
+        this(inputStream,DEFAULTINMEMORYSIZE);
+    }
+
+    public ZipStreamEntry(ZipArchiveInputStream inputStream,long maxInMemorySize) throws IOException{
+        Assert.notNull(inputStream,"");
+        ArchiveEntry entry;
+        try {
+            while ((entry = inputStream.getNextEntry())!= null) {
+                long entrySize=entry.getSize();
+                if(entry.getSize()>0L && entrySize < 2147483647L){
+                    if(entry.getSize()>maxInMemorySize){
+                        MemorySegment segment= MemorySegmentFactory.allocateOffHeapUnsafeMemory(Long.valueOf(entrySize).intValue(),this,new Thread(){});
+                        segmentList.add(segment);
+                        ByteBufferInputStream inp=new ByteBufferInputStream(segment.getOffHeapBuffer(), IOUtils.toByteArray(inputStream));
+                        zipEntrys.put(entry.getName(),inp);
+                    }else{
+                        InputStream inp=new ByteArrayInputStream(IOUtils.toByteArray(inputStream));
+                        zipEntrys.put(entry.getName(),inp);
+                    }
+                }else{
+                    throw new IOException("file too large");
+                }
+            }
+        }catch (IOException ex){
+
+        }
+    }
+    public InputStream getInputStream(String name){
+        String tname=name;
+        if(tname.startsWith("/")){
+            tname=name.substring(1);
+        }
+        if(zipEntrys.containsKey(tname)){
+            return zipEntrys.get(tname);
+        }else if(zipEntrys.containsKey(tname.toLowerCase())){
+            return zipEntrys.get(tname.toLowerCase());
+        }else if(zipEntrys.containsKey(tname.toUpperCase())){
+            return zipEntrys.get(tname.toUpperCase());
+        }
+        return null;
+    }
+
+    @Override
+    public void close() throws IOException {
+        if(!CollectionUtils.isEmpty(zipEntrys)){
+            for(InputStream inp: zipEntrys.values()){
+                try{
+                    inp.close();
+                }catch (IOException ex){
+
+                }
+            }
+        }
+        if(!CollectionUtils.isEmpty(segmentList)){
+            segmentList.forEach(seg->{
+                seg.free();
+            });
+        }
+
+    }
+}
diff --git a/tracer/src/main/java/com/robin/tracer/utils/TracerConstant.java b/tracer/src/main/java/com/robin/tracer/utils/TracerConstant.java
index 119ebc9d..ea1c2055 100644
--- a/tracer/src/main/java/com/robin/tracer/utils/TracerConstant.java
+++ b/tracer/src/main/java/com/robin/tracer/utils/TracerConstant.java
@@ -1,16 +1,6 @@
 package com.robin.tracer.utils;
 
-/**
- * <p>Project:  frame</p>
- *
- * <p>Description: TracerConstant </p>
- *
- * <p>Copyright: Copyright (c) 2021 modified at 2021-07-01</p>
- *
- *
- * @author luoming
- * @version 1.0
- */
+
 public class TracerConstant {
     public static final String APPNAME_KEY="spring.application.name";
     public static final String ENABLE_DATASOURCETRACE="tracer.datasource";
diff --git a/web/src/main/java/com/robin/core/web/service/ILoginService.java b/web/src/main/java/com/robin/core/web/service/ILoginService.java
index cef23d53..4d76bace 100644
--- a/web/src/main/java/com/robin/core/web/service/ILoginService.java
+++ b/web/src/main/java/com/robin/core/web/service/ILoginService.java
@@ -3,10 +3,13 @@
 import com.robin.core.base.exception.ServiceException;
 import com.robin.core.web.util.Session;
 
+import java.util.List;
+
 public interface ILoginService {
     Session doLogin(String accountName, String password) throws ServiceException;
     void getRights(Session session);
     Session simpleLogin(String accountName, String password) throws ServiceException;
     Session ssoGetUserById(Long userId);
     Session ssoGetUser(String userName);
+    List<Long> getUserRoles(Long userId);
 }
diff --git a/web/src/main/java/com/robin/core/web/util/RestTemplateUtils.java b/web/src/main/java/com/robin/core/web/util/RestTemplateUtils.java
index db5d8586..bd86fa88 100644
--- a/web/src/main/java/com/robin/core/web/util/RestTemplateUtils.java
+++ b/web/src/main/java/com/robin/core/web/util/RestTemplateUtils.java
@@ -41,7 +41,7 @@ public static Map<String,Object> getResultFromSsoRest(String requestUrl,String t
     }
     public static Map<String,Object> getResultFromGateWayRest(String requestUrl,String token,Object... objects){
         Environment environment= SpringContextHolder.getBean(Environment.class);
-        String url=environment.getProperty("backgroud.gatewayUrl")+requestUrl;
+        String url=environment.getProperty("project.gatewayUrl")+requestUrl;
         HttpHeaders requestHeaders = new HttpHeaders();
         if(!StringUtils.isEmpty(token)) {
             requestHeaders.add(HttpHeaders.AUTHORIZATION,"Bearer "+token);
diff --git a/web/src/main/java/com/robin/core/web/util/WebConstant.java b/web/src/main/java/com/robin/core/web/util/WebConstant.java
index 0ba4f67a..c854c6d4 100644
--- a/web/src/main/java/com/robin/core/web/util/WebConstant.java
+++ b/web/src/main/java/com/robin/core/web/util/WebConstant.java
@@ -57,6 +57,28 @@ public Short getValue(){
             return value;
         }
     }
+    public enum TENANT_KEYS{
+        PERMISSIONS_DEFAULT("PERMISSIONS_DEFAULT"),
+        ROLES_DEFAULT("ROLES_DEFAULT"),
+        ALL_PERMISSIONS("allPermissions"),
+        MANAGER_PERMISSION("managerPermissions"),
+        ORDINARY_PERMISSIONS("ordinaryPermissions"),
+        USER_CAPACITY("userCapacity"),
+        USE_DIVIDED_STORAGE("useDividedStorage"),
+        DIVIDE_STORAGE_TYPE("dividedStorageType"),
+        USE_CLOUD_STORAGE("useCloudStorage"),
+        CLOUD_TYPE("cloudType"),
+        CLOUD_ACCESSKEY("cloudAccessKey"),
+        CLOUD_SECRETKEY("cloudSecretKey");
+        private String key;
+        TENANT_KEYS(String key){
+            this.key=key;
+        }
+
+        public String getKey() {
+            return key;
+        }
+    }
     public static final String SYSPARAMS_PERMISSIONS_PERFIX="PERMISSIONS_";
     public static final String SYSPARAMS_PERMISSIONS_ORG_PERFIX="PERMISSIONS_ORG";
     public static final String SYSPARAMS_PERMISSIONS_ORDINARY_PERFIX="PERMISSIONS_ORDINARY";
diff --git a/webui/src/main/java/com/robin/webui/contorller/system/SysUserContorller.java b/webui/src/main/java/com/robin/webui/contorller/system/SysUserContorller.java
index d6767250..f0b004fa 100644
--- a/webui/src/main/java/com/robin/webui/contorller/system/SysUserContorller.java
+++ b/webui/src/main/java/com/robin/webui/contorller/system/SysUserContorller.java
@@ -25,7 +25,7 @@ public String userList(HttpServletRequest request, HttpServletResponse response)
             request.setAttribute("orgId",session.getOrgId());
         }
         request.setAttribute("resps", StringUtils.join(session.getResponsiblitys().toArray(),","));
-        return "/user/user_list";
+        return "user/user_list";
     }
     @GetMapping("/showright")
     public String userRight(HttpServletRequest request, HttpServletResponse response) {
diff --git a/webui/src/main/java/com/robin/webui/contorller/user/LoginController.java b/webui/src/main/java/com/robin/webui/contorller/user/LoginController.java
index 5e986624..e10677e2 100644
--- a/webui/src/main/java/com/robin/webui/contorller/user/LoginController.java
+++ b/webui/src/main/java/com/robin/webui/contorller/user/LoginController.java
@@ -83,245 +83,7 @@ public Map<String, Object> ssoLogin(HttpServletRequest request, HttpServletRespo
         return retMap;
     }
 
-    @PostMapping
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            ("/loginold")
+    @PostMapping("/loginold")
     @ResponseBody
     public Map<String, Object> login(HttpServletRequest request, HttpServletResponse response, @RequestParam String accountName, @RequestParam String password) {
         Map<String, Object> retMap = new HashMap<>();
