From 846600dafb82b062eaf8de9ff5c5f22abc6da5d0 Mon Sep 17 00:00:00 2001
From: 13693261870 <252740454@qq.com>
Date: 星期五, 20 六月 2025 13:46:11 +0800
Subject: [PATCH] 添加common模块

---
 se-common/src/main/java/com/terra/common/exception/file/FileSizeLimitExceededException.java                   |   16 
 se-common/src/main/java/com/terra/common/enums/UserStatus.java                                                |   30 
 se-common/src/main/java/com/terra/common/web/domain/BaseEntity.java                                           |  118 
 se-common/src/main/java/com/terra/common/web/page/TableDataInfo.java                                          |   85 
 se-common/src/main/java/com/terra/common/exception/CheckedException.java                                      |   31 
 se-common/src/main/java/com/terra/common/exception/user/UserPasswordNotMatchException.java                    |   16 
 se-common/src/main/java/com/terra/common/web/controller/BaseController.java                                   |  160 
 se-common/src/main/java/com/terra/common/constant/HttpStatus.java                                             |   94 
 se-common/src/main/java/com/terra/common/exception/DemoModeException.java                                     |   15 
 se-common/src/main/java/com/terra/common/exception/file/FileNameLengthLimitExceededException.java             |   16 
 se-common/src/main/java/com/terra/common/exception/auth/NotRoleException.java                                 |   23 
 se-common/src/main/java/com/terra/common/utils/sql/SqlUtil.java                                               |   70 
 se-common/src/main/java/com/terra/common/utils/uuid/UUID.java                                                 |  484 ++
 se-common/src/main/java/com/terra/common/web/domain/AjaxResult.java                                           |  216 +
 se-common/src/main/java/com/terra/common/utils/poi/ExcelUtil.java                                             | 1626 +++++++++
 se-common/src/main/java/com/terra/common/exception/file/FileUploadException.java                              |   61 
 se-common/src/main/java/com/terra/common/exception/UtilException.java                                         |   26 
 se-common/src/main/java/com/terra/common/utils/file/MimeTypeUtils.java                                        |   59 
 se-common/src/main/java/com/terra/common/utils/poi/ExcelHandlerAdapter.java                                   |   24 
 se-common/src/main/java/com/terra/common/web/page/TableSupport.java                                           |   56 
 se-common/src/main/java/com/terra/common/utils/JwtUtils.java                                                  |  123 
 se-common/src/main/java/com/terra/common/constant/TokenConstants.java                                         |   20 
 se-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports |    1 
 se-common/src/main/java/com/terra/common/annotation/Excel.java                                                |  187 +
 se-common/src/main/java/com/terra/common/exception/InnerAuthException.java                                    |   16 
 se-common/src/main/java/com/terra/common/utils/bean/BeanUtils.java                                            |  110 
 se-common/src/main/java/com/terra/common/utils/uuid/IdUtils.java                                              |   49 
 se-common/src/main/java/com/terra/common/constant/ScheduleConstants.java                                      |   50 
 se-common/src/main/java/com/terra/common/exception/file/FileException.java                                    |   19 
 se-common/src/main/java/com/terra/common/utils/bean/BeanValidators.java                                       |   24 
 se-common/src/main/java/com/terra/common/text/StrFormatter.java                                               |   92 
 se-common/src/main/java/com/terra/common/xss/Xss.java                                                         |   27 
 se-common/src/main/java/com/terra/common/xss/XssValidator.java                                                |   39 
 se-common/src/main/java/com/terra/common/utils/file/ImageUtils.java                                           |   84 
 se-common/src/main/java/com/terra/common/constant/UserConstants.java                                          |   88 
 se-common/src/main/java/com/terra/common/exception/GlobalException.java                                       |   58 
 pom.xml                                                                                                       |   49 
 se-common/src/main/java/com/terra/common/constant/ServiceNameConstants.java                                   |   24 
 se-common/src/main/java/com/terra/common/text/CharsetKit.java                                                 |   86 
 se-common/src/main/java/com/terra/common/exception/file/InvalidExtensionException.java                        |   80 
 se-common/src/main/java/com/terra/common/constant/SecurityConstants.java                                      |   49 
 se-common/src/main/java/com/terra/common/exception/PreAuthorizeException.java                                 |   15 
 se-common/src/main/java/com/terra/common/utils/uuid/Seq.java                                                  |   86 
 se-common/src/main/java/com/terra/common/exception/auth/NotPermissionException.java                           |   23 
 se-common/src/main/java/com/terra/common/utils/SpringUtils.java                                               |  114 
 se-common/src/main/java/com/terra/common/exception/user/UserException.java                                    |   18 
 se-common/src/main/java/com/terra/common/utils/reflect/ReflectUtils.java                                      |  410 ++
 se-common/src/main/java/com/terra/common/utils/sign/Base64.java                                               |  291 +
 se-common/src/main/java/com/terra/common/context/SecurityContextHolder.java                                   |   98 
 se-common/src/main/java/com/terra/common/exception/CaptchaException.java                                      |   16 
 se-common/src/main/java/com/terra/common/exception/user/CaptchaExpireException.java                           |   16 
 se-common/src/main/java/com/terra/common/utils/ServletUtils.java                                              |  333 +
 se-common/src/main/java/com/terra/common/utils/ip/IpUtils.java                                                |  382 ++
 se-common/src/main/java/com/terra/common/utils/ExceptionUtil.java                                             |   39 
 se-common/src/main/java/com/terra/common/utils/PageUtils.java                                                 |   35 
 se-common/src/main/java/com/terra/common/exception/auth/NotLoginException.java                                |   16 
 se-common/src/main/java/com/terra/common/constant/Constants.java                                              |  135 
 se-common/src/main/java/com/terra/common/utils/StringUtils.java                                               |  633 +++
 se-common/src/main/java/com/terra/common/utils/html/HTMLFilter.java                                           |  570 +++
 se-common/src/main/java/com/terra/common/web/page/PageDomain.java                                             |  101 
 se-common/src/main/java/com/terra/common/utils/file/FileUtils.java                                            |  253 +
 se-common/src/main/java/com/terra/common/utils/DateUtils.java                                                 |  191 +
 se-common/src/main/java/com/terra/common/web/domain/TreeEntity.java                                           |   79 
 se-common/src/main/java/com/terra/common/utils/file/FileTypeUtils.java                                        |   95 
 se-common/src/main/java/com/terra/common/constant/GenConstants.java                                           |  117 
 se-common/src/main/java/com/terra/common/exception/job/TaskException.java                                     |   34 
 se-common/src/main/java/com/terra/common/annotation/Excels.java                                               |   18 
 se-common/src/main/java/com/terra/common/utils/html/EscapeUtil.java                                           |  167 
 se-common/src/main/java/com/terra/common/domain/R.java                                                        |  115 
 se-common/src/main/java/com/terra/common/text/Convert.java                                                    | 1018 +++++
 se-common/pom.xml                                                                                             |  112 
 se-common/src/main/java/com/terra/common/exception/base/BaseException.java                                    |   79 
 se-common/src/main/java/com/terra/common/exception/ServiceException.java                                      |   74 
 se-common/src/main/java/com/terra/common/constant/CacheConstants.java                                         |   59 
 74 files changed, 10,243 insertions(+), 0 deletions(-)

diff --git a/pom.xml b/pom.xml
index 6bfbb85..ae59529 100644
--- a/pom.xml
+++ b/pom.xml
@@ -111,6 +111,41 @@
                 <version>${tomcat.version}</version>
             </dependency>
 
+            <!-- Springdoc webmvc 渚濊禆閰嶇疆 -->
+            <dependency>
+                <groupId>org.springdoc</groupId>
+                <artifactId>springdoc-openapi-ui</artifactId>
+                <version>${springdoc.version}</version>
+            </dependency>
+
+            <!-- pagehelper 鍒嗛〉鎻掍欢 -->
+            <dependency>
+                <groupId>com.github.pagehelper</groupId>
+                <artifactId>pagehelper-spring-boot-starter</artifactId>
+                <version>${pagehelper.boot.version}</version>
+            </dependency>
+
+            <!-- io甯哥敤宸ュ叿绫� -->
+            <dependency>
+                <groupId>commons-io</groupId>
+                <artifactId>commons-io</artifactId>
+                <version>${commons.io.version}</version>
+            </dependency>
+
+            <!-- excel宸ュ叿 -->
+            <dependency>
+                <groupId>org.apache.poi</groupId>
+                <artifactId>poi-ooxml</artifactId>
+                <version>${poi.version}</version>
+            </dependency>
+
+            <!-- 浠g爜鐢熸垚浣跨敤妯℃澘 -->
+            <dependency>
+                <groupId>org.apache.velocity</groupId>
+                <artifactId>velocity-engine-core</artifactId>
+                <version>${velocity.version}</version>
+            </dependency>
+
             <!-- JSON 瑙f瀽鍣ㄥ拰鐢熸垚鍣� -->
             <dependency>
                 <groupId>com.alibaba.fastjson2</groupId>
@@ -118,10 +153,24 @@
                 <version>${fastjson.version}</version>
             </dependency>
 
+            <!-- JWT -->
+            <dependency>
+                <groupId>io.jsonwebtoken</groupId>
+                <artifactId>jjwt</artifactId>
+                <version>${jjwt.version}</version>
+            </dependency>
+
+            <!-- 绾跨▼浼犻�掑�� -->
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>transmittable-thread-local</artifactId>
+                <version>${transmittable-thread-local.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
     <modules>
+        <module>se-common</module>
         <module>se-gateway</module>
         <module>se-system</module>
     </modules>
diff --git a/se-common/pom.xml b/se-common/pom.xml
new file mode 100644
index 0000000..9327875
--- /dev/null
+++ b/se-common/pom.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>com.terra</groupId>
+        <artifactId>terra</artifactId>
+        <version>1.0.2</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>se-common</artifactId>
+    
+    <description>
+        閫氱敤妯″潡
+    </description>
+
+    <dependencies>
+
+        <!-- SpringCloud Openfeign -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        
+        <!-- SpringCloud Loadbalancer -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
+        </dependency>
+
+        <!-- Spring Context Support -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+
+        <!-- Spring Web -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+
+        <!-- Transmittable ThreadLocal -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>transmittable-thread-local</artifactId>
+        </dependency>
+
+        <!-- Pagehelper -->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- Hibernate Validator -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <!-- Jackson -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+
+        <!-- Alibaba Fastjson -->
+        <dependency>
+            <groupId>com.alibaba.fastjson2</groupId>
+            <artifactId>fastjson2</artifactId>
+        </dependency>
+
+        <!-- Jwt -->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+        </dependency>
+
+        <!-- Jaxb -->
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+        </dependency>
+
+        <!-- Apache Lang3 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <!-- Commons Io -->
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+
+        <!-- excel宸ュ叿 -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+        </dependency>
+
+        <!-- Java Servlet -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
diff --git a/se-common/src/main/java/com/terra/common/annotation/Excel.java b/se-common/src/main/java/com/terra/common/annotation/Excel.java
new file mode 100644
index 0000000..53885d6
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/annotation/Excel.java
@@ -0,0 +1,187 @@
+package com.terra.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigDecimal;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import com.terra.common.utils.poi.ExcelHandlerAdapter;
+
+/**
+ * 鑷畾涔夊鍑篍xcel鏁版嵁娉ㄨВ
+ * 
+ * @author ruoyi
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Excel
+{
+    /**
+     * 瀵煎嚭鏃跺湪excel涓帓搴�
+     */
+    public int sort() default Integer.MAX_VALUE;
+
+    /**
+     * 瀵煎嚭鍒癊xcel涓殑鍚嶅瓧.
+     */
+    public String name() default "";
+
+    /**
+     * 鏃ユ湡鏍煎紡, 濡�: yyyy-MM-dd
+     */
+    public String dateFormat() default "";
+
+    /**
+     * 璇诲彇鍐呭杞〃杈惧紡 (濡�: 0=鐢�,1=濂�,2=鏈煡)
+     */
+    public String readConverterExp() default "";
+
+    /**
+     * 鍒嗛殧绗︼紝璇诲彇瀛楃涓茬粍鍐呭
+     */
+    public String separator() default ",";
+
+    /**
+     * BigDecimal 绮惧害 榛樿:-1(榛樿涓嶅紑鍚疊igDecimal鏍煎紡鍖�)
+     */
+    public int scale() default -1;
+
+    /**
+     * BigDecimal 鑸嶅叆瑙勫垯 榛樿:BigDecimal.ROUND_HALF_EVEN
+     */
+    public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
+
+    /**
+     * 瀵煎嚭鏃跺湪excel涓瘡涓垪鐨勯珮搴�
+     */
+    public double height() default 14;
+
+    /**
+     * 瀵煎嚭鏃跺湪excel涓瘡涓垪鐨勫搴�
+     */
+    public double width() default 16;
+
+    /**
+     * 鏂囧瓧鍚庣紑,濡�% 90 鍙樻垚90%
+     */
+    public String suffix() default "";
+
+    /**
+     * 褰撳�间负绌烘椂,瀛楁鐨勯粯璁ゅ��
+     */
+    public String defaultValue() default "";
+
+    /**
+     * 鎻愮ず淇℃伅
+     */
+    public String prompt() default "";
+
+    /**
+     * 鏄惁鍏佽鍐呭鎹㈣ 
+     */
+    public boolean wrapText() default false;
+
+    /**
+     * 璁剧疆鍙兘閫夋嫨涓嶈兘杈撳叆鐨勫垪鍐呭.
+     */
+    public String[] combo() default {};
+
+    /**
+     * 鏄惁闇�瑕佺旱鍚戝悎骞跺崟鍏冩牸,搴斿闇�姹�:鍚湁list闆嗗悎鍗曞厓鏍�)
+     */
+    public boolean needMerge() default false;
+
+    /**
+     * 鏄惁瀵煎嚭鏁版嵁,搴斿闇�姹�:鏈夋椂鎴戜滑闇�瑕佸鍑轰竴浠芥ā鏉�,杩欐槸鏍囬闇�瑕佷絾鍐呭闇�瑕佺敤鎴锋墜宸ュ~鍐�.
+     */
+    public boolean isExport() default true;
+
+    /**
+     * 鍙︿竴涓被涓殑灞炴�у悕绉�,鏀寔澶氱骇鑾峰彇,浠ュ皬鏁扮偣闅斿紑
+     */
+    public String targetAttr() default "";
+
+    /**
+     * 鏄惁鑷姩缁熻鏁版嵁,鍦ㄦ渶鍚庤拷鍔犱竴琛岀粺璁℃暟鎹�诲拰
+     */
+    public boolean isStatistics() default false;
+
+    /**
+     * 瀵煎嚭绫诲瀷锛�0鏁板瓧 1瀛楃涓诧級
+     */
+    public ColumnType cellType() default ColumnType.STRING;
+
+    /**
+     * 瀵煎嚭鍒楀ご鑳屾櫙棰滆壊
+     */
+    public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
+
+    /**
+     * 瀵煎嚭鍒楀ご瀛椾綋棰滆壊
+     */
+    public IndexedColors headerColor() default IndexedColors.WHITE;
+
+    /**
+     * 瀵煎嚭鍗曞厓鏍艰儗鏅鑹�
+     */
+    public IndexedColors backgroundColor() default IndexedColors.WHITE;
+
+    /**
+     * 瀵煎嚭鍗曞厓鏍煎瓧浣撻鑹�
+     */
+    public IndexedColors color() default IndexedColors.BLACK;
+
+    /**
+     * 瀵煎嚭瀛楁瀵归綈鏂瑰紡
+     */
+    public HorizontalAlignment align() default HorizontalAlignment.CENTER;
+
+    /**
+     * 鑷畾涔夋暟鎹鐞嗗櫒
+     */
+    public Class<?> handler() default ExcelHandlerAdapter.class;
+
+    /**
+     * 鑷畾涔夋暟鎹鐞嗗櫒鍙傛暟
+     */
+    public String[] args() default {};
+
+    /**
+     * 瀛楁绫诲瀷锛�0锛氬鍑哄鍏ワ紱1锛氫粎瀵煎嚭锛�2锛氫粎瀵煎叆锛�
+     */
+    Type type() default Type.ALL;
+
+    public enum Type
+    {
+        ALL(0), EXPORT(1), IMPORT(2);
+        private final int value;
+
+        Type(int value)
+        {
+            this.value = value;
+        }
+
+        public int value()
+        {
+            return this.value;
+        }
+    }
+
+    public enum ColumnType
+    {
+        NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
+        private final int value;
+
+        ColumnType(int value)
+        {
+            this.value = value;
+        }
+
+        public int value()
+        {
+            return this.value;
+        }
+    }
+}
\ No newline at end of file
diff --git a/se-common/src/main/java/com/terra/common/annotation/Excels.java b/se-common/src/main/java/com/terra/common/annotation/Excels.java
new file mode 100644
index 0000000..ea0cb6a
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/annotation/Excels.java
@@ -0,0 +1,18 @@
+package com.terra.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Excel娉ㄨВ闆�
+ * 
+ * @author ruoyi
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Excels
+{
+    Excel[] value();
+}
\ No newline at end of file
diff --git a/se-common/src/main/java/com/terra/common/constant/CacheConstants.java b/se-common/src/main/java/com/terra/common/constant/CacheConstants.java
new file mode 100644
index 0000000..57067c7
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/constant/CacheConstants.java
@@ -0,0 +1,59 @@
+package com.terra.common.constant;
+
+/**
+ * 缂撳瓨甯搁噺淇℃伅
+ * 
+ * @author ruoyi
+ */
+public class CacheConstants
+{
+    /**
+     * 缂撳瓨鏈夋晥鏈燂紝榛樿720锛堝垎閽燂級
+     */
+    public final static long EXPIRATION = 720;
+
+    /**
+     * 缂撳瓨鍒锋柊鏃堕棿锛岄粯璁�120锛堝垎閽燂級
+     */
+    public final static long REFRESH_TIME = 120;
+
+    /**
+     * 瀵嗙爜鏈�澶ч敊璇鏁�
+     */
+    public final static int PASSWORD_MAX_RETRY_COUNT = 5;
+
+    /**
+     * 瀵嗙爜閿佸畾鏃堕棿锛岄粯璁�10锛堝垎閽燂級
+     */
+    public final static long PASSWORD_LOCK_TIME = 10;
+
+    /**
+     * 鏉冮檺缂撳瓨鍓嶇紑
+     */
+    public final static String LOGIN_TOKEN_KEY = "login_tokens:";
+
+    /**
+     * 楠岃瘉鐮� redis key
+     */
+    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
+
+    /**
+     * 鍙傛暟绠$悊 cache key
+     */
+    public static final String SYS_CONFIG_KEY = "sys_config:";
+
+    /**
+     * 瀛楀吀绠$悊 cache key
+     */
+    public static final String SYS_DICT_KEY = "sys_dict:";
+
+    /**
+     * 鐧诲綍璐︽埛瀵嗙爜閿欒娆℃暟 redis key
+     */
+    public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
+
+    /**
+     * 鐧诲綍IP榛戝悕鍗� cache key
+     */
+    public static final String SYS_LOGIN_BLACKIPLIST = SYS_CONFIG_KEY + "sys.login.blackIPList";
+}
diff --git a/se-common/src/main/java/com/terra/common/constant/Constants.java b/se-common/src/main/java/com/terra/common/constant/Constants.java
new file mode 100644
index 0000000..56c1d26
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/constant/Constants.java
@@ -0,0 +1,135 @@
+package com.terra.common.constant;
+
+/**
+ * 閫氱敤甯搁噺淇℃伅
+ * 
+ * @author ruoyi
+ */
+public class Constants
+{
+    /**
+     * UTF-8 瀛楃闆�
+     */
+    public static final String UTF8 = "UTF-8";
+
+    /**
+     * GBK 瀛楃闆�
+     */
+    public static final String GBK = "GBK";
+
+    /**
+     * www涓诲煙
+     */
+    public static final String WWW = "www.";
+
+    /**
+     * RMI 杩滅▼鏂规硶璋冪敤
+     */
+    public static final String LOOKUP_RMI = "rmi:";
+
+    /**
+     * LDAP 杩滅▼鏂规硶璋冪敤
+     */
+    public static final String LOOKUP_LDAP = "ldap:";
+
+    /**
+     * LDAPS 杩滅▼鏂规硶璋冪敤
+     */
+    public static final String LOOKUP_LDAPS = "ldaps:";
+
+    /**
+     * http璇锋眰
+     */
+    public static final String HTTP = "http://";
+
+    /**
+     * https璇锋眰
+     */
+    public static final String HTTPS = "https://";
+
+    /**
+     * 鎴愬姛鏍囪
+     */
+    public static final Integer SUCCESS = 200;
+
+    /**
+     * 澶辫触鏍囪
+     */
+    public static final Integer FAIL = 500;
+
+    /**
+     * 鐧诲綍鎴愬姛鐘舵��
+     */
+    public static final String LOGIN_SUCCESS_STATUS = "0";
+
+    /**
+     * 鐧诲綍澶辫触鐘舵��
+     */
+    public static final String LOGIN_FAIL_STATUS = "1";
+
+    /**
+     * 鐧诲綍鎴愬姛
+     */
+    public static final String LOGIN_SUCCESS = "Success";
+
+    /**
+     * 娉ㄩ攢
+     */
+    public static final String LOGOUT = "Logout";
+
+    /**
+     * 娉ㄥ唽
+     */
+    public static final String REGISTER = "Register";
+
+    /**
+     * 鐧诲綍澶辫触
+     */
+    public static final String LOGIN_FAIL = "Error";
+
+    /**
+     * 褰撳墠璁板綍璧峰绱㈠紩
+     */
+    public static final String PAGE_NUM = "pageNum";
+
+    /**
+     * 姣忛〉鏄剧ず璁板綍鏁�
+     */
+    public static final String PAGE_SIZE = "pageSize";
+
+    /**
+     * 鎺掑簭鍒�
+     */
+    public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+    /**
+     * 鎺掑簭鐨勬柟鍚� "desc" 鎴栬�� "asc".
+     */
+    public static final String IS_ASC = "isAsc";
+
+    /**
+     * 楠岃瘉鐮佹湁鏁堟湡锛堝垎閽燂級
+     */
+    public static final long CAPTCHA_EXPIRATION = 2;
+
+    /**
+     * 璧勬簮鏄犲皠璺緞 鍓嶇紑
+     */
+    public static final String RESOURCE_PREFIX = "/profile";
+
+    /**
+     * 鑷姩璇嗗埆json瀵硅薄鐧藉悕鍗曢厤缃紙浠呭厑璁歌В鏋愮殑鍖呭悕锛岃寖鍥磋秺灏忚秺瀹夊叏锛�
+     */
+    public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" };
+
+    /**
+     * 瀹氭椂浠诲姟鐧藉悕鍗曢厤缃紙浠呭厑璁歌闂殑鍖呭悕锛屽鍏朵粬闇�瑕佸彲浠ヨ嚜琛屾坊鍔狅級
+     */
+    public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.job.task" };
+
+    /**
+     * 瀹氭椂浠诲姟杩濊鐨勫瓧绗�
+     */
+    public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+            "org.springframework", "org.apache", "com.terra.common.utils.file" };
+}
diff --git a/se-common/src/main/java/com/terra/common/constant/GenConstants.java b/se-common/src/main/java/com/terra/common/constant/GenConstants.java
new file mode 100644
index 0000000..12a49a2
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/constant/GenConstants.java
@@ -0,0 +1,117 @@
+package com.terra.common.constant;
+
+/**
+ * 浠g爜鐢熸垚閫氱敤甯搁噺
+ * 
+ * @author ruoyi
+ */
+public class GenConstants
+{
+    /** 鍗曡〃锛堝鍒犳敼鏌ワ級 */
+    public static final String TPL_CRUD = "crud";
+
+    /** 鏍戣〃锛堝鍒犳敼鏌ワ級 */
+    public static final String TPL_TREE = "tree";
+
+    /** 涓诲瓙琛紙澧炲垹鏀规煡锛� */
+    public static final String TPL_SUB = "sub";
+
+    /** 鏍戠紪鐮佸瓧娈� */
+    public static final String TREE_CODE = "treeCode";
+
+    /** 鏍戠埗缂栫爜瀛楁 */
+    public static final String TREE_PARENT_CODE = "treeParentCode";
+
+    /** 鏍戝悕绉板瓧娈� */
+    public static final String TREE_NAME = "treeName";
+
+    /** 涓婄骇鑿滃崟ID瀛楁 */
+    public static final String PARENT_MENU_ID = "parentMenuId";
+
+    /** 涓婄骇鑿滃崟鍚嶇О瀛楁 */
+    public static final String PARENT_MENU_NAME = "parentMenuName";
+
+    /** 鏁版嵁搴撳瓧绗︿覆绫诲瀷 */
+    public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
+
+    /** 鏁版嵁搴撴枃鏈被鍨� */
+    public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
+
+    /** 鏁版嵁搴撴椂闂寸被鍨� */
+    public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
+
+    /** 鏁版嵁搴撴暟瀛楃被鍨� */
+    public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
+            "bit", "bigint", "float", "double", "decimal" };
+
+    /** 椤甸潰涓嶉渶瑕佺紪杈戝瓧娈� */
+    public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
+
+    /** 椤甸潰涓嶉渶瑕佹樉绀虹殑鍒楄〃瀛楁 */
+    public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
+            "update_time" };
+
+    /** 椤甸潰涓嶉渶瑕佹煡璇㈠瓧娈� */
+    public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
+            "update_time", "remark" };
+
+    /** Entity鍩虹被瀛楁 */
+    public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
+
+    /** Tree鍩虹被瀛楁 */
+    public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors" };
+
+    /** 鏂囨湰妗� */
+    public static final String HTML_INPUT = "input";
+
+    /** 鏂囨湰鍩� */
+    public static final String HTML_TEXTAREA = "textarea";
+
+    /** 涓嬫媺妗� */
+    public static final String HTML_SELECT = "select";
+
+    /** 鍗曢�夋 */
+    public static final String HTML_RADIO = "radio";
+
+    /** 澶嶉�夋 */
+    public static final String HTML_CHECKBOX = "checkbox";
+
+    /** 鏃ユ湡鎺т欢 */
+    public static final String HTML_DATETIME = "datetime";
+
+    /** 鍥剧墖涓婁紶鎺т欢 */
+    public static final String HTML_IMAGE_UPLOAD = "imageUpload";
+
+    /** 鏂囦欢涓婁紶鎺т欢 */
+    public static final String HTML_FILE_UPLOAD = "fileUpload";
+
+    /** 瀵屾枃鏈帶浠� */
+    public static final String HTML_EDITOR = "editor";
+
+    /** 瀛楃涓茬被鍨� */
+    public static final String TYPE_STRING = "String";
+
+    /** 鏁村瀷 */
+    public static final String TYPE_INTEGER = "Integer";
+
+    /** 闀挎暣鍨� */
+    public static final String TYPE_LONG = "Long";
+
+    /** 娴偣鍨� */
+    public static final String TYPE_DOUBLE = "Double";
+
+    /** 楂樼簿搴﹁绠楃被鍨� */
+    public static final String TYPE_BIGDECIMAL = "BigDecimal";
+
+    /** 鏃堕棿绫诲瀷 */
+    public static final String TYPE_DATE = "Date";
+
+    /** 妯$硦鏌ヨ */
+    public static final String QUERY_LIKE = "LIKE";
+
+    /** 鐩哥瓑鏌ヨ */
+    public static final String QUERY_EQ = "EQ";
+
+    /** 闇�瑕� */
+    public static final String REQUIRE = "1";
+}
diff --git a/se-common/src/main/java/com/terra/common/constant/HttpStatus.java b/se-common/src/main/java/com/terra/common/constant/HttpStatus.java
new file mode 100644
index 0000000..ef08f7c
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/constant/HttpStatus.java
@@ -0,0 +1,94 @@
+package com.terra.common.constant;
+
+/**
+ * 杩斿洖鐘舵�佺爜
+ * 
+ * @author ruoyi
+ */
+public class HttpStatus
+{
+    /**
+     * 鎿嶄綔鎴愬姛
+     */
+    public static final int SUCCESS = 200;
+
+    /**
+     * 瀵硅薄鍒涘缓鎴愬姛
+     */
+    public static final int CREATED = 201;
+
+    /**
+     * 璇锋眰宸茬粡琚帴鍙�
+     */
+    public static final int ACCEPTED = 202;
+
+    /**
+     * 鎿嶄綔宸茬粡鎵ц鎴愬姛锛屼絾鏄病鏈夎繑鍥炴暟鎹�
+     */
+    public static final int NO_CONTENT = 204;
+
+    /**
+     * 璧勬簮宸茶绉婚櫎
+     */
+    public static final int MOVED_PERM = 301;
+
+    /**
+     * 閲嶅畾鍚�
+     */
+    public static final int SEE_OTHER = 303;
+
+    /**
+     * 璧勬簮娌℃湁琚慨鏀�
+     */
+    public static final int NOT_MODIFIED = 304;
+
+    /**
+     * 鍙傛暟鍒楄〃閿欒锛堢己灏戯紝鏍煎紡涓嶅尮閰嶏級
+     */
+    public static final int BAD_REQUEST = 400;
+
+    /**
+     * 鏈巿鏉�
+     */
+    public static final int UNAUTHORIZED = 401;
+
+    /**
+     * 璁块棶鍙楅檺锛屾巿鏉冭繃鏈�
+     */
+    public static final int FORBIDDEN = 403;
+
+    /**
+     * 璧勬簮锛屾湇鍔℃湭鎵惧埌
+     */
+    public static final int NOT_FOUND = 404;
+
+    /**
+     * 涓嶅厑璁哥殑http鏂规硶
+     */
+    public static final int BAD_METHOD = 405;
+
+    /**
+     * 璧勬簮鍐茬獊锛屾垨鑰呰祫婧愯閿�
+     */
+    public static final int CONFLICT = 409;
+
+    /**
+     * 涓嶆敮鎸佺殑鏁版嵁锛屽獟浣撶被鍨�
+     */
+    public static final int UNSUPPORTED_TYPE = 415;
+
+    /**
+     * 绯荤粺鍐呴儴閿欒
+     */
+    public static final int ERROR = 500;
+
+    /**
+     * 鎺ュ彛鏈疄鐜�
+     */
+    public static final int NOT_IMPLEMENTED = 501;
+
+    /**
+     * 绯荤粺璀﹀憡娑堟伅
+     */
+    public static final int WARN = 601;
+}
diff --git a/se-common/src/main/java/com/terra/common/constant/ScheduleConstants.java b/se-common/src/main/java/com/terra/common/constant/ScheduleConstants.java
new file mode 100644
index 0000000..25e77d7
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/constant/ScheduleConstants.java
@@ -0,0 +1,50 @@
+package com.terra.common.constant;
+
+/**
+ * 浠诲姟璋冨害閫氱敤甯搁噺
+ * 
+ * @author ruoyi
+ */
+public class ScheduleConstants
+{
+    public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
+
+    /** 鎵ц鐩爣key */
+    public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
+
+    /** 榛樿 */
+    public static final String MISFIRE_DEFAULT = "0";
+
+    /** 绔嬪嵆瑙﹀彂鎵ц */
+    public static final String MISFIRE_IGNORE_MISFIRES = "1";
+
+    /** 瑙﹀彂涓�娆℃墽琛� */
+    public static final String MISFIRE_FIRE_AND_PROCEED = "2";
+
+    /** 涓嶈Е鍙戠珛鍗虫墽琛� */
+    public static final String MISFIRE_DO_NOTHING = "3";
+
+    public enum Status
+    {
+        /**
+         * 姝e父
+         */
+        NORMAL("0"),
+        /**
+         * 鏆傚仠
+         */
+        PAUSE("1");
+
+        private String value;
+
+        private Status(String value)
+        {
+            this.value = value;
+        }
+
+        public String getValue()
+        {
+            return value;
+        }
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/constant/SecurityConstants.java b/se-common/src/main/java/com/terra/common/constant/SecurityConstants.java
new file mode 100644
index 0000000..3c73370
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/constant/SecurityConstants.java
@@ -0,0 +1,49 @@
+package com.terra.common.constant;
+
+/**
+ * 鏉冮檺鐩稿叧閫氱敤甯搁噺
+ * 
+ * @author ruoyi
+ */
+public class SecurityConstants
+{
+    /**
+     * 鐢ㄦ埛ID瀛楁
+     */
+    public static final String DETAILS_USER_ID = "user_id";
+
+    /**
+     * 鐢ㄦ埛鍚嶅瓧娈�
+     */
+    public static final String DETAILS_USERNAME = "username";
+
+    /**
+     * 鎺堟潈淇℃伅瀛楁
+     */
+    public static final String AUTHORIZATION_HEADER = "Authorization";
+
+    /**
+     * 璇锋眰鏉ユ簮
+     */
+    public static final String FROM_SOURCE = "from-source";
+
+    /**
+     * 鍐呴儴璇锋眰
+     */
+    public static final String INNER = "inner";
+
+    /**
+     * 鐢ㄦ埛鏍囪瘑
+     */
+    public static final String USER_KEY = "user_key";
+
+    /**
+     * 鐧诲綍鐢ㄦ埛
+     */
+    public static final String LOGIN_USER = "login_user";
+
+    /**
+     * 瑙掕壊鏉冮檺
+     */
+    public static final String ROLE_PERMISSION = "role_permission";
+}
diff --git a/se-common/src/main/java/com/terra/common/constant/ServiceNameConstants.java b/se-common/src/main/java/com/terra/common/constant/ServiceNameConstants.java
new file mode 100644
index 0000000..d4e61f8
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/constant/ServiceNameConstants.java
@@ -0,0 +1,24 @@
+package com.terra.common.constant;
+
+/**
+ * 鏈嶅姟鍚嶇О
+ * 
+ * @author ruoyi
+ */
+public class ServiceNameConstants
+{
+    /**
+     * 璁よ瘉鏈嶅姟鐨剆erviceid
+     */
+    public static final String AUTH_SERVICE = "ruoyi-auth";
+
+    /**
+     * 绯荤粺妯″潡鐨剆erviceid
+     */
+    public static final String SYSTEM_SERVICE = "ruoyi-system";
+
+    /**
+     * 鏂囦欢鏈嶅姟鐨剆erviceid
+     */
+    public static final String FILE_SERVICE = "ruoyi-file";
+}
diff --git a/se-common/src/main/java/com/terra/common/constant/TokenConstants.java b/se-common/src/main/java/com/terra/common/constant/TokenConstants.java
new file mode 100644
index 0000000..9a8063d
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/constant/TokenConstants.java
@@ -0,0 +1,20 @@
+package com.terra.common.constant;
+
+/**
+ * Token鐨凨ey甯搁噺
+ * 
+ * @author ruoyi
+ */
+public class TokenConstants
+{
+    /**
+     * 浠ょ墝鍓嶇紑
+     */
+    public static final String PREFIX = "Bearer ";
+
+    /**
+     * 浠ょ墝绉橀挜
+     */
+    public final static String SECRET = "abcdefghijklmnopqrstuvwxyz";
+
+}
diff --git a/se-common/src/main/java/com/terra/common/constant/UserConstants.java b/se-common/src/main/java/com/terra/common/constant/UserConstants.java
new file mode 100644
index 0000000..0a0a556
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/constant/UserConstants.java
@@ -0,0 +1,88 @@
+package com.terra.common.constant;
+
+/**
+ * 鐢ㄦ埛甯搁噺淇℃伅
+ * 
+ * @author ruoyi
+ */
+public class UserConstants
+{
+    /**
+     * 骞冲彴鍐呯郴缁熺敤鎴风殑鍞竴鏍囧織
+     */
+    public static final String SYS_USER = "SYS_USER";
+
+    /** 姝e父鐘舵�� */
+    public static final String NORMAL = "0";
+
+    /** 寮傚父鐘舵�� */
+    public static final String EXCEPTION = "1";
+
+    /** 鐢ㄦ埛灏佺鐘舵�� */
+    public static final String USER_DISABLE = "1";
+
+    /** 瑙掕壊姝e父鐘舵�� */
+    public static final String ROLE_NORMAL = "0";
+
+    /** 瑙掕壊灏佺鐘舵�� */
+    public static final String ROLE_DISABLE = "1";
+
+    /** 閮ㄩ棬姝e父鐘舵�� */
+    public static final String DEPT_NORMAL = "0";
+
+    /** 閮ㄩ棬鍋滅敤鐘舵�� */
+    public static final String DEPT_DISABLE = "1";
+
+    /** 瀛楀吀姝e父鐘舵�� */
+    public static final String DICT_NORMAL = "0";
+
+    /** 鏄惁涓虹郴缁熼粯璁わ紙鏄級 */
+    public static final String YES = "Y";
+
+    /** 鏄惁鑿滃崟澶栭摼锛堟槸锛� */
+    public static final String YES_FRAME = "0";
+
+    /** 鏄惁鑿滃崟澶栭摼锛堝惁锛� */
+    public static final String NO_FRAME = "1";
+
+    /** 鑿滃崟绫诲瀷锛堢洰褰曪級 */
+    public static final String TYPE_DIR = "M";
+
+    /** 鑿滃崟绫诲瀷锛堣彍鍗曪級 */
+    public static final String TYPE_MENU = "C";
+
+    /** 鑿滃崟绫诲瀷锛堟寜閽級 */
+    public static final String TYPE_BUTTON = "F";
+
+    /** Layout缁勪欢鏍囪瘑 */
+    public final static String LAYOUT = "Layout";
+
+    /** ParentView缁勪欢鏍囪瘑 */
+    public final static String PARENT_VIEW = "ParentView";
+
+    /** InnerLink缁勪欢鏍囪瘑 */
+    public final static String INNER_LINK = "InnerLink";
+
+    /** 鏍¢獙鏄惁鍞竴鐨勮繑鍥炴爣璇� */
+    public final static boolean UNIQUE = true;
+    public final static boolean NOT_UNIQUE = false;
+
+    /**
+     * 鐢ㄦ埛鍚嶉暱搴﹂檺鍒�
+     */
+    public static final int USERNAME_MIN_LENGTH = 2;
+
+    public static final int USERNAME_MAX_LENGTH = 20;
+
+    /**
+     * 瀵嗙爜闀垮害闄愬埗
+     */
+    public static final int PASSWORD_MIN_LENGTH = 5;
+
+    public static final int PASSWORD_MAX_LENGTH = 20;
+
+    public static boolean isAdmin(Long userId)
+    {
+        return userId != null && 1L == userId;
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/context/SecurityContextHolder.java b/se-common/src/main/java/com/terra/common/context/SecurityContextHolder.java
new file mode 100644
index 0000000..c45d763
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/context/SecurityContextHolder.java
@@ -0,0 +1,98 @@
+package com.terra.common.context;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import com.alibaba.ttl.TransmittableThreadLocal;
+import com.terra.common.constant.SecurityConstants;
+import com.terra.common.text.Convert;
+import com.terra.common.utils.StringUtils;
+
+/**
+ * 鑾峰彇褰撳墠绾跨▼鍙橀噺涓殑 鐢ㄦ埛id銆佺敤鎴峰悕绉般�乀oken绛変俊鎭� 
+ * 娉ㄦ剰锛� 蹇呴』鍦ㄧ綉鍏抽�氳繃璇锋眰澶寸殑鏂规硶浼犲叆锛屽悓鏃跺湪HeaderInterceptor鎷︽埅鍣ㄨ缃�笺�� 鍚﹀垯杩欓噷鏃犳硶鑾峰彇
+ *
+ * @author ruoyi
+ */
+public class SecurityContextHolder
+{
+    private static final TransmittableThreadLocal<Map<String, Object>> THREAD_LOCAL = new TransmittableThreadLocal<>();
+
+    public static void set(String key, Object value)
+    {
+        Map<String, Object> map = getLocalMap();
+        map.put(key, value == null ? StringUtils.EMPTY : value);
+    }
+
+    public static String get(String key)
+    {
+        Map<String, Object> map = getLocalMap();
+        return Convert.toStr(map.getOrDefault(key, StringUtils.EMPTY));
+    }
+
+    public static <T> T get(String key, Class<T> clazz)
+    {
+        Map<String, Object> map = getLocalMap();
+        return StringUtils.cast(map.getOrDefault(key, null));
+    }
+
+    public static Map<String, Object> getLocalMap()
+    {
+        Map<String, Object> map = THREAD_LOCAL.get();
+        if (map == null)
+        {
+            map = new ConcurrentHashMap<String, Object>();
+            THREAD_LOCAL.set(map);
+        }
+        return map;
+    }
+
+    public static void setLocalMap(Map<String, Object> threadLocalMap)
+    {
+        THREAD_LOCAL.set(threadLocalMap);
+    }
+
+    public static Long getUserId()
+    {
+        return Convert.toLong(get(SecurityConstants.DETAILS_USER_ID), 0L);
+    }
+
+    public static void setUserId(String account)
+    {
+        set(SecurityConstants.DETAILS_USER_ID, account);
+    }
+
+    public static String getUserName()
+    {
+        return get(SecurityConstants.DETAILS_USERNAME);
+    }
+
+    public static void setUserName(String username)
+    {
+        set(SecurityConstants.DETAILS_USERNAME, username);
+    }
+
+    public static String getUserKey()
+    {
+        return get(SecurityConstants.USER_KEY);
+    }
+
+    public static void setUserKey(String userKey)
+    {
+        set(SecurityConstants.USER_KEY, userKey);
+    }
+
+    public static String getPermission()
+    {
+        return get(SecurityConstants.ROLE_PERMISSION);
+    }
+
+    public static void setPermission(String permissions)
+    {
+        set(SecurityConstants.ROLE_PERMISSION, permissions);
+    }
+
+    public static void remove()
+    {
+        THREAD_LOCAL.remove();
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/domain/R.java b/se-common/src/main/java/com/terra/common/domain/R.java
new file mode 100644
index 0000000..1103b50
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/domain/R.java
@@ -0,0 +1,115 @@
+package com.terra.common.domain;
+
+import java.io.Serializable;
+import com.terra.common.constant.Constants;
+
+/**
+ * 鍝嶅簲淇℃伅涓讳綋
+ *
+ * @author ruoyi
+ */
+public class R<T> implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鎴愬姛 */
+    public static final int SUCCESS = Constants.SUCCESS;
+
+    /** 澶辫触 */
+    public static final int FAIL = Constants.FAIL;
+
+    private int code;
+
+    private String msg;
+
+    private T data;
+
+    public static <T> R<T> ok()
+    {
+        return restResult(null, SUCCESS, null);
+    }
+
+    public static <T> R<T> ok(T data)
+    {
+        return restResult(data, SUCCESS, null);
+    }
+
+    public static <T> R<T> ok(T data, String msg)
+    {
+        return restResult(data, SUCCESS, msg);
+    }
+
+    public static <T> R<T> fail()
+    {
+        return restResult(null, FAIL, null);
+    }
+
+    public static <T> R<T> fail(String msg)
+    {
+        return restResult(null, FAIL, msg);
+    }
+
+    public static <T> R<T> fail(T data)
+    {
+        return restResult(data, FAIL, null);
+    }
+
+    public static <T> R<T> fail(T data, String msg)
+    {
+        return restResult(data, FAIL, msg);
+    }
+
+    public static <T> R<T> fail(int code, String msg)
+    {
+        return restResult(null, code, msg);
+    }
+
+    private static <T> R<T> restResult(T data, int code, String msg)
+    {
+        R<T> apiResult = new R<>();
+        apiResult.setCode(code);
+        apiResult.setData(data);
+        apiResult.setMsg(msg);
+        return apiResult;
+    }
+
+    public int getCode()
+    {
+        return code;
+    }
+
+    public void setCode(int code)
+    {
+        this.code = code;
+    }
+
+    public String getMsg()
+    {
+        return msg;
+    }
+
+    public void setMsg(String msg)
+    {
+        this.msg = msg;
+    }
+
+    public T getData()
+    {
+        return data;
+    }
+
+    public void setData(T data)
+    {
+        this.data = data;
+    }
+
+    public static <T> Boolean isError(R<T> ret)
+    {
+        return !isSuccess(ret);
+    }
+
+    public static <T> Boolean isSuccess(R<T> ret)
+    {
+        return R.SUCCESS == ret.getCode();
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/enums/UserStatus.java b/se-common/src/main/java/com/terra/common/enums/UserStatus.java
new file mode 100644
index 0000000..45d2eca
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/enums/UserStatus.java
@@ -0,0 +1,30 @@
+package com.terra.common.enums;
+
+/**
+ * 鐢ㄦ埛鐘舵��
+ * 
+ * @author ruoyi
+ */
+public enum UserStatus
+{
+    OK("0", "姝e父"), DISABLE("1", "鍋滅敤"), DELETED("2", "鍒犻櫎");
+
+    private final String code;
+    private final String info;
+
+    UserStatus(String code, String info)
+    {
+        this.code = code;
+        this.info = info;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public String getInfo()
+    {
+        return info;
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/CaptchaException.java b/se-common/src/main/java/com/terra/common/exception/CaptchaException.java
new file mode 100644
index 0000000..32be5b2
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/CaptchaException.java
@@ -0,0 +1,16 @@
+package com.terra.common.exception;
+
+/**
+ * 楠岃瘉鐮侀敊璇紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class CaptchaException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaException(String msg)
+    {
+        super(msg);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/CheckedException.java b/se-common/src/main/java/com/terra/common/exception/CheckedException.java
new file mode 100644
index 0000000..6168e8c
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/CheckedException.java
@@ -0,0 +1,31 @@
+package com.terra.common.exception;
+
+/**
+ * 妫�鏌ュ紓甯�
+ * 
+ * @author ruoyi
+ */
+public class CheckedException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CheckedException(String message)
+    {
+        super(message);
+    }
+
+    public CheckedException(Throwable cause)
+    {
+        super(cause);
+    }
+
+    public CheckedException(String message, Throwable cause)
+    {
+        super(message, cause);
+    }
+
+    public CheckedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)
+    {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/DemoModeException.java b/se-common/src/main/java/com/terra/common/exception/DemoModeException.java
new file mode 100644
index 0000000..d159e46
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/DemoModeException.java
@@ -0,0 +1,15 @@
+package com.terra.common.exception;
+
+/**
+ * 婕旂ず妯″紡寮傚父
+ * 
+ * @author ruoyi
+ */
+public class DemoModeException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public DemoModeException()
+    {
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/GlobalException.java b/se-common/src/main/java/com/terra/common/exception/GlobalException.java
new file mode 100644
index 0000000..4f554d5
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/GlobalException.java
@@ -0,0 +1,58 @@
+package com.terra.common.exception;
+
+/**
+ * 鍏ㄥ眬寮傚父
+ * 
+ * @author ruoyi
+ */
+public class GlobalException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 閿欒鎻愮ず
+     */
+    private String message;
+
+    /**
+     * 閿欒鏄庣粏锛屽唴閮ㄨ皟璇曢敊璇�
+     *
+     * 鍜� {@link CommonResult#getDetailMessage()} 涓�鑷寸殑璁捐
+     */
+    private String detailMessage;
+
+    /**
+     * 绌烘瀯閫犳柟娉曪紝閬垮厤鍙嶅簭鍒楀寲闂
+     */
+    public GlobalException()
+    {
+    }
+
+    public GlobalException(String message)
+    {
+        this.message = message;
+    }
+
+    public String getDetailMessage()
+    {
+        return detailMessage;
+    }
+
+    public GlobalException setDetailMessage(String detailMessage)
+    {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public GlobalException setMessage(String message)
+    {
+        this.message = message;
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/se-common/src/main/java/com/terra/common/exception/InnerAuthException.java b/se-common/src/main/java/com/terra/common/exception/InnerAuthException.java
new file mode 100644
index 0000000..266d124
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/InnerAuthException.java
@@ -0,0 +1,16 @@
+package com.terra.common.exception;
+
+/**
+ * 鍐呴儴璁よ瘉寮傚父
+ * 
+ * @author ruoyi
+ */
+public class InnerAuthException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public InnerAuthException(String message)
+    {
+        super(message);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/PreAuthorizeException.java b/se-common/src/main/java/com/terra/common/exception/PreAuthorizeException.java
new file mode 100644
index 0000000..e68e528
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/PreAuthorizeException.java
@@ -0,0 +1,15 @@
+package com.terra.common.exception;
+
+/**
+ * 鏉冮檺寮傚父
+ * 
+ * @author ruoyi
+ */
+public class PreAuthorizeException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public PreAuthorizeException()
+    {
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/ServiceException.java b/se-common/src/main/java/com/terra/common/exception/ServiceException.java
new file mode 100644
index 0000000..d35de2a
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/ServiceException.java
@@ -0,0 +1,74 @@
+package com.terra.common.exception;
+
+/**
+ * 涓氬姟寮傚父
+ * 
+ * @author ruoyi
+ */
+public final class ServiceException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 閿欒鐮�
+     */
+    private Integer code;
+
+    /**
+     * 閿欒鎻愮ず
+     */
+    private String message;
+
+    /**
+     * 閿欒鏄庣粏锛屽唴閮ㄨ皟璇曢敊璇�
+     *
+     * 鍜� {@link CommonResult#getDetailMessage()} 涓�鑷寸殑璁捐
+     */
+    private String detailMessage;
+
+    /**
+     * 绌烘瀯閫犳柟娉曪紝閬垮厤鍙嶅簭鍒楀寲闂
+     */
+    public ServiceException()
+    {
+    }
+
+    public ServiceException(String message)
+    {
+        this.message = message;
+    }
+
+    public ServiceException(String message, Integer code)
+    {
+        this.message = message;
+        this.code = code;
+    }
+
+    public String getDetailMessage()
+    {
+        return detailMessage;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public ServiceException setMessage(String message)
+    {
+        this.message = message;
+        return this;
+    }
+
+    public ServiceException setDetailMessage(String detailMessage)
+    {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/se-common/src/main/java/com/terra/common/exception/UtilException.java b/se-common/src/main/java/com/terra/common/exception/UtilException.java
new file mode 100644
index 0000000..80330a8
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/UtilException.java
@@ -0,0 +1,26 @@
+package com.terra.common.exception;
+
+/**
+ * 宸ュ叿绫诲紓甯�
+ * 
+ * @author ruoyi
+ */
+public class UtilException extends RuntimeException
+{
+    private static final long serialVersionUID = 8247610319171014183L;
+
+    public UtilException(Throwable e)
+    {
+        super(e.getMessage(), e);
+    }
+
+    public UtilException(String message)
+    {
+        super(message);
+    }
+
+    public UtilException(String message, Throwable throwable)
+    {
+        super(message, throwable);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/auth/NotLoginException.java b/se-common/src/main/java/com/terra/common/exception/auth/NotLoginException.java
new file mode 100644
index 0000000..7d842c8
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/auth/NotLoginException.java
@@ -0,0 +1,16 @@
+package com.terra.common.exception.auth;
+
+/**
+ * 鏈兘閫氳繃鐨勭櫥褰曡璇佸紓甯�
+ * 
+ * @author ruoyi
+ */
+public class NotLoginException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public NotLoginException(String message)
+    {
+        super(message);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/auth/NotPermissionException.java b/se-common/src/main/java/com/terra/common/exception/auth/NotPermissionException.java
new file mode 100644
index 0000000..8b05533
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/auth/NotPermissionException.java
@@ -0,0 +1,23 @@
+package com.terra.common.exception.auth;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 鏈兘閫氳繃鐨勬潈闄愯璇佸紓甯�
+ * 
+ * @author ruoyi
+ */
+public class NotPermissionException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public NotPermissionException(String permission)
+    {
+        super(permission);
+    }
+
+    public NotPermissionException(String[] permissions)
+    {
+        super(StringUtils.join(permissions, ","));
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/auth/NotRoleException.java b/se-common/src/main/java/com/terra/common/exception/auth/NotRoleException.java
new file mode 100644
index 0000000..64f03fe
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/auth/NotRoleException.java
@@ -0,0 +1,23 @@
+package com.terra.common.exception.auth;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 鏈兘閫氳繃鐨勮鑹茶璇佸紓甯�
+ * 
+ * @author ruoyi
+ */
+public class NotRoleException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public NotRoleException(String role)
+    {
+        super(role);
+    }
+
+    public NotRoleException(String[] roles)
+    {
+        super(StringUtils.join(roles, ","));
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/base/BaseException.java b/se-common/src/main/java/com/terra/common/exception/base/BaseException.java
new file mode 100644
index 0000000..820b5c8
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/base/BaseException.java
@@ -0,0 +1,79 @@
+package com.terra.common.exception.base;
+
+/**
+ * 鍩虹寮傚父
+ * 
+ * @author ruoyi
+ */
+public class BaseException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鎵�灞炴ā鍧�
+     */
+    private String module;
+
+    /**
+     * 閿欒鐮�
+     */
+    private String code;
+
+    /**
+     * 閿欒鐮佸搴旂殑鍙傛暟
+     */
+    private Object[] args;
+
+    /**
+     * 閿欒娑堟伅
+     */
+    private String defaultMessage;
+
+    public BaseException(String module, String code, Object[] args, String defaultMessage)
+    {
+        this.module = module;
+        this.code = code;
+        this.args = args;
+        this.defaultMessage = defaultMessage;
+    }
+
+    public BaseException(String module, String code, Object[] args)
+    {
+        this(module, code, args, null);
+    }
+
+    public BaseException(String module, String defaultMessage)
+    {
+        this(module, null, null, defaultMessage);
+    }
+
+    public BaseException(String code, Object[] args)
+    {
+        this(null, code, args, null);
+    }
+
+    public BaseException(String defaultMessage)
+    {
+        this(null, null, null, defaultMessage);
+    }
+
+    public String getModule()
+    {
+        return module;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public Object[] getArgs()
+    {
+        return args;
+    }
+
+    public String getDefaultMessage()
+    {
+        return defaultMessage;
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/file/FileException.java b/se-common/src/main/java/com/terra/common/exception/file/FileException.java
new file mode 100644
index 0000000..bfb3dca
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/file/FileException.java
@@ -0,0 +1,19 @@
+package com.terra.common.exception.file;
+
+import com.terra.common.exception.base.BaseException;
+
+/**
+ * 鏂囦欢淇℃伅寮傚父绫�
+ * 
+ * @author ruoyi
+ */
+public class FileException extends BaseException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileException(String code, Object[] args, String msg)
+    {
+        super("file", code, args, msg);
+    }
+
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/file/FileNameLengthLimitExceededException.java b/se-common/src/main/java/com/terra/common/exception/file/FileNameLengthLimitExceededException.java
new file mode 100644
index 0000000..d044180
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/file/FileNameLengthLimitExceededException.java
@@ -0,0 +1,16 @@
+package com.terra.common.exception.file;
+
+/**
+ * 鏂囦欢鍚嶇О瓒呴暱闄愬埗寮傚父绫�
+ * 
+ * @author ruoyi
+ */
+public class FileNameLengthLimitExceededException extends FileException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileNameLengthLimitExceededException(int defaultFileNameLength)
+    {
+        super("upload.filename.exceed.length", new Object[] { defaultFileNameLength }, "the filename is too long");
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/file/FileSizeLimitExceededException.java b/se-common/src/main/java/com/terra/common/exception/file/FileSizeLimitExceededException.java
new file mode 100644
index 0000000..a5436a2
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/file/FileSizeLimitExceededException.java
@@ -0,0 +1,16 @@
+package com.terra.common.exception.file;
+
+/**
+ * 鏂囦欢鍚嶅ぇ灏忛檺鍒跺紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class FileSizeLimitExceededException extends FileException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileSizeLimitExceededException(long defaultMaxSize)
+    {
+        super("upload.exceed.maxSize", new Object[] { defaultMaxSize }, "the filesize is too large");
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/file/FileUploadException.java b/se-common/src/main/java/com/terra/common/exception/file/FileUploadException.java
new file mode 100644
index 0000000..654d93f
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/file/FileUploadException.java
@@ -0,0 +1,61 @@
+package com.terra.common.exception.file;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * 鏂囦欢涓婁紶寮傚父绫�
+ * 
+ * @author ruoyi
+ */
+public class FileUploadException extends Exception
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private final Throwable cause;
+
+    public FileUploadException()
+    {
+        this(null, null);
+    }
+
+    public FileUploadException(final String msg)
+    {
+        this(msg, null);
+    }
+
+    public FileUploadException(String msg, Throwable cause)
+    {
+        super(msg);
+        this.cause = cause;
+    }
+
+    @Override
+    public void printStackTrace(PrintStream stream)
+    {
+        super.printStackTrace(stream);
+        if (cause != null)
+        {
+            stream.println("Caused by:");
+            cause.printStackTrace(stream);
+        }
+    }
+
+    @Override
+    public void printStackTrace(PrintWriter writer)
+    {
+        super.printStackTrace(writer);
+        if (cause != null)
+        {
+            writer.println("Caused by:");
+            cause.printStackTrace(writer);
+        }
+    }
+
+    @Override
+    public Throwable getCause()
+    {
+        return cause;
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/file/InvalidExtensionException.java b/se-common/src/main/java/com/terra/common/exception/file/InvalidExtensionException.java
new file mode 100644
index 0000000..11f7d79
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/file/InvalidExtensionException.java
@@ -0,0 +1,80 @@
+package com.terra.common.exception.file;
+
+import java.util.Arrays;
+
+/**
+ * 鏂囦欢涓婁紶 璇紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class InvalidExtensionException extends FileUploadException
+{
+    private static final long serialVersionUID = 1L;
+
+    private String[] allowedExtension;
+    private String extension;
+    private String filename;
+
+    public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
+    {
+        super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
+        this.allowedExtension = allowedExtension;
+        this.extension = extension;
+        this.filename = filename;
+    }
+
+    public String[] getAllowedExtension()
+    {
+        return allowedExtension;
+    }
+
+    public String getExtension()
+    {
+        return extension;
+    }
+
+    public String getFilename()
+    {
+        return filename;
+    }
+
+    public static class InvalidImageExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidFlashExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidMediaExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+    
+    public static class InvalidVideoExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/job/TaskException.java b/se-common/src/main/java/com/terra/common/exception/job/TaskException.java
new file mode 100644
index 0000000..e942c2e
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/job/TaskException.java
@@ -0,0 +1,34 @@
+package com.terra.common.exception.job;
+
+/**
+ * 璁″垝绛栫暐寮傚父
+ * 
+ * @author ruoyi
+ */
+public class TaskException extends Exception
+{
+    private static final long serialVersionUID = 1L;
+
+    private Code code;
+
+    public TaskException(String msg, Code code)
+    {
+        this(msg, code, null);
+    }
+
+    public TaskException(String msg, Code code, Exception nestedEx)
+    {
+        super(msg, nestedEx);
+        this.code = code;
+    }
+
+    public Code getCode()
+    {
+        return code;
+    }
+
+    public enum Code
+    {
+        TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
+    }
+}
\ No newline at end of file
diff --git a/se-common/src/main/java/com/terra/common/exception/user/CaptchaExpireException.java b/se-common/src/main/java/com/terra/common/exception/user/CaptchaExpireException.java
new file mode 100644
index 0000000..3191bf4
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/user/CaptchaExpireException.java
@@ -0,0 +1,16 @@
+package com.terra.common.exception.user;
+
+/**
+ * 楠岃瘉鐮佸け鏁堝紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class CaptchaExpireException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaExpireException()
+    {
+        super("user.jcaptcha.expire", null);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/user/UserException.java b/se-common/src/main/java/com/terra/common/exception/user/UserException.java
new file mode 100644
index 0000000..fd3d0be
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/user/UserException.java
@@ -0,0 +1,18 @@
+package com.terra.common.exception.user;
+
+import com.terra.common.exception.base.BaseException;
+
+/**
+ * 鐢ㄦ埛淇℃伅寮傚父绫�
+ * 
+ * @author ruoyi
+ */
+public class UserException extends BaseException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserException(String code, Object[] args)
+    {
+        super("user", code, args, null);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/exception/user/UserPasswordNotMatchException.java b/se-common/src/main/java/com/terra/common/exception/user/UserPasswordNotMatchException.java
new file mode 100644
index 0000000..aceb3eb
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/exception/user/UserPasswordNotMatchException.java
@@ -0,0 +1,16 @@
+package com.terra.common.exception.user;
+
+/**
+ * 鐢ㄦ埛瀵嗙爜涓嶆纭垨涓嶇鍚堣鑼冨紓甯哥被
+ * 
+ * @author ruoyi
+ */
+public class UserPasswordNotMatchException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordNotMatchException()
+    {
+        super("user.password.not.match", null);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/text/CharsetKit.java b/se-common/src/main/java/com/terra/common/text/CharsetKit.java
new file mode 100644
index 0000000..0396b6f
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/text/CharsetKit.java
@@ -0,0 +1,86 @@
+package com.terra.common.text;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import com.terra.common.utils.StringUtils;
+
+/**
+ * 瀛楃闆嗗伐鍏风被
+ * 
+ * @author ruoyi
+ */
+public class CharsetKit
+{
+    /** ISO-8859-1 */
+    public static final String ISO_8859_1 = "ISO-8859-1";
+    /** UTF-8 */
+    public static final String UTF_8 = "UTF-8";
+    /** GBK */
+    public static final String GBK = "GBK";
+
+    /** ISO-8859-1 */
+    public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
+    /** UTF-8 */
+    public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+    /** GBK */
+    public static final Charset CHARSET_GBK = Charset.forName(GBK);
+
+    /**
+     * 杞崲涓篊harset瀵硅薄
+     * 
+     * @param charset 瀛楃闆嗭紝涓虹┖鍒欒繑鍥為粯璁ゅ瓧绗﹂泦
+     * @return Charset
+     */
+    public static Charset charset(String charset)
+    {
+        return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+    }
+
+    /**
+     * 杞崲瀛楃涓茬殑瀛楃闆嗙紪鐮�
+     * 
+     * @param source 瀛楃涓�
+     * @param srcCharset 婧愬瓧绗﹂泦锛岄粯璁SO-8859-1
+     * @param destCharset 鐩爣瀛楃闆嗭紝榛樿UTF-8
+     * @return 杞崲鍚庣殑瀛楃闆�
+     */
+    public static String convert(String source, String srcCharset, String destCharset)
+    {
+        return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
+    }
+
+    /**
+     * 杞崲瀛楃涓茬殑瀛楃闆嗙紪鐮�
+     * 
+     * @param source 瀛楃涓�
+     * @param srcCharset 婧愬瓧绗﹂泦锛岄粯璁SO-8859-1
+     * @param destCharset 鐩爣瀛楃闆嗭紝榛樿UTF-8
+     * @return 杞崲鍚庣殑瀛楃闆�
+     */
+    public static String convert(String source, Charset srcCharset, Charset destCharset)
+    {
+        if (null == srcCharset)
+        {
+            srcCharset = StandardCharsets.ISO_8859_1;
+        }
+
+        if (null == destCharset)
+        {
+            destCharset = StandardCharsets.UTF_8;
+        }
+
+        if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
+        {
+            return source;
+        }
+        return new String(source.getBytes(srcCharset), destCharset);
+    }
+
+    /**
+     * @return 绯荤粺瀛楃闆嗙紪鐮�
+     */
+    public static String systemCharset()
+    {
+        return Charset.defaultCharset().name();
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/text/Convert.java b/se-common/src/main/java/com/terra/common/text/Convert.java
new file mode 100644
index 0000000..f6f77ec
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/text/Convert.java
@@ -0,0 +1,1018 @@
+package com.terra.common.text;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.Set;
+import com.terra.common.utils.StringUtils;
+
+/**
+ * 绫诲瀷杞崲鍣�
+ * 
+ * @author ruoyi
+ */
+public class Convert
+{
+    /**
+     * 杞崲涓哄瓧绗︿覆<br>
+     * 濡傛灉缁欏畾鐨勫�间负null锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static String toStr(Object value, String defaultValue)
+    {
+        if (null == value)
+        {
+            return defaultValue;
+        }
+        if (value instanceof String)
+        {
+            return (String) value;
+        }
+        return value.toString();
+    }
+
+    /**
+     * 杞崲涓哄瓧绗︿覆<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static String toStr(Object value)
+    {
+        return toStr(value, null);
+    }
+
+    /**
+     * 杞崲涓哄瓧绗�<br>
+     * 濡傛灉缁欏畾鐨勫�间负null锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Character toChar(Object value, Character defaultValue)
+    {
+        if (null == value)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Character)
+        {
+            return (Character) value;
+        }
+
+        final String valueStr = toStr(value, null);
+        return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
+    }
+
+    /**
+     * 杞崲涓哄瓧绗�<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Character toChar(Object value)
+    {
+        return toChar(value, null);
+    }
+
+    /**
+     * 杞崲涓篵yte<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Byte toByte(Object value, Byte defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Byte)
+        {
+            return (Byte) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).byteValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Byte.parseByte(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篵yte<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Byte toByte(Object value)
+    {
+        return toByte(value, null);
+    }
+
+    /**
+     * 杞崲涓篠hort<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Short toShort(Object value, Short defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Short)
+        {
+            return (Short) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).shortValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Short.parseShort(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篠hort<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Short toShort(Object value)
+    {
+        return toShort(value, null);
+    }
+
+    /**
+     * 杞崲涓篘umber<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Number toNumber(Object value, Number defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Number)
+        {
+            return (Number) value;
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return NumberFormat.getInstance().parse(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篘umber<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Number toNumber(Object value)
+    {
+        return toNumber(value, null);
+    }
+
+    /**
+     * 杞崲涓篿nt<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Integer toInt(Object value, Integer defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Integer)
+        {
+            return (Integer) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).intValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Integer.parseInt(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篿nt<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Integer toInt(Object value)
+    {
+        return toInt(value, null);
+    }
+
+    /**
+     * 杞崲涓篒nteger鏁扮粍<br>
+     * 
+     * @param str 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Integer[] toIntArray(String str)
+    {
+        return toIntArray(",", str);
+    }
+
+    /**
+     * 杞崲涓篖ong鏁扮粍<br>
+     * 
+     * @param str 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Long[] toLongArray(String str)
+    {
+        return toLongArray(",", str);
+    }
+
+    /**
+     * 杞崲涓篒nteger鏁扮粍<br>
+     * 
+     * @param split 鍒嗛殧绗�
+     * @param str 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Integer[] toIntArray(String split, String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new Integer[] {};
+        }
+        String[] arr = str.split(split);
+        final Integer[] ints = new Integer[arr.length];
+        for (int i = 0; i < arr.length; i++)
+        {
+            final Integer v = toInt(arr[i], 0);
+            ints[i] = v;
+        }
+        return ints;
+    }
+
+    /**
+     * 杞崲涓篖ong鏁扮粍<br>
+     * 
+     * @param split 鍒嗛殧绗�
+     * @param str 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Long[] toLongArray(String split, String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new Long[] {};
+        }
+        String[] arr = str.split(split);
+        final Long[] longs = new Long[arr.length];
+        for (int i = 0; i < arr.length; i++)
+        {
+            final Long v = toLong(arr[i], null);
+            longs[i] = v;
+        }
+        return longs;
+    }
+
+    /**
+     * 杞崲涓篠tring鏁扮粍<br>
+     * 
+     * @param str 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static String[] toStrArray(String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new String[] {};
+        }
+        return toStrArray(",", str);
+    }
+
+    /**
+     * 杞崲涓篠tring鏁扮粍<br>
+     * 
+     * @param split 鍒嗛殧绗�
+     * @param str 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static String[] toStrArray(String split, String str)
+    {
+        return str.split(split);
+    }
+
+    /**
+     * 杞崲涓簂ong<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Long toLong(Object value, Long defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Long)
+        {
+            return (Long) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).longValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            // 鏀寔绉戝璁℃暟娉�
+            return new BigDecimal(valueStr.trim()).longValue();
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓簂ong<br>
+     * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Long toLong(Object value)
+    {
+        return toLong(value, null);
+    }
+
+    /**
+     * 杞崲涓篸ouble<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Double toDouble(Object value, Double defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Double)
+        {
+            return (Double) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).doubleValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            // 鏀寔绉戝璁℃暟娉�
+            return new BigDecimal(valueStr.trim()).doubleValue();
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篸ouble<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Double toDouble(Object value)
+    {
+        return toDouble(value, null);
+    }
+
+    /**
+     * 杞崲涓篎loat<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Float toFloat(Object value, Float defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Float)
+        {
+            return (Float) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).floatValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Float.parseFloat(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篎loat<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Float toFloat(Object value)
+    {
+        return toFloat(value, null);
+    }
+
+    /**
+     * 杞崲涓篵oolean<br>
+     * String鏀寔鐨勫�间负锛歵rue銆乫alse銆亂es銆乷k銆乶o銆�1銆�0銆佹槸銆佸惁, 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     *
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static Boolean toBool(Object value, Boolean defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Boolean)
+        {
+            return (Boolean) value;
+        }
+        String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        valueStr = valueStr.trim().toLowerCase();
+        switch (valueStr)
+        {
+            case "true":
+            case "yes":
+            case "ok":
+            case "1":
+            case "鏄�":
+                return true;
+            case "false":
+            case "no":
+            case "0":
+            case "鍚�":
+                return false;
+            default:
+                return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篵oolean<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static Boolean toBool(Object value)
+    {
+        return toBool(value, null);
+    }
+
+    /**
+     * 杞崲涓篍num瀵硅薄<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 
+     * @param clazz Enum鐨凜lass
+     * @param value 鍊�
+     * @param defaultValue 榛樿鍊�
+     * @return Enum
+     */
+    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (clazz.isAssignableFrom(value.getClass()))
+        {
+            @SuppressWarnings("unchecked")
+            E myE = (E) value;
+            return myE;
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Enum.valueOf(clazz, valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓篍num瀵硅薄<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 
+     * @param clazz Enum鐨凜lass
+     * @param value 鍊�
+     * @return Enum
+     */
+    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value)
+    {
+        return toEnum(clazz, value, null);
+    }
+
+    /**
+     * 杞崲涓築igInteger<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static BigInteger toBigInteger(Object value, BigInteger defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof BigInteger)
+        {
+            return (BigInteger) value;
+        }
+        if (value instanceof Long)
+        {
+            return BigInteger.valueOf((Long) value);
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return new BigInteger(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓築igInteger<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static BigInteger toBigInteger(Object value)
+    {
+        return toBigInteger(value, null);
+    }
+
+    /**
+     * 杞崲涓築igDecimal<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+     * @return 缁撴灉
+     */
+    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof BigDecimal)
+        {
+            return (BigDecimal) value;
+        }
+        if (value instanceof Long)
+        {
+            return new BigDecimal((Long) value);
+        }
+        if (value instanceof Double)
+        {
+            return BigDecimal.valueOf((Double) value);
+        }
+        if (value instanceof Integer)
+        {
+            return new BigDecimal((Integer) value);
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return new BigDecimal(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 杞崲涓築igDecimal<br>
+     * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+     * 杞崲澶辫触涓嶄細鎶ラ敊
+     * 
+     * @param value 琚浆鎹㈢殑鍊�
+     * @return 缁撴灉
+     */
+    public static BigDecimal toBigDecimal(Object value)
+    {
+        return toBigDecimal(value, null);
+    }
+
+    /**
+     * 灏嗗璞¤浆涓哄瓧绗︿覆<br>
+     * 1銆丅yte鏁扮粍鍜孊yteBuffer浼氳杞崲涓哄搴斿瓧绗︿覆鐨勬暟缁� 2銆佸璞℃暟缁勪細璋冪敤Arrays.toString鏂规硶
+     * 
+     * @param obj 瀵硅薄
+     * @return 瀛楃涓�
+     */
+    public static String utf8Str(Object obj)
+    {
+        return str(obj, CharsetKit.CHARSET_UTF_8);
+    }
+
+    /**
+     * 灏嗗璞¤浆涓哄瓧绗︿覆<br>
+     * 1銆丅yte鏁扮粍鍜孊yteBuffer浼氳杞崲涓哄搴斿瓧绗︿覆鐨勬暟缁� 2銆佸璞℃暟缁勪細璋冪敤Arrays.toString鏂规硶
+     * 
+     * @param obj 瀵硅薄
+     * @param charsetName 瀛楃闆�
+     * @return 瀛楃涓�
+     */
+    public static String str(Object obj, String charsetName)
+    {
+        return str(obj, Charset.forName(charsetName));
+    }
+
+    /**
+     * 灏嗗璞¤浆涓哄瓧绗︿覆<br>
+     * 1銆丅yte鏁扮粍鍜孊yteBuffer浼氳杞崲涓哄搴斿瓧绗︿覆鐨勬暟缁� 2銆佸璞℃暟缁勪細璋冪敤Arrays.toString鏂规硶
+     * 
+     * @param obj 瀵硅薄
+     * @param charset 瀛楃闆�
+     * @return 瀛楃涓�
+     */
+    public static String str(Object obj, Charset charset)
+    {
+        if (null == obj)
+        {
+            return null;
+        }
+
+        if (obj instanceof String)
+        {
+            return (String) obj;
+        }
+        else if (obj instanceof byte[] || obj instanceof Byte[])
+        {
+            if (obj instanceof byte[])
+            {
+                return str((byte[]) obj, charset);
+            }
+            else
+            {
+                Byte[] bytes = (Byte[]) obj;
+                int length = bytes.length;
+                byte[] dest = new byte[length];
+                for (int i = 0; i < length; i++)
+                {
+                    dest[i] = bytes[i];
+                }
+                return str(dest, charset);
+            }
+        }
+        else if (obj instanceof ByteBuffer)
+        {
+            return str((ByteBuffer) obj, charset);
+        }
+        return obj.toString();
+    }
+
+    /**
+     * 灏哹yte鏁扮粍杞负瀛楃涓�
+     * 
+     * @param bytes byte鏁扮粍
+     * @param charset 瀛楃闆�
+     * @return 瀛楃涓�
+     */
+    public static String str(byte[] bytes, String charset)
+    {
+        return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+    }
+
+    /**
+     * 瑙g爜瀛楄妭鐮�
+     * 
+     * @param data 瀛楃涓�
+     * @param charset 瀛楃闆嗭紝濡傛灉姝ゅ瓧娈典负绌猴紝鍒欒В鐮佺殑缁撴灉鍙栧喅浜庡钩鍙�
+     * @return 瑙g爜鍚庣殑瀛楃涓�
+     */
+    public static String str(byte[] data, Charset charset)
+    {
+        if (data == null)
+        {
+            return null;
+        }
+
+        if (null == charset)
+        {
+            return new String(data);
+        }
+        return new String(data, charset);
+    }
+
+    /**
+     * 灏嗙紪鐮佺殑byteBuffer鏁版嵁杞崲涓哄瓧绗︿覆
+     * 
+     * @param data 鏁版嵁
+     * @param charset 瀛楃闆嗭紝濡傛灉涓虹┖浣跨敤褰撳墠绯荤粺瀛楃闆�
+     * @return 瀛楃涓�
+     */
+    public static String str(ByteBuffer data, String charset)
+    {
+        if (data == null)
+        {
+            return null;
+        }
+
+        return str(data, Charset.forName(charset));
+    }
+
+    /**
+     * 灏嗙紪鐮佺殑byteBuffer鏁版嵁杞崲涓哄瓧绗︿覆
+     * 
+     * @param data 鏁版嵁
+     * @param charset 瀛楃闆嗭紝濡傛灉涓虹┖浣跨敤褰撳墠绯荤粺瀛楃闆�
+     * @return 瀛楃涓�
+     */
+    public static String str(ByteBuffer data, Charset charset)
+    {
+        if (null == charset)
+        {
+            charset = Charset.defaultCharset();
+        }
+        return charset.decode(data).toString();
+    }
+
+    // ----------------------------------------------------------------------- 鍏ㄨ鍗婅杞崲
+    /**
+     * 鍗婅杞叏瑙�
+     * 
+     * @param input String.
+     * @return 鍏ㄨ瀛楃涓�.
+     */
+    public static String toSBC(String input)
+    {
+        return toSBC(input, null);
+    }
+
+    /**
+     * 鍗婅杞叏瑙�
+     * 
+     * @param input String
+     * @param notConvertSet 涓嶆浛鎹㈢殑瀛楃闆嗗悎
+     * @return 鍏ㄨ瀛楃涓�.
+     */
+    public static String toSBC(String input, Set<Character> notConvertSet)
+    {
+        char[] c = input.toCharArray();
+        for (int i = 0; i < c.length; i++)
+        {
+            if (null != notConvertSet && notConvertSet.contains(c[i]))
+            {
+                // 璺宠繃涓嶆浛鎹㈢殑瀛楃
+                continue;
+            }
+
+            if (c[i] == ' ')
+            {
+                c[i] = '\u3000';
+            }
+            else if (c[i] < '\177')
+            {
+                c[i] = (char) (c[i] + 65248);
+
+            }
+        }
+        return new String(c);
+    }
+
+    /**
+     * 鍏ㄨ杞崐瑙�
+     * 
+     * @param input String.
+     * @return 鍗婅瀛楃涓�
+     */
+    public static String toDBC(String input)
+    {
+        return toDBC(input, null);
+    }
+
+    /**
+     * 鏇挎崲鍏ㄨ涓哄崐瑙�
+     * 
+     * @param text 鏂囨湰
+     * @param notConvertSet 涓嶆浛鎹㈢殑瀛楃闆嗗悎
+     * @return 鏇挎崲鍚庣殑瀛楃
+     */
+    public static String toDBC(String text, Set<Character> notConvertSet)
+    {
+        char[] c = text.toCharArray();
+        for (int i = 0; i < c.length; i++)
+        {
+            if (null != notConvertSet && notConvertSet.contains(c[i]))
+            {
+                // 璺宠繃涓嶆浛鎹㈢殑瀛楃
+                continue;
+            }
+
+            if (c[i] == '\u3000')
+            {
+                c[i] = ' ';
+            }
+            else if (c[i] > '\uFF00' && c[i] < '\uFF5F')
+            {
+                c[i] = (char) (c[i] - 65248);
+            }
+        }
+        return new String(c);
+    }
+
+    /**
+     * 鏁板瓧閲戦澶у啓杞崲 鍏堝啓涓畬鏁寸殑鐒跺悗灏嗗闆舵嬀鏇挎崲鎴愰浂
+     * 
+     * @param n 鏁板瓧
+     * @return 涓枃澶у啓鏁板瓧
+     */
+    public static String digitUppercase(double n)
+    {
+        String[] fraction = { "瑙�", "鍒�" };
+        String[] digit = { "闆�", "澹�", "璐�", "鍙�", "鑲�", "浼�", "闄�", "鏌�", "鎹�", "鐜�" };
+        String[][] unit = { { "鍏�", "涓�", "浜�" }, { "", "鎷�", "浣�", "浠�" } };
+
+        String head = n < 0 ? "璐�" : "";
+        n = Math.abs(n);
+
+        String s = "";
+        for (int i = 0; i < fraction.length; i++)
+        {
+            // 浼樺寲double璁$畻绮惧害涓㈠け闂
+            BigDecimal nNum = new BigDecimal(n);
+            BigDecimal decimal = new BigDecimal(10);
+            BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
+            double d = scale.doubleValue();
+            s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(闆�.)+", "");
+        }
+        if (s.length() < 1)
+        {
+            s = "鏁�";
+        }
+        int integerPart = (int) Math.floor(n);
+
+        for (int i = 0; i < unit[0].length && integerPart > 0; i++)
+        {
+            String p = "";
+            for (int j = 0; j < unit[1].length && n > 0; j++)
+            {
+                p = digit[integerPart % 10] + unit[1][j] + p;
+                integerPart = integerPart / 10;
+            }
+            s = p.replaceAll("(闆�.)*闆�$", "").replaceAll("^$", "闆�") + unit[0][i] + s;
+        }
+        return head + s.replaceAll("(闆�.)*闆跺厓", "鍏�").replaceFirst("(闆�.)+", "").replaceAll("(闆�.)+", "闆�").replaceAll("^鏁�$", "闆跺厓鏁�");
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/text/StrFormatter.java b/se-common/src/main/java/com/terra/common/text/StrFormatter.java
new file mode 100644
index 0000000..08ac715
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/text/StrFormatter.java
@@ -0,0 +1,92 @@
+package com.terra.common.text;
+
+import com.terra.common.utils.StringUtils;
+
+/**
+ * 瀛楃涓叉牸寮忓寲
+ * 
+ * @author ruoyi
+ */
+public class StrFormatter
+{
+    public static final String EMPTY_JSON = "{}";
+    public static final char C_BACKSLASH = '\\';
+    public static final char C_DELIM_START = '{';
+    public static final char C_DELIM_END = '}';
+
+    /**
+     * 鏍煎紡鍖栧瓧绗︿覆<br>
+     * 姝ゆ柟娉曞彧鏄畝鍗曞皢鍗犱綅绗� {} 鎸夌収椤哄簭鏇挎崲涓哄弬鏁�<br>
+     * 濡傛灉鎯宠緭鍑� {} 浣跨敤 \\杞箟 { 鍗冲彲锛屽鏋滄兂杈撳嚭 {} 涔嬪墠鐨� \ 浣跨敤鍙岃浆涔夌 \\\\ 鍗冲彲<br>
+     * 渚嬶細<br>
+     * 閫氬父浣跨敤锛歠ormat("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 杞箟{}锛� format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 杞箟\锛� format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     * 
+     * @param strPattern 瀛楃涓叉ā鏉�
+     * @param argArray 鍙傛暟鍒楄〃
+     * @return 缁撴灉
+     */
+    public static String format(final String strPattern, final Object... argArray)
+    {
+        if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
+        {
+            return strPattern;
+        }
+        final int strPatternLength = strPattern.length();
+
+        // 鍒濆鍖栧畾涔夊ソ鐨勯暱搴︿互鑾峰緱鏇村ソ鐨勬�ц兘
+        StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
+
+        int handledPosition = 0;
+        int delimIndex;// 鍗犱綅绗︽墍鍦ㄤ綅缃�
+        for (int argIndex = 0; argIndex < argArray.length; argIndex++)
+        {
+            delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
+            if (delimIndex == -1)
+            {
+                if (handledPosition == 0)
+                {
+                    return strPattern;
+                }
+                else
+                { // 瀛楃涓叉ā鏉垮墿浣欓儴鍒嗕笉鍐嶅寘鍚崰浣嶇锛屽姞鍏ュ墿浣欓儴鍒嗗悗杩斿洖缁撴灉
+                    sbuf.append(strPattern, handledPosition, strPatternLength);
+                    return sbuf.toString();
+                }
+            }
+            else
+            {
+                if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
+                {
+                    if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
+                    {
+                        // 杞箟绗︿箣鍓嶈繕鏈変竴涓浆涔夌锛屽崰浣嶇渚濇棫鏈夋晥
+                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
+                        sbuf.append(Convert.utf8Str(argArray[argIndex]));
+                        handledPosition = delimIndex + 2;
+                    }
+                    else
+                    {
+                        // 鍗犱綅绗﹁杞箟
+                        argIndex--;
+                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
+                        sbuf.append(C_DELIM_START);
+                        handledPosition = delimIndex + 1;
+                    }
+                }
+                else
+                {
+                    // 姝e父鍗犱綅绗�
+                    sbuf.append(strPattern, handledPosition, delimIndex);
+                    sbuf.append(Convert.utf8Str(argArray[argIndex]));
+                    handledPosition = delimIndex + 2;
+                }
+            }
+        }
+        // 鍔犲叆鏈�鍚庝竴涓崰浣嶇鍚庢墍鏈夌殑瀛楃
+        sbuf.append(strPattern, handledPosition, strPattern.length());
+
+        return sbuf.toString();
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/DateUtils.java b/se-common/src/main/java/com/terra/common/utils/DateUtils.java
new file mode 100644
index 0000000..da8ea47
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/DateUtils.java
@@ -0,0 +1,191 @@
+package com.terra.common.utils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Date;
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+/**
+ * 鏃堕棿宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils
+{
+    public static String YYYY = "yyyy";
+
+    public static String YYYY_MM = "yyyy-MM";
+
+    public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+    private static String[] parsePatterns = {
+            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
+            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+    /**
+     * 鑾峰彇褰撳墠Date鍨嬫棩鏈�
+     *
+     * @return Date() 褰撳墠鏃ユ湡
+     */
+    public static Date getNowDate()
+    {
+        return new Date();
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鏃ユ湡, 榛樿鏍煎紡涓簓yyy-MM-dd
+     *
+     * @return String
+     */
+    public static String getDate()
+    {
+        return dateTimeNow(YYYY_MM_DD);
+    }
+
+    public static final String getTime()
+    {
+        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static final String dateTimeNow()
+    {
+        return dateTimeNow(YYYYMMDDHHMMSS);
+    }
+
+    public static final String dateTimeNow(final String format)
+    {
+        return parseDateToStr(format, new Date());
+    }
+
+    public static final String dateTime(final Date date)
+    {
+        return parseDateToStr(YYYY_MM_DD, date);
+    }
+
+    public static final String parseDateToStr(final String format, final Date date)
+    {
+        return new SimpleDateFormat(format).format(date);
+    }
+
+    public static final Date dateTime(final String format, final String ts)
+    {
+        try
+        {
+            return new SimpleDateFormat(format).parse(ts);
+        }
+        catch (ParseException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 鏃ユ湡璺緞 鍗冲勾/鏈�/鏃� 濡�2018/08/08
+     */
+    public static final String datePath()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyy/MM/dd");
+    }
+
+    /**
+     * 鏃ユ湡璺緞 鍗冲勾/鏈�/鏃� 濡�20180808
+     */
+    public static final String dateTime()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyyMMdd");
+    }
+
+    /**
+     * 鏃ユ湡鍨嬪瓧绗︿覆杞寲涓烘棩鏈� 鏍煎紡
+     */
+    public static Date parseDate(Object str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        try
+        {
+            return parseDate(str.toString(), parsePatterns);
+        }
+        catch (ParseException e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * 鑾峰彇鏈嶅姟鍣ㄥ惎鍔ㄦ椂闂�
+     */
+    public static Date getServerStartDate()
+    {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        return new Date(time);
+    }
+
+    /**
+     * 璁$畻鐩稿樊澶╂暟
+     */
+    public static int differentDaysByMillisecond(Date date1, Date date2)
+    {
+        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
+    }
+
+    /**
+     * 璁$畻鏃堕棿宸�
+     *
+     * @param endDate 鏈�鍚庢椂闂�
+     * @param startTime 寮�濮嬫椂闂�
+     * @return 鏃堕棿宸紙澶�/灏忔椂/鍒嗛挓锛�
+     */
+    public static String timeDistance(Date endDate, Date startTime)
+    {
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+        // long ns = 1000;
+        // 鑾峰緱涓や釜鏃堕棿鐨勬绉掓椂闂村樊寮�
+        long diff = endDate.getTime() - startTime.getTime();
+        // 璁$畻宸灏戝ぉ
+        long day = diff / nd;
+        // 璁$畻宸灏戝皬鏃�
+        long hour = diff % nd / nh;
+        // 璁$畻宸灏戝垎閽�
+        long min = diff % nd % nh / nm;
+        // 璁$畻宸灏戠//杈撳嚭缁撴灉
+        // long sec = diff % nd % nh % nm / ns;
+        return day + "澶�" + hour + "灏忔椂" + min + "鍒嗛挓";
+    }
+
+    /**
+     * 澧炲姞 LocalDateTime ==> Date
+     */
+    public static Date toDate(LocalDateTime temporalAccessor)
+    {
+        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+
+    /**
+     * 澧炲姞 LocalDate ==> Date
+     */
+    public static Date toDate(LocalDate temporalAccessor)
+    {
+        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
+        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/ExceptionUtil.java b/se-common/src/main/java/com/terra/common/utils/ExceptionUtil.java
new file mode 100644
index 0000000..754a433
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/ExceptionUtil.java
@@ -0,0 +1,39 @@
+package com.terra.common.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+
+/**
+ * 閿欒淇℃伅澶勭悊绫汇��
+ *
+ * @author ruoyi
+ */
+public class ExceptionUtil
+{
+    /**
+     * 鑾峰彇exception鐨勮缁嗛敊璇俊鎭��
+     */
+    public static String getExceptionMessage(Throwable e)
+    {
+        StringWriter sw = new StringWriter();
+        e.printStackTrace(new PrintWriter(sw, true));
+        return sw.toString();
+    }
+
+    public static String getRootErrorMessage(Exception e)
+    {
+        Throwable root = ExceptionUtils.getRootCause(e);
+        root = (root == null ? e : root);
+        if (root == null)
+        {
+            return "";
+        }
+        String msg = root.getMessage();
+        if (msg == null)
+        {
+            return "null";
+        }
+        return StringUtils.defaultString(msg);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/JwtUtils.java b/se-common/src/main/java/com/terra/common/utils/JwtUtils.java
new file mode 100644
index 0000000..94cb273
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/JwtUtils.java
@@ -0,0 +1,123 @@
+package com.terra.common.utils;
+
+import java.util.Map;
+import com.terra.common.constant.SecurityConstants;
+import com.terra.common.constant.TokenConstants;
+import com.terra.common.text.Convert;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+/**
+ * Jwt宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class JwtUtils
+{
+    public static String secret = TokenConstants.SECRET;
+
+    /**
+     * 浠庢暟鎹0鏄庣敓鎴愪护鐗�
+     *
+     * @param claims 鏁版嵁澹版槑
+     * @return 浠ょ墝
+     */
+    public static String createToken(Map<String, Object> claims)
+    {
+        String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();
+        return token;
+    }
+
+    /**
+     * 浠庝护鐗屼腑鑾峰彇鏁版嵁澹版槑
+     *
+     * @param token 浠ょ墝
+     * @return 鏁版嵁澹版槑
+     */
+    public static Claims parseToken(String token)
+    {
+        return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
+    }
+
+    /**
+     * 鏍规嵁浠ょ墝鑾峰彇鐢ㄦ埛鏍囪瘑
+     * 
+     * @param token 浠ょ墝
+     * @return 鐢ㄦ埛ID
+     */
+    public static String getUserKey(String token)
+    {
+        Claims claims = parseToken(token);
+        return getValue(claims, SecurityConstants.USER_KEY);
+    }
+
+    /**
+     * 鏍规嵁浠ょ墝鑾峰彇鐢ㄦ埛鏍囪瘑
+     * 
+     * @param claims 韬唤淇℃伅
+     * @return 鐢ㄦ埛ID
+     */
+    public static String getUserKey(Claims claims)
+    {
+        return getValue(claims, SecurityConstants.USER_KEY);
+    }
+
+    /**
+     * 鏍规嵁浠ょ墝鑾峰彇鐢ㄦ埛ID
+     * 
+     * @param token 浠ょ墝
+     * @return 鐢ㄦ埛ID
+     */
+    public static String getUserId(String token)
+    {
+        Claims claims = parseToken(token);
+        return getValue(claims, SecurityConstants.DETAILS_USER_ID);
+    }
+
+    /**
+     * 鏍规嵁韬唤淇℃伅鑾峰彇鐢ㄦ埛ID
+     * 
+     * @param claims 韬唤淇℃伅
+     * @return 鐢ㄦ埛ID
+     */
+    public static String getUserId(Claims claims)
+    {
+        return getValue(claims, SecurityConstants.DETAILS_USER_ID);
+    }
+
+    /**
+     * 鏍规嵁浠ょ墝鑾峰彇鐢ㄦ埛鍚�
+     * 
+     * @param token 浠ょ墝
+     * @return 鐢ㄦ埛鍚�
+     */
+    public static String getUserName(String token)
+    {
+        Claims claims = parseToken(token);
+        return getValue(claims, SecurityConstants.DETAILS_USERNAME);
+    }
+
+    /**
+     * 鏍规嵁韬唤淇℃伅鑾峰彇鐢ㄦ埛鍚�
+     * 
+     * @param claims 韬唤淇℃伅
+     * @return 鐢ㄦ埛鍚�
+     */
+    public static String getUserName(Claims claims)
+    {
+        return getValue(claims, SecurityConstants.DETAILS_USERNAME);
+    }
+
+    /**
+     * 鏍规嵁韬唤淇℃伅鑾峰彇閿��
+     * 
+     * @param claims 韬唤淇℃伅
+     * @param key 閿�
+     * @return 鍊�
+     */
+    public static String getValue(Claims claims, String key)
+    {
+        return Convert.toStr(claims.get(key), "");
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/PageUtils.java b/se-common/src/main/java/com/terra/common/utils/PageUtils.java
new file mode 100644
index 0000000..5d10d4e
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/PageUtils.java
@@ -0,0 +1,35 @@
+package com.terra.common.utils;
+
+import com.github.pagehelper.PageHelper;
+import com.terra.common.utils.sql.SqlUtil;
+import com.terra.common.web.page.PageDomain;
+import com.terra.common.web.page.TableSupport;
+
+/**
+ * 鍒嗛〉宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class PageUtils extends PageHelper
+{
+    /**
+     * 璁剧疆璇锋眰鍒嗛〉鏁版嵁
+     */
+    public static void startPage()
+    {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+        String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+        Boolean reasonable = pageDomain.getReasonable();
+        PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
+    }
+
+    /**
+     * 娓呯悊鍒嗛〉鐨勭嚎绋嬪彉閲�
+     */
+    public static void clearPage()
+    {
+        PageHelper.clearPage();
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/ServletUtils.java b/se-common/src/main/java/com/terra/common/utils/ServletUtils.java
new file mode 100644
index 0000000..52064ab
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/ServletUtils.java
@@ -0,0 +1,333 @@
+package com.terra.common.utils;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.util.LinkedCaseInsensitiveMap;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import com.alibaba.fastjson2.JSON;
+import com.terra.common.constant.Constants;
+import com.terra.common.domain.R;
+import com.terra.common.text.Convert;
+import reactor.core.publisher.Mono;
+
+/**
+ * 瀹㈡埛绔伐鍏风被
+ * 
+ * @author ruoyi
+ */
+public class ServletUtils
+{
+    /**
+     * 鑾峰彇String鍙傛暟
+     */
+    public static String getParameter(String name)
+    {
+        return getRequest().getParameter(name);
+    }
+
+    /**
+     * 鑾峰彇String鍙傛暟
+     */
+    public static String getParameter(String name, String defaultValue)
+    {
+        return Convert.toStr(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 鑾峰彇Integer鍙傛暟
+     */
+    public static Integer getParameterToInt(String name)
+    {
+        return Convert.toInt(getRequest().getParameter(name));
+    }
+
+    /**
+     * 鑾峰彇Integer鍙傛暟
+     */
+    public static Integer getParameterToInt(String name, Integer defaultValue)
+    {
+        return Convert.toInt(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 鑾峰彇Boolean鍙傛暟
+     */
+    public static Boolean getParameterToBool(String name)
+    {
+        return Convert.toBool(getRequest().getParameter(name));
+    }
+
+    /**
+     * 鑾峰彇Boolean鍙傛暟
+     */
+    public static Boolean getParameterToBool(String name, Boolean defaultValue)
+    {
+        return Convert.toBool(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 鑾峰緱鎵�鏈夎姹傚弬鏁�
+     *
+     * @param request 璇锋眰瀵硅薄{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String[]> getParams(ServletRequest request)
+    {
+        final Map<String, String[]> map = request.getParameterMap();
+        return Collections.unmodifiableMap(map);
+    }
+
+    /**
+     * 鑾峰緱鎵�鏈夎姹傚弬鏁�
+     *
+     * @param request 璇锋眰瀵硅薄{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String> getParamMap(ServletRequest request)
+    {
+        Map<String, String> params = new HashMap<>();
+        for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
+        {
+            params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
+        }
+        return params;
+    }
+
+    /**
+     * 鑾峰彇request
+     */
+    public static HttpServletRequest getRequest()
+    {
+        try
+        {
+            return getRequestAttributes().getRequest();
+        }
+        catch (Exception e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * 鑾峰彇response
+     */
+    public static HttpServletResponse getResponse()
+    {
+        try
+        {
+            return getRequestAttributes().getResponse();
+        }
+        catch (Exception e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * 鑾峰彇session
+     */
+    public static HttpSession getSession()
+    {
+        return getRequest().getSession();
+    }
+
+    public static ServletRequestAttributes getRequestAttributes()
+    {
+        try
+        {
+            RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+            return (ServletRequestAttributes) attributes;
+        }
+        catch (Exception e)
+        {
+            return null;
+        }
+    }
+
+    public static String getHeader(HttpServletRequest request, String name)
+    {
+        String value = request.getHeader(name);
+        if (StringUtils.isEmpty(value))
+        {
+            return StringUtils.EMPTY;
+        }
+        return urlDecode(value);
+    }
+
+    public static Map<String, String> getHeaders(HttpServletRequest request)
+    {
+        Map<String, String> map = new LinkedCaseInsensitiveMap<>();
+        Enumeration<String> enumeration = request.getHeaderNames();
+        if (enumeration != null)
+        {
+            while (enumeration.hasMoreElements())
+            {
+                String key = enumeration.nextElement();
+                String value = request.getHeader(key);
+                map.put(key, value);
+            }
+        }
+        return map;
+    }
+
+    /**
+     * 灏嗗瓧绗︿覆娓叉煋鍒板鎴风
+     * 
+     * @param response 娓叉煋瀵硅薄
+     * @param string 寰呮覆鏌撶殑瀛楃涓�
+     */
+    public static void renderString(HttpServletResponse response, String string)
+    {
+        try
+        {
+            response.setStatus(200);
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(string);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 鏄惁鏄疉jax寮傛璇锋眰
+     * 
+     * @param request
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request)
+    {
+        String accept = request.getHeader("accept");
+        if (accept != null && accept.contains("application/json"))
+        {
+            return true;
+        }
+
+        String xRequestedWith = request.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
+        {
+            return true;
+        }
+
+        String uri = request.getRequestURI();
+        if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
+        {
+            return true;
+        }
+
+        String ajax = request.getParameter("__ajax");
+        return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
+    }
+
+    /**
+     * 鍐呭缂栫爜
+     * 
+     * @param str 鍐呭
+     * @return 缂栫爜鍚庣殑鍐呭
+     */
+    public static String urlEncode(String str)
+    {
+        try
+        {
+            return URLEncoder.encode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+
+    /**
+     * 鍐呭瑙g爜
+     * 
+     * @param str 鍐呭
+     * @return 瑙g爜鍚庣殑鍐呭
+     */
+    public static String urlDecode(String str)
+    {
+        try
+        {
+            return URLDecoder.decode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+
+    /**
+     * 璁剧疆webflux妯″瀷鍝嶅簲
+     *
+     * @param response ServerHttpResponse
+     * @param value 鍝嶅簲鍐呭
+     * @return Mono<Void>
+     */
+    public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, Object value)
+    {
+        return webFluxResponseWriter(response, HttpStatus.OK, value, R.FAIL);
+    }
+
+    /**
+     * 璁剧疆webflux妯″瀷鍝嶅簲
+     *
+     * @param response ServerHttpResponse
+     * @param code 鍝嶅簲鐘舵�佺爜
+     * @param value 鍝嶅簲鍐呭
+     * @return Mono<Void>
+     */
+    public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, Object value, int code)
+    {
+        return webFluxResponseWriter(response, HttpStatus.OK, value, code);
+    }
+
+    /**
+     * 璁剧疆webflux妯″瀷鍝嶅簲
+     *
+     * @param response ServerHttpResponse
+     * @param status http鐘舵�佺爜
+     * @param code 鍝嶅簲鐘舵�佺爜
+     * @param value 鍝嶅簲鍐呭
+     * @return Mono<Void>
+     */
+    public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, HttpStatus status, Object value, int code)
+    {
+        return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE, status, value, code);
+    }
+
+    /**
+     * 璁剧疆webflux妯″瀷鍝嶅簲
+     *
+     * @param response ServerHttpResponse
+     * @param contentType content-type
+     * @param status http鐘舵�佺爜
+     * @param code 鍝嶅簲鐘舵�佺爜
+     * @param value 鍝嶅簲鍐呭
+     * @return Mono<Void>
+     */
+    public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status, Object value, int code)
+    {
+        response.setStatusCode(status);
+        response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
+        R<?> result = R.fail(code, value.toString());
+        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONString(result).getBytes());
+        return response.writeWith(Mono.just(dataBuffer));
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/SpringUtils.java b/se-common/src/main/java/com/terra/common/utils/SpringUtils.java
new file mode 100644
index 0000000..295436b
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/SpringUtils.java
@@ -0,0 +1,114 @@
+package com.terra.common.utils;
+
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * spring宸ュ叿绫� 鏂逛究鍦ㄩ潪spring绠$悊鐜涓幏鍙朾ean
+ * 
+ * @author ruoyi
+ */
+@Component
+public final class SpringUtils implements BeanFactoryPostProcessor
+{
+    /** Spring搴旂敤涓婁笅鏂囩幆澧� */
+    private static ConfigurableListableBeanFactory beanFactory;
+
+    @Override
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
+    {
+        SpringUtils.beanFactory = beanFactory;
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄
+     *
+     * @param name
+     * @return Object 涓�涓互鎵�缁欏悕瀛楁敞鍐岀殑bean鐨勫疄渚�
+     * @throws org.springframework.beans.BeansException
+     *
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) throws BeansException
+    {
+        return (T) beanFactory.getBean(name);
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷涓簉equiredType鐨勫璞�
+     *
+     * @param clz
+     * @return
+     * @throws org.springframework.beans.BeansException
+     *
+     */
+    public static <T> T getBean(Class<T> clz) throws BeansException
+    {
+        T result = (T) beanFactory.getBean(clz);
+        return result;
+    }
+
+    /**
+     * 濡傛灉BeanFactory鍖呭惈涓�涓笌鎵�缁欏悕绉板尮閰嶇殑bean瀹氫箟锛屽垯杩斿洖true
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean containsBean(String name)
+    {
+        return beanFactory.containsBean(name);
+    }
+
+    /**
+     * 鍒ゆ柇浠ョ粰瀹氬悕瀛楁敞鍐岀殑bean瀹氫箟鏄竴涓猻ingleton杩樻槸涓�涓猵rototype銆� 濡傛灉涓庣粰瀹氬悕瀛楃浉搴旂殑bean瀹氫箟娌℃湁琚壘鍒帮紝灏嗕細鎶涘嚭涓�涓紓甯革紙NoSuchBeanDefinitionException锛�
+     *
+     * @param name
+     * @return boolean
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.isSingleton(name);
+    }
+
+    /**
+     * @param name
+     * @return Class 娉ㄥ唽瀵硅薄鐨勭被鍨�
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getType(name);
+    }
+
+    /**
+     * 濡傛灉缁欏畾鐨刡ean鍚嶅瓧鍦╞ean瀹氫箟涓湁鍒悕锛屽垯杩斿洖杩欎簺鍒悕
+     *
+     * @param name
+     * @return
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getAliases(name);
+    }
+
+    /**
+     * 鑾峰彇aop浠g悊瀵硅薄
+     * 
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker)
+    {
+        return (T) AopContext.currentProxy();
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/StringUtils.java b/se-common/src/main/java/com/terra/common/utils/StringUtils.java
new file mode 100644
index 0000000..873a937
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/StringUtils.java
@@ -0,0 +1,633 @@
+package com.terra.common.utils;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import org.springframework.util.AntPathMatcher;
+import com.terra.common.constant.Constants;
+import com.terra.common.text.StrFormatter;
+
+/**
+ * 瀛楃涓插伐鍏风被
+ * 
+ * @author ruoyi
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+    /** 绌哄瓧绗︿覆 */
+    private static final String NULLSTR = "";
+
+    /** 涓嬪垝绾� */
+    private static final char SEPARATOR = '_';
+
+    /** 鏄熷彿 */
+    private static final char ASTERISK = '*';
+
+    /**
+     * 鑾峰彇鍙傛暟涓嶄负绌哄��
+     * 
+     * @param value defaultValue 瑕佸垽鏂殑value
+     * @return value 杩斿洖鍊�
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓狢ollection鏄惁涓虹┖锛� 鍖呭惈List锛孲et锛孮ueue
+     * 
+     * @param coll 瑕佸垽鏂殑Collection
+     * @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓狢ollection鏄惁闈炵┖锛屽寘鍚獿ist锛孲et锛孮ueue
+     * 
+     * @param coll 瑕佸垽鏂殑Collection
+     * @return true锛氶潪绌� false锛氱┖
+     */
+    public static boolean isNotEmpty(Collection<?> coll)
+    {
+        return !isEmpty(coll);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓璞℃暟缁勬槸鍚︿负绌�
+     * 
+     * @param objects 瑕佸垽鏂殑瀵硅薄鏁扮粍
+     ** @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isEmpty(Object[] objects)
+    {
+        return isNull(objects) || (objects.length == 0);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓璞℃暟缁勬槸鍚﹂潪绌�
+     * 
+     * @param objects 瑕佸垽鏂殑瀵硅薄鏁扮粍
+     * @return true锛氶潪绌� false锛氱┖
+     */
+    public static boolean isNotEmpty(Object[] objects)
+    {
+        return !isEmpty(objects);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓狹ap鏄惁涓虹┖
+     * 
+     * @param map 瑕佸垽鏂殑Map
+     * @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓狹ap鏄惁涓虹┖
+     * 
+     * @param map 瑕佸垽鏂殑Map
+     * @return true锛氶潪绌� false锛氱┖
+     */
+    public static boolean isNotEmpty(Map<?, ?> map)
+    {
+        return !isEmpty(map);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁涓虹┖涓�
+     * 
+     * @param str String
+     * @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isEmpty(String str)
+    {
+        return isNull(str) || NULLSTR.equals(str.trim());
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁涓洪潪绌轰覆
+     * 
+     * @param str String
+     * @return true锛氶潪绌轰覆 false锛氱┖涓�
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return !isEmpty(str);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓璞℃槸鍚︿负绌�
+     * 
+     * @param object Object
+     * @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isNull(Object object)
+    {
+        return object == null;
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓璞℃槸鍚﹂潪绌�
+     * 
+     * @param object Object
+     * @return true锛氶潪绌� false锛氱┖
+     */
+    public static boolean isNotNull(Object object)
+    {
+        return !isNull(object);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓璞℃槸鍚︽槸鏁扮粍绫诲瀷锛圝ava鍩烘湰鍨嬪埆鐨勬暟缁勶級
+     * 
+     * @param object 瀵硅薄
+     * @return true锛氭槸鏁扮粍 false锛氫笉鏄暟缁�
+     */
+    public static boolean isArray(Object object)
+    {
+        return isNotNull(object) && object.getClass().isArray();
+    }
+
+    /**
+     * 鍘荤┖鏍�
+     */
+    public static String trim(String str)
+    {
+        return (str == null ? "" : str.trim());
+    }
+
+    /**
+     * 鏇挎崲鎸囧畾瀛楃涓茬殑鎸囧畾鍖洪棿鍐呭瓧绗︿负"*"
+     *
+     * @param str 瀛楃涓�
+     * @param startInclude 寮�濮嬩綅缃紙鍖呭惈锛�
+     * @param endExclude 缁撴潫浣嶇疆锛堜笉鍖呭惈锛�
+     * @return 鏇挎崲鍚庣殑瀛楃涓�
+     */
+    public static String hide(CharSequence str, int startInclude, int endExclude)
+    {
+        if (isEmpty(str))
+        {
+            return NULLSTR;
+        }
+        final int strLength = str.length();
+        if (startInclude > strLength)
+        {
+            return NULLSTR;
+        }
+        if (endExclude > strLength)
+        {
+            endExclude = strLength;
+        }
+        if (startInclude > endExclude)
+        {
+            // 濡傛灉璧峰浣嶇疆澶т簬缁撴潫浣嶇疆锛屼笉鏇挎崲
+            return NULLSTR;
+        }
+        final char[] chars = new char[strLength];
+        for (int i = 0; i < strLength; i++)
+        {
+            if (i >= startInclude && i < endExclude)
+            {
+                chars[i] = ASTERISK;
+            }
+            else
+            {
+                chars[i] = str.charAt(i);
+            }
+        }
+        return new String(chars);
+    }
+
+    /**
+     * 鎴彇瀛楃涓�
+     * 
+     * @param str 瀛楃涓�
+     * @param start 寮�濮�
+     * @return 缁撴灉
+     */
+    public static String substring(final String str, int start)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (start > str.length())
+        {
+            return NULLSTR;
+        }
+
+        return str.substring(start);
+    }
+
+    /**
+     * 鎴彇瀛楃涓�
+     * 
+     * @param str 瀛楃涓�
+     * @param start 寮�濮�
+     * @param end 缁撴潫
+     * @return 缁撴灉
+     */
+    public static String substring(final String str, int start, int end)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (end < 0)
+        {
+            end = str.length() + end;
+        }
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (end > str.length())
+        {
+            end = str.length();
+        }
+
+        if (start > end)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (end < 0)
+        {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+    /**
+     * 鍦ㄥ瓧绗︿覆涓煡鎵剧涓�涓嚭鐜扮殑 `open` 鍜屾渶鍚庝竴涓嚭鐜扮殑 `close` 涔嬮棿鐨勫瓙瀛楃涓�
+     * 
+     * @param str 瑕佹埅鍙栫殑瀛楃涓�
+     * @param open 璧峰瀛楃涓�
+     * @param close 缁撴潫瀛楃涓�
+     * @return 鎴彇缁撴灉
+     */
+    public static String substringBetweenLast(final String str, final String open, final String close)
+    {
+        if (isEmpty(str) || isEmpty(open) || isEmpty(close))
+        {
+            return NULLSTR;
+        }
+        final int start = str.indexOf(open);
+        if (start != INDEX_NOT_FOUND)
+        {
+            final int end = str.lastIndexOf(close);
+            if (end != INDEX_NOT_FOUND)
+            {
+                return str.substring(start + open.length(), end);
+            }
+        }
+        return NULLSTR;
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓虹┖锛屽苟涓斾笉鏄┖鐧藉瓧绗�
+     * 
+     * @param str 瑕佸垽鏂殑value
+     * @return 缁撴灉
+     */
+    public static boolean hasText(String str)
+    {
+        return (str != null && !str.isEmpty() && containsText(str));
+    }
+
+    private static boolean containsText(CharSequence str)
+    {
+        int strLen = str.length();
+        for (int i = 0; i < strLen; i++)
+        {
+            if (!Character.isWhitespace(str.charAt(i)))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鏍煎紡鍖栨枃鏈�, {} 琛ㄧず鍗犱綅绗�<br>
+     * 姝ゆ柟娉曞彧鏄畝鍗曞皢鍗犱綅绗� {} 鎸夌収椤哄簭鏇挎崲涓哄弬鏁�<br>
+     * 濡傛灉鎯宠緭鍑� {} 浣跨敤 \\杞箟 { 鍗冲彲锛屽鏋滄兂杈撳嚭 {} 涔嬪墠鐨� \ 浣跨敤鍙岃浆涔夌 \\\\ 鍗冲彲<br>
+     * 渚嬶細<br>
+     * 閫氬父浣跨敤锛歠ormat("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 杞箟{}锛� format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 杞箟\锛� format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     * 
+     * @param template 鏂囨湰妯℃澘锛岃鏇挎崲鐨勯儴鍒嗙敤 {} 琛ㄧず
+     * @param params 鍙傛暟鍊�
+     * @return 鏍煎紡鍖栧悗鐨勬枃鏈�
+     */
+    public static String format(String template, Object... params)
+    {
+        if (isEmpty(params) || isEmpty(template))
+        {
+            return template;
+        }
+        return StrFormatter.format(template, params);
+    }
+
+    /**
+     * 鏄惁涓篽ttp(s)://寮�澶�
+     * 
+     * @param link 閾炬帴
+     * @return 缁撴灉
+     */
+    public static boolean ishttp(String link)
+    {
+        return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
+    }
+
+    /**
+     * 鍒ゆ柇缁欏畾鐨刢ollection鍒楄〃涓槸鍚﹀寘鍚暟缁刟rray 鍒ゆ柇缁欏畾鐨勬暟缁刟rray涓槸鍚﹀寘鍚粰瀹氱殑鍏冪礌value
+     *
+     * @param collection 缁欏畾鐨勯泦鍚�
+     * @param array 缁欏畾鐨勬暟缁�
+     * @return boolean 缁撴灉
+     */
+    public static boolean containsAny(Collection<String> collection, String... array)
+    {
+        if (isEmpty(collection) || isEmpty(array))
+        {
+            return false;
+        }
+        else
+        {
+            for (String str : array)
+            {
+                if (collection.contains(str))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * 椹煎嘲杞笅鍒掔嚎鍛藉悕
+     */
+    public static String toUnderScoreCase(String str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        // 鍓嶇疆瀛楃鏄惁澶у啓
+        boolean preCharIsUpperCase = true;
+        // 褰撳墠瀛楃鏄惁澶у啓
+        boolean curreCharIsUpperCase = true;
+        // 涓嬩竴瀛楃鏄惁澶у啓
+        boolean nexteCharIsUpperCase = true;
+        for (int i = 0; i < str.length(); i++)
+        {
+            char c = str.charAt(i);
+            if (i > 0)
+            {
+                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+            }
+            else
+            {
+                preCharIsUpperCase = false;
+            }
+
+            curreCharIsUpperCase = Character.isUpperCase(c);
+
+            if (i < (str.length() - 1))
+            {
+                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+            }
+
+            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 鏄惁鍖呭惈瀛楃涓�
+     * 
+     * @param str 楠岃瘉瀛楃涓�
+     * @param strs 瀛楃涓茬粍
+     * @return 鍖呭惈杩斿洖true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs)
+    {
+        if (str != null && strs != null)
+        {
+            for (String s : strs)
+            {
+                if (str.equalsIgnoreCase(trim(s)))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 灏嗕笅鍒掔嚎澶у啓鏂瑰紡鍛藉悕鐨勫瓧绗︿覆杞崲涓洪┘宄板紡銆傚鏋滆浆鎹㈠墠鐨勪笅鍒掔嚎澶у啓鏂瑰紡鍛藉悕鐨勫瓧绗︿覆涓虹┖锛屽垯杩斿洖绌哄瓧绗︿覆銆� 渚嬪锛欻ELLO_WORLD->HelloWorld
+     * 
+     * @param name 杞崲鍓嶇殑涓嬪垝绾垮ぇ鍐欐柟寮忓懡鍚嶇殑瀛楃涓�
+     * @return 杞崲鍚庣殑椹煎嘲寮忓懡鍚嶇殑瀛楃涓�
+     */
+    public static String convertToCamelCase(String name)
+    {
+        StringBuilder result = new StringBuilder();
+        // 蹇�熸鏌�
+        if (name == null || name.isEmpty())
+        {
+            // 娌″繀瑕佽浆鎹�
+            return "";
+        }
+        else if (!name.contains("_"))
+        {
+            // 涓嶅惈涓嬪垝绾匡紝浠呭皢棣栧瓧姣嶅ぇ鍐�
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+        }
+        // 鐢ㄤ笅鍒掔嚎灏嗗師濮嬪瓧绗︿覆鍒嗗壊
+        String[] camels = name.split("_");
+        for (String camel : camels)
+        {
+            // 璺宠繃鍘熷瀛楃涓蹭腑寮�澶淬�佺粨灏剧殑涓嬫崲绾挎垨鍙岄噸涓嬪垝绾�
+            if (camel.isEmpty())
+            {
+                continue;
+            }
+            // 棣栧瓧姣嶅ぇ鍐�
+            result.append(camel.substring(0, 1).toUpperCase());
+            result.append(camel.substring(1).toLowerCase());
+        }
+        return result.toString();
+    }
+
+    /**
+     * 椹煎嘲寮忓懡鍚嶆硶
+     * 渚嬪锛歶ser_name->userName
+     */
+    public static String toCamelCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        if (s.indexOf(SEPARATOR) == -1)
+        {
+            return s;
+        }
+        s = s.toLowerCase();
+        StringBuilder sb = new StringBuilder(s.length());
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            if (c == SEPARATOR)
+            {
+                upperCase = true;
+            }
+            else if (upperCase)
+            {
+                sb.append(Character.toUpperCase(c));
+                upperCase = false;
+            }
+            else
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀尮閰嶆寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆
+     * 
+     * @param str 鎸囧畾瀛楃涓�
+     * @param strs 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+     * @return 鏄惁鍖归厤
+     */
+    public static boolean matches(String str, List<String> strs)
+    {
+        if (isEmpty(str) || isEmpty(strs))
+        {
+            return false;
+        }
+        for (String pattern : strs)
+        {
+            if (isMatch(pattern, str))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鍒ゆ柇url鏄惁涓庤鍒欓厤缃�: 
+     * ? 琛ㄧず鍗曚釜瀛楃; 
+     * * 琛ㄧず涓�灞傝矾寰勫唴鐨勪换鎰忓瓧绗︿覆锛屼笉鍙法灞傜骇; 
+     * ** 琛ㄧず浠绘剰灞傝矾寰�;
+     * 
+     * @param pattern 鍖归厤瑙勫垯
+     * @param url 闇�瑕佸尮閰嶇殑url
+     * @return
+     */
+    public static boolean isMatch(String pattern, String url)
+    {
+        AntPathMatcher matcher = new AntPathMatcher();
+        return matcher.match(pattern, url);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T cast(Object obj)
+    {
+        return (T) obj;
+    }
+
+    /**
+     * 鏁板瓧宸﹁竟琛ラ綈0锛屼娇涔嬭揪鍒版寚瀹氶暱搴︺�傛敞鎰忥紝濡傛灉鏁板瓧杞崲涓哄瓧绗︿覆鍚庯紝闀垮害澶т簬size锛屽垯鍙繚鐣� 鏈�鍚巗ize涓瓧绗︺��
+     * 
+     * @param num 鏁板瓧瀵硅薄
+     * @param size 瀛楃涓叉寚瀹氶暱搴�
+     * @return 杩斿洖鏁板瓧鐨勫瓧绗︿覆鏍煎紡锛岃瀛楃涓蹭负鎸囧畾闀垮害銆�
+     */
+    public static final String padl(final Number num, final int size)
+    {
+        return padl(num.toString(), size, '0');
+    }
+
+    /**
+     * 瀛楃涓插乏琛ラ綈銆傚鏋滃師濮嬪瓧绗︿覆s闀垮害澶т簬size锛屽垯鍙繚鐣欐渶鍚巗ize涓瓧绗︺��
+     * 
+     * @param s 鍘熷瀛楃涓�
+     * @param size 瀛楃涓叉寚瀹氶暱搴�
+     * @param c 鐢ㄤ簬琛ラ綈鐨勫瓧绗�
+     * @return 杩斿洖鎸囧畾闀垮害鐨勫瓧绗︿覆锛岀敱鍘熷瓧绗︿覆宸﹁ˉ榻愭垨鎴彇寰楀埌銆�
+     */
+    public static final String padl(final String s, final int size, final char c)
+    {
+        final StringBuilder sb = new StringBuilder(size);
+        if (s != null)
+        {
+            final int len = s.length();
+            if (s.length() <= size)
+            {
+                for (int i = size - len; i > 0; i--)
+                {
+                    sb.append(c);
+                }
+                sb.append(s);
+            }
+            else
+            {
+                return s.substring(len - size, len);
+            }
+        }
+        else
+        {
+            for (int i = size; i > 0; i--)
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/bean/BeanUtils.java b/se-common/src/main/java/com/terra/common/utils/bean/BeanUtils.java
new file mode 100644
index 0000000..d7bdba1
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/bean/BeanUtils.java
@@ -0,0 +1,110 @@
+package com.terra.common.utils.bean;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Bean 宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class BeanUtils extends org.springframework.beans.BeanUtils
+{
+    /** Bean鏂规硶鍚嶄腑灞炴�у悕寮�濮嬬殑涓嬫爣 */
+    private static final int BEAN_METHOD_PROP_INDEX = 3;
+
+    /** * 鍖归厤getter鏂规硶鐨勬鍒欒〃杈惧紡 */
+    private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");
+
+    /** * 鍖归厤setter鏂规硶鐨勬鍒欒〃杈惧紡 */
+    private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");
+
+    /**
+     * Bean灞炴�у鍒跺伐鍏锋柟娉曘��
+     * 
+     * @param dest 鐩爣瀵硅薄
+     * @param src 婧愬璞�
+     */
+    public static void copyBeanProp(Object dest, Object src)
+    {
+        try
+        {
+            copyProperties(src, dest);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄鐨剆etter鏂规硶銆�
+     * 
+     * @param obj 瀵硅薄
+     * @return 瀵硅薄鐨剆etter鏂规硶鍒楄〃
+     */
+    public static List<Method> getSetterMethods(Object obj)
+    {
+        // setter鏂规硶鍒楄〃
+        List<Method> setterMethods = new ArrayList<Method>();
+
+        // 鑾峰彇鎵�鏈夋柟娉�
+        Method[] methods = obj.getClass().getMethods();
+
+        // 鏌ユ壘setter鏂规硶
+
+        for (Method method : methods)
+        {
+            Matcher m = SET_PATTERN.matcher(method.getName());
+            if (m.matches() && (method.getParameterTypes().length == 1))
+            {
+                setterMethods.add(method);
+            }
+        }
+        // 杩斿洖setter鏂规硶鍒楄〃
+        return setterMethods;
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄鐨刧etter鏂规硶銆�
+     * 
+     * @param obj 瀵硅薄
+     * @return 瀵硅薄鐨刧etter鏂规硶鍒楄〃
+     */
+
+    public static List<Method> getGetterMethods(Object obj)
+    {
+        // getter鏂规硶鍒楄〃
+        List<Method> getterMethods = new ArrayList<Method>();
+        // 鑾峰彇鎵�鏈夋柟娉�
+        Method[] methods = obj.getClass().getMethods();
+        // 鏌ユ壘getter鏂规硶
+        for (Method method : methods)
+        {
+            Matcher m = GET_PATTERN.matcher(method.getName());
+            if (m.matches() && (method.getParameterTypes().length == 0))
+            {
+                getterMethods.add(method);
+            }
+        }
+        // 杩斿洖getter鏂规硶鍒楄〃
+        return getterMethods;
+    }
+
+    /**
+     * 妫�鏌ean鏂规硶鍚嶄腑鐨勫睘鎬у悕鏄惁鐩哥瓑銆�<br>
+     * 濡俫etName()鍜宻etName()灞炴�у悕涓�鏍凤紝getName()鍜宻etAge()灞炴�у悕涓嶄竴鏍枫��
+     * 
+     * @param m1 鏂规硶鍚�1
+     * @param m2 鏂规硶鍚�2
+     * @return 灞炴�у悕涓�鏍疯繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse
+     */
+
+    public static boolean isMethodPropEquals(String m1, String m2)
+    {
+        return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/bean/BeanValidators.java b/se-common/src/main/java/com/terra/common/utils/bean/BeanValidators.java
new file mode 100644
index 0000000..959123d
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/bean/BeanValidators.java
@@ -0,0 +1,24 @@
+package com.terra.common.utils.bean;
+
+import java.util.Set;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.validation.Validator;
+
+/**
+ * bean瀵硅薄灞炴�ч獙璇�
+ * 
+ * @author ruoyi
+ */
+public class BeanValidators
+{
+    public static void validateWithException(Validator validator, Object object, Class<?>... groups)
+            throws ConstraintViolationException
+    {
+        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
+        if (!constraintViolations.isEmpty())
+        {
+            throw new ConstraintViolationException(constraintViolations);
+        }
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/file/FileTypeUtils.java b/se-common/src/main/java/com/terra/common/utils/file/FileTypeUtils.java
new file mode 100644
index 0000000..585db89
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/file/FileTypeUtils.java
@@ -0,0 +1,95 @@
+package com.terra.common.utils.file;
+
+import java.io.File;
+import java.util.Objects;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 鏂囦欢绫诲瀷宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class FileTypeUtils
+{
+    /**
+     * 鑾峰彇鏂囦欢绫诲瀷
+     * <p>
+     * 渚嬪: ruoyi.txt, 杩斿洖: txt
+     * 
+     * @param file 鏂囦欢鍚�
+     * @return 鍚庣紑锛堜笉鍚�".")
+     */
+    public static String getFileType(File file)
+    {
+        if (null == file)
+        {
+            return StringUtils.EMPTY;
+        }
+        return getFileType(file.getName());
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢绫诲瀷
+     * <p>
+     * 渚嬪: ruoyi.txt, 杩斿洖: txt
+     *
+     * @param fileName 鏂囦欢鍚�
+     * @return 鍚庣紑锛堜笉鍚�".")
+     */
+    public static String getFileType(String fileName)
+    {
+        int separatorIndex = fileName.lastIndexOf(".");
+        if (separatorIndex < 0)
+        {
+            return "";
+        }
+        return fileName.substring(separatorIndex + 1).toLowerCase();
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢鍚嶇殑鍚庣紑
+     * 
+     * @param file 琛ㄥ崟鏂囦欢
+     * @return 鍚庣紑鍚�
+     */
+    public static final String getExtension(MultipartFile file)
+    {
+        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
+        if (StringUtils.isEmpty(extension))
+        {
+            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
+        }
+        return extension;
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢绫诲瀷
+     * 
+     * @param photoByte 鏂囦欢瀛楄妭鐮�
+     * @return 鍚庣紑锛堜笉鍚�".")
+     */
+    public static String getFileExtendName(byte[] photoByte)
+    {
+        String strFileExtendName = "JPG";
+        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
+                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
+        {
+            strFileExtendName = "GIF";
+        }
+        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
+        {
+            strFileExtendName = "JPG";
+        }
+        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
+        {
+            strFileExtendName = "BMP";
+        }
+        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
+        {
+            strFileExtendName = "PNG";
+        }
+        return strFileExtendName;
+    }
+}
\ No newline at end of file
diff --git a/se-common/src/main/java/com/terra/common/utils/file/FileUtils.java b/se-common/src/main/java/com/terra/common/utils/file/FileUtils.java
new file mode 100644
index 0000000..43ac4de
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/file/FileUtils.java
@@ -0,0 +1,253 @@
+package com.terra.common.utils.file;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import com.terra.common.utils.StringUtils;
+
+/**
+ * 鏂囦欢澶勭悊宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class FileUtils
+{
+    /** 瀛楃甯搁噺锛氭枩鏉� {@code '/'} */
+    public static final char SLASH = '/';
+
+    /** 瀛楃甯搁噺锛氬弽鏂滄潬 {@code '\\'} */
+    public static final char BACKSLASH = '\\';
+
+    public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
+
+    /**
+     * 杈撳嚭鎸囧畾鏂囦欢鐨刡yte鏁扮粍
+     * 
+     * @param filePath 鏂囦欢璺緞
+     * @param os 杈撳嚭娴�
+     * @return
+     */
+    public static void writeBytes(String filePath, OutputStream os) throws IOException
+    {
+        FileInputStream fis = null;
+        try
+        {
+            File file = new File(filePath);
+            if (!file.exists())
+            {
+                throw new FileNotFoundException(filePath);
+            }
+            fis = new FileInputStream(file);
+            byte[] b = new byte[1024];
+            int length;
+            while ((length = fis.read(b)) > 0)
+            {
+                os.write(b, 0, length);
+            }
+        }
+        catch (IOException e)
+        {
+            throw e;
+        }
+        finally
+        {
+            if (os != null)
+            {
+                try
+                {
+                    os.close();
+                }
+                catch (IOException e1)
+                {
+                    e1.printStackTrace();
+                }
+            }
+            if (fis != null)
+            {
+                try
+                {
+                    fis.close();
+                }
+                catch (IOException e1)
+                {
+                    e1.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * 鍒犻櫎鏂囦欢
+     * 
+     * @param filePath 鏂囦欢
+     * @return
+     */
+    public static boolean deleteFile(String filePath)
+    {
+        boolean flag = false;
+        File file = new File(filePath);
+        // 璺緞涓烘枃浠朵笖涓嶄负绌哄垯杩涜鍒犻櫎
+        if (file.isFile() && file.exists())
+        {
+            flag = file.delete();
+        }
+        return flag;
+    }
+
+    /**
+     * 鏂囦欢鍚嶇О楠岃瘉
+     * 
+     * @param filename 鏂囦欢鍚嶇О
+     * @return true 姝e父 false 闈炴硶
+     */
+    public static boolean isValidFilename(String filename)
+    {
+        return filename.matches(FILENAME_PATTERN);
+    }
+
+    /**
+     * 鏍¢獙鏂囦欢璺緞鍚堟硶鎬э紙瀹夊叏鎬т笌鎵╁睍鍚嶏級
+     * 
+     * @param fileUrl 寰呮牎楠岀殑鏂囦欢鍦板潃
+     * @return true 姝e父 false 闈炴硶
+     */
+    public static boolean validateFilePath(String fileUrl)
+    {
+        // 绂佹鐩綍涓婅烦绾у埆
+        if (StringUtils.contains(fileUrl, ".."))
+        {
+            return false;
+        }
+        // 鍒ゆ柇鏄惁鍦ㄥ厑璁镐笅杞界殑鏂囦欢瑙勫垯鍐�
+        return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(fileUrl));
+    }
+
+    /**
+     * 涓嬭浇鏂囦欢鍚嶉噸鏂扮紪鐮�
+     * 
+     * @param request 璇锋眰瀵硅薄
+     * @param fileName 鏂囦欢鍚�
+     * @return 缂栫爜鍚庣殑鏂囦欢鍚�
+     */
+    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
+    {
+        final String agent = request.getHeader("USER-AGENT");
+        String filename = fileName;
+        if (agent.contains("MSIE"))
+        {
+            // IE娴忚鍣�
+            filename = URLEncoder.encode(filename, "utf-8");
+            filename = filename.replace("+", " ");
+        }
+        else if (agent.contains("Firefox"))
+        {
+            // 鐏嫄娴忚鍣�
+            filename = new String(fileName.getBytes(), "ISO8859-1");
+        }
+        else if (agent.contains("Chrome"))
+        {
+            // google娴忚鍣�
+            filename = URLEncoder.encode(filename, "utf-8");
+        }
+        else
+        {
+            // 鍏跺畠娴忚鍣�
+            filename = URLEncoder.encode(filename, "utf-8");
+        }
+        return filename;
+    }
+
+    /**
+     * 杩斿洖鏂囦欢鍚�
+     *
+     * @param filePath 鏂囦欢
+     * @return 鏂囦欢鍚�
+     */
+    public static String getName(String filePath)
+    {
+        if (null == filePath)
+        {
+            return null;
+        }
+        int len = filePath.length();
+        if (0 == len)
+        {
+            return filePath;
+        }
+        if (isFileSeparator(filePath.charAt(len - 1)))
+        {
+            // 浠ュ垎闅旂缁撳熬鐨勫幓鎺夌粨灏惧垎闅旂
+            len--;
+        }
+
+        int begin = 0;
+        char c;
+        for (int i = len - 1; i > -1; i--)
+        {
+            c = filePath.charAt(i);
+            if (isFileSeparator(c))
+            {
+                // 鏌ユ壘鏈�鍚庝竴涓矾寰勫垎闅旂锛�/鎴栬�匼锛�
+                begin = i + 1;
+                break;
+            }
+        }
+
+        return filePath.substring(begin, len);
+    }
+
+    /**
+     * 鏄惁涓篧indows鎴栬�匧inux锛圲nix锛夋枃浠跺垎闅旂<br>
+     * Windows骞冲彴涓嬪垎闅旂涓篭锛孡inux锛圲nix锛変负/
+     *
+     * @param c 瀛楃
+     * @return 鏄惁涓篧indows鎴栬�匧inux锛圲nix锛夋枃浠跺垎闅旂
+     */
+    public static boolean isFileSeparator(char c)
+    {
+        return SLASH == c || BACKSLASH == c;
+    }
+
+    /**
+     * 涓嬭浇鏂囦欢鍚嶉噸鏂扮紪鐮�
+     *
+     * @param response 鍝嶅簲瀵硅薄
+     * @param realFileName 鐪熷疄鏂囦欢鍚�
+     * @return
+     */
+    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
+    {
+        String percentEncodedFileName = percentEncode(realFileName);
+
+        StringBuilder contentDispositionValue = new StringBuilder();
+        contentDispositionValue.append("attachment; filename=")
+                .append(percentEncodedFileName)
+                .append(";")
+                .append("filename*=")
+                .append("utf-8''")
+                .append(percentEncodedFileName);
+
+        response.setHeader("Content-disposition", contentDispositionValue.toString());
+        response.setHeader("download-filename", percentEncodedFileName);
+    }
+
+    /**
+     * 鐧惧垎鍙风紪鐮佸伐鍏锋柟娉�
+     *
+     * @param s 闇�瑕佺櫨鍒嗗彿缂栫爜鐨勫瓧绗︿覆
+     * @return 鐧惧垎鍙风紪鐮佸悗鐨勫瓧绗︿覆
+     */
+    public static String percentEncode(String s) throws UnsupportedEncodingException
+    {
+        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
+        return encode.replaceAll("\\+", "%20");
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/file/ImageUtils.java b/se-common/src/main/java/com/terra/common/utils/file/ImageUtils.java
new file mode 100644
index 0000000..0f93b2f
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/file/ImageUtils.java
@@ -0,0 +1,84 @@
+package com.terra.common.utils.file;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Arrays;
+import org.apache.poi.util.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 鍥剧墖澶勭悊宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class ImageUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
+
+    public static byte[] getImage(String imagePath)
+    {
+        InputStream is = getFile(imagePath);
+        try
+        {
+            return IOUtils.toByteArray(is);
+        }
+        catch (Exception e)
+        {
+            log.error("鍥剧墖鍔犺浇寮傚父 {}", e);
+            return null;
+        }
+        finally
+        {
+            IOUtils.closeQuietly(is);
+        }
+    }
+
+    public static InputStream getFile(String imagePath)
+    {
+        try
+        {
+            byte[] result = readFile(imagePath);
+            result = Arrays.copyOf(result, result.length);
+            return new ByteArrayInputStream(result);
+        }
+        catch (Exception e)
+        {
+            log.error("鑾峰彇鍥剧墖寮傚父 {}", e);
+        }
+        return null;
+    }
+
+    /**
+     * 璇诲彇鏂囦欢涓哄瓧鑺傛暟鎹�
+     * 
+     * @param url 鍦板潃
+     * @return 瀛楄妭鏁版嵁
+     */
+    public static byte[] readFile(String url)
+    {
+        InputStream in = null;
+        try
+        {
+            // 缃戠粶鍦板潃
+            URL urlObj = new URL(url);
+            URLConnection urlConnection = urlObj.openConnection();
+            urlConnection.setConnectTimeout(30 * 1000);
+            urlConnection.setReadTimeout(60 * 1000);
+            urlConnection.setDoInput(true);
+            in = urlConnection.getInputStream();
+            return IOUtils.toByteArray(in);
+        }
+        catch (Exception e)
+        {
+            log.error("璁块棶鏂囦欢寮傚父 {}", e);
+            return null;
+        }
+        finally
+        {
+            IOUtils.closeQuietly(in);
+        }
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/file/MimeTypeUtils.java b/se-common/src/main/java/com/terra/common/utils/file/MimeTypeUtils.java
new file mode 100644
index 0000000..46ef4ca
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/file/MimeTypeUtils.java
@@ -0,0 +1,59 @@
+package com.terra.common.utils.file;
+
+/**
+ * 濯掍綋绫诲瀷宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class MimeTypeUtils
+{
+    public static final String IMAGE_PNG = "image/png";
+
+    public static final String IMAGE_JPG = "image/jpg";
+
+    public static final String IMAGE_JPEG = "image/jpeg";
+
+    public static final String IMAGE_BMP = "image/bmp";
+
+    public static final String IMAGE_GIF = "image/gif";
+
+    public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
+
+    public static final String[] FLASH_EXTENSION = { "swf", "flv" };
+
+    public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
+            "asf", "rm", "rmvb" };
+
+    public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
+
+    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
+            // 鍥剧墖
+            "bmp", "gif", "jpg", "jpeg", "png",
+            // word excel powerpoint
+            "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
+            // 鍘嬬缉鏂囦欢
+            "rar", "zip", "gz", "bz2",
+            // 瑙嗛鏍煎紡
+            "mp4", "avi", "rmvb",
+            // pdf
+            "pdf" };
+
+    public static String getExtension(String prefix)
+    {
+        switch (prefix)
+        {
+            case IMAGE_PNG:
+                return "png";
+            case IMAGE_JPG:
+                return "jpg";
+            case IMAGE_JPEG:
+                return "jpeg";
+            case IMAGE_BMP:
+                return "bmp";
+            case IMAGE_GIF:
+                return "gif";
+            default:
+                return "";
+        }
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/html/EscapeUtil.java b/se-common/src/main/java/com/terra/common/utils/html/EscapeUtil.java
new file mode 100644
index 0000000..c11960a
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/html/EscapeUtil.java
@@ -0,0 +1,167 @@
+package com.terra.common.utils.html;
+
+import com.terra.common.utils.StringUtils;
+
+/**
+ * 杞箟鍜屽弽杞箟宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class EscapeUtil
+{
+    public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
+
+    private static final char[][] TEXT = new char[64][];
+
+    static
+    {
+        for (int i = 0; i < 64; i++)
+        {
+            TEXT[i] = new char[] { (char) i };
+        }
+
+        // special HTML characters
+        TEXT['\''] = "&#039;".toCharArray(); // 鍗曞紩鍙�
+        TEXT['"'] = "&#34;".toCharArray(); // 鍙屽紩鍙�
+        TEXT['&'] = "&#38;".toCharArray(); // &绗�
+        TEXT['<'] = "&#60;".toCharArray(); // 灏忎簬鍙�
+        TEXT['>'] = "&#62;".toCharArray(); // 澶т簬鍙�
+    }
+
+    /**
+     * 杞箟鏂囨湰涓殑HTML瀛楃涓哄畨鍏ㄧ殑瀛楃
+     * 
+     * @param text 琚浆涔夌殑鏂囨湰
+     * @return 杞箟鍚庣殑鏂囨湰
+     */
+    public static String escape(String text)
+    {
+        return encode(text);
+    }
+
+    /**
+     * 杩樺師琚浆涔夌殑HTML鐗规畩瀛楃
+     * 
+     * @param content 鍖呭惈杞箟绗︾殑HTML鍐呭
+     * @return 杞崲鍚庣殑瀛楃涓�
+     */
+    public static String unescape(String content)
+    {
+        return decode(content);
+    }
+
+    /**
+     * 娓呴櫎鎵�鏈塇TML鏍囩锛屼絾鏄笉鍒犻櫎鏍囩鍐呯殑鍐呭
+     * 
+     * @param content 鏂囨湰
+     * @return 娓呴櫎鏍囩鍚庣殑鏂囨湰
+     */
+    public static String clean(String content)
+    {
+        return new HTMLFilter().filter(content);
+    }
+
+    /**
+     * Escape缂栫爜
+     * 
+     * @param text 琚紪鐮佺殑鏂囨湰
+     * @return 缂栫爜鍚庣殑瀛楃
+     */
+    private static String encode(String text)
+    {
+        if (StringUtils.isEmpty(text))
+        {
+            return StringUtils.EMPTY;
+        }
+
+        final StringBuilder tmp = new StringBuilder(text.length() * 6);
+        char c;
+        for (int i = 0; i < text.length(); i++)
+        {
+            c = text.charAt(i);
+            if (c < 256)
+            {
+                tmp.append("%");
+                if (c < 16)
+                {
+                    tmp.append("0");
+                }
+                tmp.append(Integer.toString(c, 16));
+            }
+            else
+            {
+                tmp.append("%u");
+                if (c <= 0xfff)
+                {
+                    // issue#I49JU8@Gitee
+                    tmp.append("0");
+                }
+                tmp.append(Integer.toString(c, 16));
+            }
+        }
+        return tmp.toString();
+    }
+
+    /**
+     * Escape瑙g爜
+     * 
+     * @param content 琚浆涔夌殑鍐呭
+     * @return 瑙g爜鍚庣殑瀛楃涓�
+     */
+    public static String decode(String content)
+    {
+        if (StringUtils.isEmpty(content))
+        {
+            return content;
+        }
+
+        StringBuilder tmp = new StringBuilder(content.length());
+        int lastPos = 0, pos = 0;
+        char ch;
+        while (lastPos < content.length())
+        {
+            pos = content.indexOf("%", lastPos);
+            if (pos == lastPos)
+            {
+                if (content.charAt(pos + 1) == 'u')
+                {
+                    ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
+                    tmp.append(ch);
+                    lastPos = pos + 6;
+                }
+                else
+                {
+                    ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
+                    tmp.append(ch);
+                    lastPos = pos + 3;
+                }
+            }
+            else
+            {
+                if (pos == -1)
+                {
+                    tmp.append(content.substring(lastPos));
+                    lastPos = content.length();
+                }
+                else
+                {
+                    tmp.append(content.substring(lastPos, pos));
+                    lastPos = pos;
+                }
+            }
+        }
+        return tmp.toString();
+    }
+
+    public static void main(String[] args)
+    {
+        String html = "<script>alert(1);</script>";
+        String escape = EscapeUtil.escape(html);
+        // String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
+        // String html = "<123";
+        // String html = "123>";
+        System.out.println("clean: " + EscapeUtil.clean(html));
+        System.out.println("escape: " + escape);
+        System.out.println("unescape: " + EscapeUtil.unescape(escape));
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/html/HTMLFilter.java b/se-common/src/main/java/com/terra/common/utils/html/HTMLFilter.java
new file mode 100644
index 0000000..a751949
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/html/HTMLFilter.java
@@ -0,0 +1,570 @@
+package com.terra.common.utils.html;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * HTML杩囨护鍣紝鐢ㄤ簬鍘婚櫎XSS婕忔礊闅愭偅銆�
+ *
+ * @author ruoyi
+ */
+public final class HTMLFilter
+{
+    /**
+     * regex flag union representing /si modifiers in php
+     **/
+    private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
+    private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
+    private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
+    private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
+    private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
+    private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
+    private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
+    private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
+    private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
+    private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
+    private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
+    private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
+    private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
+    private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
+    private static final Pattern P_END_ARROW = Pattern.compile("^>");
+    private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
+    private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
+    private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
+    private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
+    private static final Pattern P_AMP = Pattern.compile("&");
+    private static final Pattern P_QUOTE = Pattern.compile("\"");
+    private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
+    private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
+    private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
+
+    // @xxx could grow large... maybe use sesat's ReferenceMap
+    private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>();
+    private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>();
+
+    /**
+     * set of allowed html elements, along with allowed attributes for each element
+     **/
+    private final Map<String, List<String>> vAllowed;
+    /**
+     * counts of open tags for each (allowable) html element
+     **/
+    private final Map<String, Integer> vTagCounts = new HashMap<>();
+
+    /**
+     * html elements which must always be self-closing (e.g. "<img />")
+     **/
+    private final String[] vSelfClosingTags;
+    /**
+     * html elements which must always have separate opening and closing tags (e.g. "<b></b>")
+     **/
+    private final String[] vNeedClosingTags;
+    /**
+     * set of disallowed html elements
+     **/
+    private final String[] vDisallowed;
+    /**
+     * attributes which should be checked for valid protocols
+     **/
+    private final String[] vProtocolAtts;
+    /**
+     * allowed protocols
+     **/
+    private final String[] vAllowedProtocols;
+    /**
+     * tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
+     **/
+    private final String[] vRemoveBlanks;
+    /**
+     * entities allowed within html markup
+     **/
+    private final String[] vAllowedEntities;
+    /**
+     * flag determining whether comments are allowed in input String.
+     */
+    private final boolean stripComment;
+    private final boolean encodeQuotes;
+    /**
+     * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>"
+     * becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped.
+     */
+    private final boolean alwaysMakeTags;
+
+    /**
+     * Default constructor.
+     */
+    public HTMLFilter()
+    {
+        vAllowed = new HashMap<>();
+
+        final ArrayList<String> a_atts = new ArrayList<>();
+        a_atts.add("href");
+        a_atts.add("target");
+        vAllowed.put("a", a_atts);
+
+        final ArrayList<String> img_atts = new ArrayList<>();
+        img_atts.add("src");
+        img_atts.add("width");
+        img_atts.add("height");
+        img_atts.add("alt");
+        vAllowed.put("img", img_atts);
+
+        final ArrayList<String> no_atts = new ArrayList<>();
+        vAllowed.put("b", no_atts);
+        vAllowed.put("strong", no_atts);
+        vAllowed.put("i", no_atts);
+        vAllowed.put("em", no_atts);
+
+        vSelfClosingTags = new String[] { "img" };
+        vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" };
+        vDisallowed = new String[] {};
+        vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp.
+        vProtocolAtts = new String[] { "src", "href" };
+        vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" };
+        vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
+        stripComment = true;
+        encodeQuotes = true;
+        alwaysMakeTags = false;
+    }
+
+    /**
+     * Map-parameter configurable constructor.
+     *
+     * @param conf map containing configuration. keys match field names.
+     */
+    @SuppressWarnings("unchecked")
+    public HTMLFilter(final Map<String, Object> conf)
+    {
+
+        assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
+        assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
+        assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
+        assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
+        assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
+        assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
+        assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
+        assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
+
+        vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
+        vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
+        vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
+        vDisallowed = (String[]) conf.get("vDisallowed");
+        vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
+        vProtocolAtts = (String[]) conf.get("vProtocolAtts");
+        vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
+        vAllowedEntities = (String[]) conf.get("vAllowedEntities");
+        stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
+        encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
+        alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
+    }
+
+    private void reset()
+    {
+        vTagCounts.clear();
+    }
+
+    // ---------------------------------------------------------------
+    // my versions of some PHP library functions
+    public static String chr(final int decimal)
+    {
+        return String.valueOf((char) decimal);
+    }
+
+    public static String htmlSpecialChars(final String s)
+    {
+        String result = s;
+        result = regexReplace(P_AMP, "&amp;", result);
+        result = regexReplace(P_QUOTE, "&quot;", result);
+        result = regexReplace(P_LEFT_ARROW, "&lt;", result);
+        result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
+        return result;
+    }
+
+    // ---------------------------------------------------------------
+
+    /**
+     * given a user submitted input String, filter out any invalid or restricted html.
+     *
+     * @param input text (i.e. submitted by a user) than may contain html
+     * @return "clean" version of input, with only valid, whitelisted html elements allowed
+     */
+    public String filter(final String input)
+    {
+        reset();
+        String s = input;
+
+        s = escapeComments(s);
+
+        s = balanceHTML(s);
+
+        s = checkTags(s);
+
+        s = processRemoveBlanks(s);
+
+        // s = validateEntities(s);
+
+        return s;
+    }
+
+    public boolean isAlwaysMakeTags()
+    {
+        return alwaysMakeTags;
+    }
+
+    public boolean isStripComments()
+    {
+        return stripComment;
+    }
+
+    private String escapeComments(final String s)
+    {
+        final Matcher m = P_COMMENTS.matcher(s);
+        final StringBuffer buf = new StringBuffer();
+        if (m.find())
+        {
+            final String match = m.group(1); // (.*?)
+            m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
+        }
+        m.appendTail(buf);
+
+        return buf.toString();
+    }
+
+    private String balanceHTML(String s)
+    {
+        if (alwaysMakeTags)
+        {
+            //
+            // try and form html
+            //
+            s = regexReplace(P_END_ARROW, "", s);
+            // 涓嶈拷鍔犵粨鏉熸爣绛�
+            s = regexReplace(P_BODY_TO_END, "<$1>", s);
+            s = regexReplace(P_XML_CONTENT, "$1<$2", s);
+
+        }
+        else
+        {
+            //
+            // escape stray brackets
+            //
+            s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
+            s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
+
+            //
+            // the last regexp causes '<>' entities to appear
+            // (we need to do a lookahead assertion so that the last bracket can
+            // be used in the next pass of the regexp)
+            //
+            s = regexReplace(P_BOTH_ARROWS, "", s);
+        }
+
+        return s;
+    }
+
+    private String checkTags(String s)
+    {
+        Matcher m = P_TAGS.matcher(s);
+
+        final StringBuffer buf = new StringBuffer();
+        while (m.find())
+        {
+            String replaceStr = m.group(1);
+            replaceStr = processTag(replaceStr);
+            m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
+        }
+        m.appendTail(buf);
+
+        // these get tallied in processTag
+        // (remember to reset before subsequent calls to filter method)
+        final StringBuilder sBuilder = new StringBuilder(buf.toString());
+        for (String key : vTagCounts.keySet())
+        {
+            for (int ii = 0; ii < vTagCounts.get(key); ii++)
+            {
+                sBuilder.append("</").append(key).append(">");
+            }
+        }
+        s = sBuilder.toString();
+
+        return s;
+    }
+
+    private String processRemoveBlanks(final String s)
+    {
+        String result = s;
+        for (String tag : vRemoveBlanks)
+        {
+            if (!P_REMOVE_PAIR_BLANKS.containsKey(tag))
+            {
+                P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
+            }
+            result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
+            if (!P_REMOVE_SELF_BLANKS.containsKey(tag))
+            {
+                P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
+            }
+            result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
+        }
+
+        return result;
+    }
+
+    private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s)
+    {
+        Matcher m = regex_pattern.matcher(s);
+        return m.replaceAll(replacement);
+    }
+
+    private String processTag(final String s)
+    {
+        // ending tags
+        Matcher m = P_END_TAG.matcher(s);
+        if (m.find())
+        {
+            final String name = m.group(1).toLowerCase();
+            if (allowed(name))
+            {
+                if (!inArray(name, vSelfClosingTags))
+                {
+                    if (vTagCounts.containsKey(name))
+                    {
+                        vTagCounts.put(name, vTagCounts.get(name) - 1);
+                        return "</" + name + ">";
+                    }
+                }
+            }
+        }
+
+        // starting tags
+        m = P_START_TAG.matcher(s);
+        if (m.find())
+        {
+            final String name = m.group(1).toLowerCase();
+            final String body = m.group(2);
+            String ending = m.group(3);
+
+            // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
+            if (allowed(name))
+            {
+                final StringBuilder params = new StringBuilder();
+
+                final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
+                final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
+                final List<String> paramNames = new ArrayList<>();
+                final List<String> paramValues = new ArrayList<>();
+                while (m2.find())
+                {
+                    paramNames.add(m2.group(1)); // ([a-z0-9]+)
+                    paramValues.add(m2.group(3)); // (.*?)
+                }
+                while (m3.find())
+                {
+                    paramNames.add(m3.group(1)); // ([a-z0-9]+)
+                    paramValues.add(m3.group(3)); // ([^\"\\s']+)
+                }
+
+                String paramName, paramValue;
+                for (int ii = 0; ii < paramNames.size(); ii++)
+                {
+                    paramName = paramNames.get(ii).toLowerCase();
+                    paramValue = paramValues.get(ii);
+
+                    // debug( "paramName='" + paramName + "'" );
+                    // debug( "paramValue='" + paramValue + "'" );
+                    // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
+
+                    if (allowedAttribute(name, paramName))
+                    {
+                        if (inArray(paramName, vProtocolAtts))
+                        {
+                            paramValue = processParamProtocol(paramValue);
+                        }
+                        params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\\\"");
+                    }
+                }
+
+                if (inArray(name, vSelfClosingTags))
+                {
+                    ending = " /";
+                }
+
+                if (inArray(name, vNeedClosingTags))
+                {
+                    ending = "";
+                }
+
+                if (ending == null || ending.length() < 1)
+                {
+                    if (vTagCounts.containsKey(name))
+                    {
+                        vTagCounts.put(name, vTagCounts.get(name) + 1);
+                    }
+                    else
+                    {
+                        vTagCounts.put(name, 1);
+                    }
+                }
+                else
+                {
+                    ending = " /";
+                }
+                return "<" + name + params + ending + ">";
+            }
+            else
+            {
+                return "";
+            }
+        }
+
+        // comments
+        m = P_COMMENT.matcher(s);
+        if (!stripComment && m.find())
+        {
+            return "<" + m.group() + ">";
+        }
+
+        return "";
+    }
+
+    private String processParamProtocol(String s)
+    {
+        s = decodeEntities(s);
+        final Matcher m = P_PROTOCOL.matcher(s);
+        if (m.find())
+        {
+            final String protocol = m.group(1);
+            if (!inArray(protocol, vAllowedProtocols))
+            {
+                // bad protocol, turn into local anchor link instead
+                s = "#" + s.substring(protocol.length() + 1);
+                if (s.startsWith("#//"))
+                {
+                    s = "#" + s.substring(3);
+                }
+            }
+        }
+
+        return s;
+    }
+
+    private String decodeEntities(String s)
+    {
+        StringBuffer buf = new StringBuffer();
+
+        Matcher m = P_ENTITY.matcher(s);
+        while (m.find())
+        {
+            final String match = m.group(1);
+            final int decimal = Integer.decode(match).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        buf = new StringBuffer();
+        m = P_ENTITY_UNICODE.matcher(s);
+        while (m.find())
+        {
+            final String match = m.group(1);
+            final int decimal = Integer.valueOf(match, 16).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        buf = new StringBuffer();
+        m = P_ENCODE.matcher(s);
+        while (m.find())
+        {
+            final String match = m.group(1);
+            final int decimal = Integer.valueOf(match, 16).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        s = validateEntities(s);
+        return s;
+    }
+
+    private String validateEntities(final String s)
+    {
+        StringBuffer buf = new StringBuffer();
+
+        // validate entities throughout the string
+        Matcher m = P_VALID_ENTITIES.matcher(s);
+        while (m.find())
+        {
+            final String one = m.group(1); // ([^&;]*)
+            final String two = m.group(2); // (?=(;|&|$))
+            m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
+        }
+        m.appendTail(buf);
+
+        return encodeQuotes(buf.toString());
+    }
+
+    private String encodeQuotes(final String s)
+    {
+        if (encodeQuotes)
+        {
+            StringBuffer buf = new StringBuffer();
+            Matcher m = P_VALID_QUOTES.matcher(s);
+            while (m.find())
+            {
+                final String one = m.group(1); // (>|^)
+                final String two = m.group(2); // ([^<]+?)
+                final String three = m.group(3); // (<|$)
+                // 涓嶆浛鎹㈠弻寮曞彿涓�&quot;锛岄槻姝son鏍煎紡鏃犳晥 regexReplace(P_QUOTE, "&quot;", two)
+                m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three));
+            }
+            m.appendTail(buf);
+            return buf.toString();
+        }
+        else
+        {
+            return s;
+        }
+    }
+
+    private String checkEntity(final String preamble, final String term)
+    {
+
+        return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&amp;" + preamble;
+    }
+
+    private boolean isValidEntity(final String entity)
+    {
+        return inArray(entity, vAllowedEntities);
+    }
+
+    private static boolean inArray(final String s, final String[] array)
+    {
+        for (String item : array)
+        {
+            if (item != null && item.equals(s))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean allowed(final String name)
+    {
+        return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
+    }
+
+    private boolean allowedAttribute(final String name, final String paramName)
+    {
+        return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
+    }
+}
\ No newline at end of file
diff --git a/se-common/src/main/java/com/terra/common/utils/ip/IpUtils.java b/se-common/src/main/java/com/terra/common/utils/ip/IpUtils.java
new file mode 100644
index 0000000..5c89db5
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/ip/IpUtils.java
@@ -0,0 +1,382 @@
+package com.terra.common.utils.ip;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import javax.servlet.http.HttpServletRequest;
+import com.terra.common.utils.ServletUtils;
+import com.terra.common.utils.StringUtils;
+
+/**
+ * 鑾峰彇IP鏂规硶
+ * 
+ * @author ruoyi
+ */
+public class IpUtils
+{
+    public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";
+    // 鍖归厤 ip
+    public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")";
+    public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))";
+    // 鍖归厤缃戞
+    public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")";
+
+    /**
+     * 鑾峰彇瀹㈡埛绔疘P
+     * 
+     * @return IP鍦板潃
+     */
+    public static String getIpAddr()
+    {
+        return getIpAddr(ServletUtils.getRequest());
+    }
+
+    /**
+     * 鑾峰彇瀹㈡埛绔疘P
+     * 
+     * @param request 璇锋眰瀵硅薄
+     * @return IP鍦板潃
+     */
+    public static String getIpAddr(HttpServletRequest request)
+    {
+        if (request == null)
+        {
+            return "unknown";
+        }
+        String ip = request.getHeader("x-forwarded-for");
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getHeader("X-Forwarded-For");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getHeader("X-Real-IP");
+        }
+
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getRemoteAddr();
+        }
+
+        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
+    }
+
+    /**
+     * 妫�鏌ユ槸鍚︿负鍐呴儴IP鍦板潃
+     * 
+     * @param ip IP鍦板潃
+     * @return 缁撴灉
+     */
+    public static boolean internalIp(String ip)
+    {
+        byte[] addr = textToNumericFormatV4(ip);
+        return internalIp(addr) || "127.0.0.1".equals(ip);
+    }
+
+    /**
+     * 妫�鏌ユ槸鍚︿负鍐呴儴IP鍦板潃
+     * 
+     * @param addr byte鍦板潃
+     * @return 缁撴灉
+     */
+    private static boolean internalIp(byte[] addr)
+    {
+        if (StringUtils.isNull(addr) || addr.length < 2)
+        {
+            return true;
+        }
+        final byte b0 = addr[0];
+        final byte b1 = addr[1];
+        // 10.x.x.x/8
+        final byte SECTION_1 = 0x0A;
+        // 172.16.x.x/12
+        final byte SECTION_2 = (byte) 0xAC;
+        final byte SECTION_3 = (byte) 0x10;
+        final byte SECTION_4 = (byte) 0x1F;
+        // 192.168.x.x/16
+        final byte SECTION_5 = (byte) 0xC0;
+        final byte SECTION_6 = (byte) 0xA8;
+        switch (b0)
+        {
+            case SECTION_1:
+                return true;
+            case SECTION_2:
+                if (b1 >= SECTION_3 && b1 <= SECTION_4)
+                {
+                    return true;
+                }
+            case SECTION_5:
+                switch (b1)
+                {
+                    case SECTION_6:
+                        return true;
+                }
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * 灏咺Pv4鍦板潃杞崲鎴愬瓧鑺�
+     * 
+     * @param text IPv4鍦板潃
+     * @return byte 瀛楄妭
+     */
+    public static byte[] textToNumericFormatV4(String text)
+    {
+        if (text.length() == 0)
+        {
+            return null;
+        }
+
+        byte[] bytes = new byte[4];
+        String[] elements = text.split("\\.", -1);
+        try
+        {
+            long l;
+            int i;
+            switch (elements.length)
+            {
+                case 1:
+                    l = Long.parseLong(elements[0]);
+                    if ((l < 0L) || (l > 4294967295L))
+                    {
+                        return null;
+                    }
+                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
+                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 2:
+                    l = Integer.parseInt(elements[0]);
+                    if ((l < 0L) || (l > 255L))
+                    {
+                        return null;
+                    }
+                    bytes[0] = (byte) (int) (l & 0xFF);
+                    l = Integer.parseInt(elements[1]);
+                    if ((l < 0L) || (l > 16777215L))
+                    {
+                        return null;
+                    }
+                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 3:
+                    for (i = 0; i < 2; ++i)
+                    {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L))
+                        {
+                            return null;
+                        }
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    l = Integer.parseInt(elements[2]);
+                    if ((l < 0L) || (l > 65535L))
+                    {
+                        return null;
+                    }
+                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 4:
+                    for (i = 0; i < 4; ++i)
+                    {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L))
+                        {
+                            return null;
+                        }
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    break;
+                default:
+                    return null;
+            }
+        }
+        catch (NumberFormatException e)
+        {
+            return null;
+        }
+        return bytes;
+    }
+
+    /**
+     * 鑾峰彇IP鍦板潃
+     * 
+     * @return 鏈湴IP鍦板潃
+     */
+    public static String getHostIp()
+    {
+        try
+        {
+            return InetAddress.getLocalHost().getHostAddress();
+        }
+        catch (UnknownHostException e)
+        {
+        }
+        return "127.0.0.1";
+    }
+
+    /**
+     * 鑾峰彇涓绘満鍚�
+     * 
+     * @return 鏈湴涓绘満鍚�
+     */
+    public static String getHostName()
+    {
+        try
+        {
+            return InetAddress.getLocalHost().getHostName();
+        }
+        catch (UnknownHostException e)
+        {
+        }
+        return "鏈煡";
+    }
+
+    /**
+     * 浠庡绾у弽鍚戜唬鐞嗕腑鑾峰緱绗竴涓潪unknown IP鍦板潃
+     *
+     * @param ip 鑾峰緱鐨処P鍦板潃
+     * @return 绗竴涓潪unknown IP鍦板潃
+     */
+    public static String getMultistageReverseProxyIp(String ip)
+    {
+        // 澶氱骇鍙嶅悜浠g悊妫�娴�
+        if (ip != null && ip.indexOf(",") > 0)
+        {
+            final String[] ips = ip.trim().split(",");
+            for (String subIp : ips)
+            {
+                if (false == isUnknown(subIp))
+                {
+                    ip = subIp;
+                    break;
+                }
+            }
+        }
+        return StringUtils.substring(ip, 0, 255);
+    }
+
+    /**
+     * 妫�娴嬬粰瀹氬瓧绗︿覆鏄惁涓烘湭鐭ワ紝澶氱敤浜庢娴婬TTP璇锋眰鐩稿叧
+     *
+     * @param checkString 琚娴嬬殑瀛楃涓�
+     * @return 鏄惁鏈煡
+     */
+    public static boolean isUnknown(String checkString)
+    {
+        return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
+    }
+
+    /**
+     * 鏄惁涓篒P
+     */
+    public static boolean isIP(String ip)
+    {
+        return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP);
+    }
+
+    /**
+     * 鏄惁涓篒P锛屾垨 *涓洪棿闅旂殑閫氶厤绗﹀湴鍧�
+     */
+    public static boolean isIpWildCard(String ip)
+    {
+        return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD);
+    }
+
+    /**
+     * 妫�娴嬪弬鏁版槸鍚﹀湪ip閫氶厤绗﹂噷
+     */
+    public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip)
+    {
+        String[] s1 = ipWildCard.split("\\.");
+        String[] s2 = ip.split("\\.");
+        boolean isMatchedSeg = true;
+        for (int i = 0; i < s1.length && !s1[i].equals("*"); i++)
+        {
+            if (!s1[i].equals(s2[i]))
+            {
+                isMatchedSeg = false;
+                break;
+            }
+        }
+        return isMatchedSeg;
+    }
+
+    /**
+     * 鏄惁涓虹壒瀹氭牸寮忓:鈥�10.10.10.1-10.10.10.99鈥濈殑ip娈靛瓧绗︿覆
+     */
+    public static boolean isIPSegment(String ipSeg)
+    {
+        return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG);
+    }
+
+    /**
+     * 鍒ゆ柇ip鏄惁鍦ㄦ寚瀹氱綉娈典腑
+     */
+    public static boolean ipIsInNetNoCheck(String iparea, String ip)
+    {
+        int idx = iparea.indexOf('-');
+        String[] sips = iparea.substring(0, idx).split("\\.");
+        String[] sipe = iparea.substring(idx + 1).split("\\.");
+        String[] sipt = ip.split("\\.");
+        long ips = 0L, ipe = 0L, ipt = 0L;
+        for (int i = 0; i < 4; ++i)
+        {
+            ips = ips << 8 | Integer.parseInt(sips[i]);
+            ipe = ipe << 8 | Integer.parseInt(sipe[i]);
+            ipt = ipt << 8 | Integer.parseInt(sipt[i]);
+        }
+        if (ips > ipe)
+        {
+            long t = ips;
+            ips = ipe;
+            ipe = t;
+        }
+        return ips <= ipt && ipt <= ipe;
+    }
+
+    /**
+     * 鏍¢獙ip鏄惁绗﹀悎杩囨护涓茶鍒�
+     * 
+     * @param filter 杩囨护IP鍒楄〃,鏀寔鍚庣紑'*'閫氶厤,鏀寔缃戞濡�:`10.10.10.1-10.10.10.99`
+     * @param ip 鏍¢獙IP鍦板潃
+     * @return boolean 缁撴灉
+     */
+    public static boolean isMatchedIp(String filter, String ip)
+    {
+        if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip))
+        {
+            return false;
+        }
+        String[] ips = filter.split(";");
+        for (String iStr : ips)
+        {
+            if (isIP(iStr) && iStr.equals(ip))
+            {
+                return true;
+            }
+            else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip))
+            {
+                return true;
+            }
+            else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/se-common/src/main/java/com/terra/common/utils/poi/ExcelHandlerAdapter.java b/se-common/src/main/java/com/terra/common/utils/poi/ExcelHandlerAdapter.java
new file mode 100644
index 0000000..eead235
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/poi/ExcelHandlerAdapter.java
@@ -0,0 +1,24 @@
+package com.terra.common.utils.poi;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Workbook;
+
+/**
+ * Excel鏁版嵁鏍煎紡澶勭悊閫傞厤鍣�
+ * 
+ * @author ruoyi
+ */
+public interface ExcelHandlerAdapter
+{
+    /**
+     * 鏍煎紡鍖�
+     * 
+     * @param value 鍗曞厓鏍兼暟鎹��
+     * @param args excel娉ㄨВargs鍙傛暟缁�
+     * @param cell 鍗曞厓鏍煎璞�
+     * @param wb 宸ヤ綔绨垮璞�
+     *
+     * @return 澶勭悊鍚庣殑鍊�
+     */
+    Object format(Object value, String[] args, Cell cell, Workbook wb);
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/poi/ExcelUtil.java b/se-common/src/main/java/com/terra/common/utils/poi/ExcelUtil.java
new file mode 100644
index 0000000..6cc107f
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/poi/ExcelUtil.java
@@ -0,0 +1,1626 @@
+package com.terra.common.utils.poi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.RegExUtils;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.DataFormat;
+import org.apache.poi.ss.usermodel.DataValidation;
+import org.apache.poi.ss.usermodel.DataValidationConstraint;
+import org.apache.poi.ss.usermodel.DataValidationHelper;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Name;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDataValidation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.terra.common.annotation.Excel;
+import com.terra.common.annotation.Excel.ColumnType;
+import com.terra.common.annotation.Excel.Type;
+import com.terra.common.annotation.Excels;
+import com.terra.common.exception.UtilException;
+import com.terra.common.text.Convert;
+import com.terra.common.utils.DateUtils;
+import com.terra.common.utils.StringUtils;
+import com.terra.common.utils.file.FileTypeUtils;
+import com.terra.common.utils.file.ImageUtils;
+import com.terra.common.utils.reflect.ReflectUtils;
+
+/**
+ * Excel鐩稿叧澶勭悊
+ *
+ * @author ruoyi
+ */
+public class ExcelUtil<T>
+{
+    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
+
+    public static final String SEPARATOR = ",";
+
+    public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
+
+    public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
+
+    /**
+     * Excel sheet鏈�澶ц鏁帮紝榛樿65536
+     */
+    public static final int sheetSize = 65536;
+
+    /**
+     * 宸ヤ綔琛ㄥ悕绉�
+     */
+    private String sheetName;
+
+    /**
+     * 瀵煎嚭绫诲瀷锛圗XPORT:瀵煎嚭鏁版嵁锛汭MPORT锛氬鍏ユā鏉匡級
+     */
+    private Type type;
+
+    /**
+     * 宸ヤ綔钖勫璞�
+     */
+    private Workbook wb;
+
+    /**
+     * 宸ヤ綔琛ㄥ璞�
+     */
+    private Sheet sheet;
+
+    /**
+     * 鏍峰紡鍒楄〃
+     */
+    private Map<String, CellStyle> styles;
+
+    /**
+     * 瀵煎叆瀵煎嚭鏁版嵁鍒楄〃
+     */
+    private List<T> list;
+
+    /**
+     * 娉ㄨВ鍒楄〃
+     */
+    private List<Object[]> fields;
+
+    /**
+     * 褰撳墠琛屽彿
+     */
+    private int rownum;
+
+    /**
+     * 鏍囬
+     */
+    private String title;
+
+    /**
+     * 鏈�澶ч珮搴�
+     */
+    private short maxHeight;
+
+    /**
+     * 鍚堝苟鍚庢渶鍚庤鏁�
+     */
+    private int subMergedLastRowNum = 0;
+
+    /**
+     * 鍚堝苟鍚庡紑濮嬭鏁�
+     */
+    private int subMergedFirstRowNum = 1;
+
+    /**
+     * 瀵硅薄鐨勫瓙鍒楄〃鏂规硶
+     */
+    private Method subMethod;
+
+    /**
+     * 瀵硅薄鐨勫瓙鍒楄〃灞炴��
+     */
+    private List<Field> subFields;
+
+    /**
+     * 缁熻鍒楄〃
+     */
+    private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
+
+    /**
+     * 瀹炰綋瀵硅薄
+     */
+    public Class<T> clazz;
+
+    /**
+     * 闇�瑕佹樉绀哄垪灞炴��
+     */
+    public String[] includeFields;
+
+    /**
+     * 闇�瑕佹帓闄ゅ垪灞炴��
+     */
+    public String[] excludeFields;
+
+    public ExcelUtil(Class<T> clazz)
+    {
+        this.clazz = clazz;
+    }
+
+    /**
+     * 浠呭湪Excel涓樉绀哄垪灞炴��
+     *
+     * @param fields 鍒楀睘鎬у悕 绀轰緥[鍗曚釜"name"/澶氫釜"id","name"]
+     */
+    public void showColumn(String... fields)
+    {
+        this.includeFields = fields;
+    }
+
+    /**
+     * 闅愯棌Excel涓垪灞炴��
+     *
+     * @param fields 鍒楀睘鎬у悕 绀轰緥[鍗曚釜"name"/澶氫釜"id","name"]
+     */
+    public void hideColumn(String... fields)
+    {
+        this.excludeFields = fields;
+    }
+
+    public void init(List<T> list, String sheetName, String title, Type type)
+    {
+        if (list == null)
+        {
+            list = new ArrayList<T>();
+        }
+        this.list = list;
+        this.sheetName = sheetName;
+        this.type = type;
+        this.title = title;
+        createExcelField();
+        createWorkbook();
+        createTitle();
+        createSubHead();
+    }
+
+    /**
+     * 鍒涘缓excel绗竴琛屾爣棰�
+     */
+    public void createTitle()
+    {
+        if (StringUtils.isNotEmpty(title))
+        {
+            int titleLastCol = this.fields.size() - 1;
+            if (isSubList())
+            {
+                titleLastCol = titleLastCol + subFields.size() - 1;
+            }
+            Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
+            titleRow.setHeightInPoints(30);
+            Cell titleCell = titleRow.createCell(0);
+            titleCell.setCellStyle(styles.get("title"));
+            titleCell.setCellValue(title);
+            sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol));
+        }
+    }
+
+    /**
+     * 鍒涘缓瀵硅薄鐨勫瓙鍒楄〃鍚嶇О
+     */
+    public void createSubHead()
+    {
+        if (isSubList())
+        {
+            Row subRow = sheet.createRow(rownum);
+            int column = 0;
+            int subFieldSize = subFields != null ? subFields.size() : 0;
+            for (Object[] objects : fields)
+            {
+                Field field = (Field) objects[0];
+                Excel attr = (Excel) objects[1];
+                if (Collection.class.isAssignableFrom(field.getType()))
+                {
+                    Cell cell = subRow.createCell(column);
+                    cell.setCellValue(attr.name());
+                    cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+                    if (subFieldSize > 1)
+                    {
+                        CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
+                        sheet.addMergedRegion(cellAddress);
+                    }
+                    column += subFieldSize;
+                }
+                else
+                {
+                    Cell cell = subRow.createCell(column++);
+                    cell.setCellValue(attr.name());
+                    cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+                }
+            }
+            rownum++;
+        }
+    }
+
+    /**
+     * 瀵筫xcel琛ㄥ崟榛樿绗竴涓储寮曞悕杞崲鎴恖ist
+     * 
+     * @param is 杈撳叆娴�
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public List<T> importExcel(InputStream is)
+    {
+        return importExcel(is, 0);
+    }
+
+    /**
+     * 瀵筫xcel琛ㄥ崟榛樿绗竴涓储寮曞悕杞崲鎴恖ist
+     * 
+     * @param is 杈撳叆娴�
+     * @param titleNum 鏍囬鍗犵敤琛屾暟
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public List<T> importExcel(InputStream is, int titleNum)
+    {
+        List<T> list = null;
+        try
+        {
+            list = importExcel(StringUtils.EMPTY, is, titleNum);
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎叆Excel寮傚父{}", e.getMessage());
+            throw new UtilException(e.getMessage());
+        }
+        finally
+        {
+            IOUtils.closeQuietly(is);
+        }
+        return list;
+    }
+
+    /**
+     * 瀵筫xcel琛ㄥ崟鎸囧畾琛ㄦ牸绱㈠紩鍚嶈浆鎹㈡垚list
+     * 
+     * @param sheetName 琛ㄦ牸绱㈠紩鍚�
+     * @param titleNum 鏍囬鍗犵敤琛屾暟
+     * @param is 杈撳叆娴�
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception
+    {
+        this.type = Type.IMPORT;
+        this.wb = WorkbookFactory.create(is);
+        List<T> list = new ArrayList<T>();
+        // 濡傛灉鎸囧畾sheet鍚�,鍒欏彇鎸囧畾sheet涓殑鍐呭 鍚﹀垯榛樿鎸囧悜绗�1涓猻heet
+        Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0);
+        if (sheet == null)
+        {
+            throw new IOException("鏂囦欢sheet涓嶅瓨鍦�");
+        }
+
+        // 鑾峰彇鏈�鍚庝竴涓潪绌鸿鐨勮涓嬫爣锛屾瘮濡傛�昏鏁颁负n锛屽垯杩斿洖鐨勪负n-1
+        int rows = sheet.getLastRowNum();
+        if (rows > 0)
+        {
+            // 瀹氫箟涓�涓猰ap鐢ㄤ簬瀛樻斁excel鍒楃殑搴忓彿鍜宖ield.
+            Map<String, Integer> cellMap = new HashMap<String, Integer>();
+            // 鑾峰彇琛ㄥご
+            Row heard = sheet.getRow(titleNum);
+            for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
+            {
+                Cell cell = heard.getCell(i);
+                if (StringUtils.isNotNull(cell))
+                {
+                    String value = this.getCellValue(heard, i).toString();
+                    cellMap.put(value, i);
+                }
+                else
+                {
+                    cellMap.put(null, i);
+                }
+            }
+            // 鏈夋暟鎹椂鎵嶅鐞� 寰楀埌绫荤殑鎵�鏈塮ield.
+            List<Object[]> fields = this.getFields();
+            Map<Integer, Object[]> fieldsMap = new HashMap<Integer, Object[]>();
+            for (Object[] objects : fields)
+            {
+                Excel attr = (Excel) objects[1];
+                Integer column = cellMap.get(attr.name());
+                if (column != null)
+                {
+                    fieldsMap.put(column, objects);
+                }
+            }
+            for (int i = titleNum + 1; i <= rows; i++)
+            {
+                // 浠庣2琛屽紑濮嬪彇鏁版嵁,榛樿绗竴琛屾槸琛ㄥご.
+                Row row = sheet.getRow(i);
+                // 鍒ゆ柇褰撳墠琛屾槸鍚︽槸绌鸿
+                if (isRowEmpty(row))
+                {
+                    continue;
+                }
+                T entity = null;
+                for (Map.Entry<Integer, Object[]> entry : fieldsMap.entrySet())
+                {
+                    Object val = this.getCellValue(row, entry.getKey());
+
+                    // 濡傛灉涓嶅瓨鍦ㄥ疄渚嬪垯鏂板缓.
+                    entity = (entity == null ? clazz.newInstance() : entity);
+                    // 浠巑ap涓緱鍒板搴斿垪鐨刦ield.
+                    Field field = (Field) entry.getValue()[0];
+                    Excel attr = (Excel) entry.getValue()[1];
+                    // 鍙栧緱绫诲瀷,骞舵牴鎹璞$被鍨嬭缃��.
+                    Class<?> fieldType = field.getType();
+                    if (String.class == fieldType)
+                    {
+                        String s = Convert.toStr(val);
+                        if (s.matches("^\\d+\\.0$"))
+                        {
+                            val = StringUtils.substringBefore(s, ".0");
+                        }
+                        else
+                        {
+                            String dateFormat = field.getAnnotation(Excel.class).dateFormat();
+                            if (StringUtils.isNotEmpty(dateFormat))
+                            {
+                                val = parseDateToStr(dateFormat, val);
+                            }
+                            else
+                            {
+                                val = Convert.toStr(val);
+                            }
+                        }
+                    }
+                    else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
+                    {
+                        val = Convert.toInt(val);
+                    }
+                    else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
+                    {
+                        val = Convert.toLong(val);
+                    }
+                    else if (Double.TYPE == fieldType || Double.class == fieldType)
+                    {
+                        val = Convert.toDouble(val);
+                    }
+                    else if (Float.TYPE == fieldType || Float.class == fieldType)
+                    {
+                        val = Convert.toFloat(val);
+                    }
+                    else if (BigDecimal.class == fieldType)
+                    {
+                        val = Convert.toBigDecimal(val);
+                    }
+                    else if (Date.class == fieldType)
+                    {
+                        if (val instanceof String)
+                        {
+                            val = DateUtils.parseDate(val);
+                        }
+                        else if (val instanceof Double)
+                        {
+                            val = DateUtil.getJavaDate((Double) val);
+                        }
+                    }
+                    else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
+                    {
+                        val = Convert.toBool(val, false);
+                    }
+                    if (StringUtils.isNotNull(fieldType))
+                    {
+                        String propertyName = field.getName();
+                        if (StringUtils.isNotEmpty(attr.targetAttr()))
+                        {
+                            propertyName = field.getName() + "." + attr.targetAttr();
+                        }
+                        if (StringUtils.isNotEmpty(attr.readConverterExp()))
+                        {
+                            val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
+                        }
+                        else if (!attr.handler().equals(ExcelHandlerAdapter.class))
+                        {
+                            val = dataFormatHandlerAdapter(val, attr, null);
+                        }
+                        ReflectUtils.invokeSetter(entity, propertyName, val);
+                    }
+                }
+                list.add(entity);
+            }
+        }
+        return list;
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     *
+     * @param response 杩斿洖鏁版嵁
+     * @param list 瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @return 缁撴灉
+     */
+    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)
+    {
+        exportExcel(response, list, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     *
+     * @param response 杩斿洖鏁版嵁
+     * @param list 瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param title 鏍囬
+     * @return 缁撴灉
+     */
+    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title)
+    {
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        this.init(list, sheetName, title, Type.EXPORT);
+        exportExcel(response);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     *
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @return 缁撴灉
+     */
+    public void importTemplateExcel(HttpServletResponse response, String sheetName)
+    {
+        importTemplateExcel(response, sheetName, StringUtils.EMPTY);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     *
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param title 鏍囬
+     * @return 缁撴灉
+     */
+    public void importTemplateExcel(HttpServletResponse response, String sheetName, String title)
+    {
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        this.init(null, sheetName, title, Type.IMPORT);
+        exportExcel(response);
+    }
+
+    /**
+     * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+     * 
+     * @return 缁撴灉
+     */
+    public void exportExcel(HttpServletResponse response)
+    {
+        try
+        {
+            writeSheet();
+            wb.write(response.getOutputStream());
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎嚭Excel寮傚父{}", e.getMessage());
+        }
+        finally
+        {
+            IOUtils.closeQuietly(wb);
+        }
+    }
+
+    /**
+     * 鍒涘缓鍐欏叆鏁版嵁鍒癝heet
+     */
+    public void writeSheet()
+    {
+        // 鍙栧嚭涓�鍏辨湁澶氬皯涓猻heet.
+        int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));
+        for (int index = 0; index < sheetNo; index++)
+        {
+            createSheet(sheetNo, index);
+
+            // 浜х敓涓�琛�
+            Row row = sheet.createRow(rownum);
+            int column = 0;
+            // 鍐欏叆鍚勪釜瀛楁鐨勫垪澶村悕绉�
+            for (Object[] os : fields)
+            {
+                Field field = (Field) os[0];
+                Excel excel = (Excel) os[1];
+                if (Collection.class.isAssignableFrom(field.getType()))
+                {
+                    for (Field subField : subFields)
+                    {
+                        Excel subExcel = subField.getAnnotation(Excel.class);
+                        this.createHeadCell(subExcel, row, column++);
+                    }
+                }
+                else
+                {
+                    this.createHeadCell(excel, row, column++);
+                }
+            }
+            if (Type.EXPORT.equals(type))
+            {
+                fillExcelData(index, row);
+                addStatisticsRow();
+            }
+        }
+    }
+
+    /**
+     * 濉厖excel鏁版嵁
+     * 
+     * @param index 搴忓彿
+     * @param row 鍗曞厓鏍艰
+     */
+    @SuppressWarnings("unchecked")
+    public void fillExcelData(int index, Row row)
+    {
+        int startNo = index * sheetSize;
+        int endNo = Math.min(startNo + sheetSize, list.size());
+        int currentRowNum = rownum + 1; // 浠庢爣棰樿鍚庡紑濮�
+
+        for (int i = startNo; i < endNo; i++)
+        {
+            row = sheet.createRow(currentRowNum);
+            T vo = (T) list.get(i);
+            int column = 0;
+            int maxSubListSize = getCurrentMaxSubListSize(vo);
+            for (Object[] os : fields)
+            {
+                Field field = (Field) os[0];
+                Excel excel = (Excel) os[1];
+                if (Collection.class.isAssignableFrom(field.getType()))
+                {
+                    try
+                    {
+                        Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
+                        if (subList != null && !subList.isEmpty())
+                        {
+                            int subIndex = 0;
+                            for (Object subVo : subList)
+                            {
+                                Row subRow = sheet.getRow(currentRowNum + subIndex);
+                                if (subRow == null)
+                                {
+                                    subRow = sheet.createRow(currentRowNum + subIndex);
+                                }
+
+                                int subColumn = column;
+                                for (Field subField : subFields)
+                                {
+                                    Excel subExcel = subField.getAnnotation(Excel.class);
+                                    addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
+                                }
+                                subIndex++;
+                            }
+                            column += subFields.size();
+                        }
+                    }
+                    catch (Exception e)
+                    {
+                        log.error("濉厖闆嗗悎鏁版嵁澶辫触", e);
+                    }
+                }
+                else
+                {
+                    // 鍒涘缓鍗曞厓鏍煎苟璁剧疆鍊�
+                    addCell(excel, row, vo, field, column);
+                    if (maxSubListSize > 1 && excel.needMerge())
+                    {
+                        sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));
+                    }
+                    column++;
+                }
+            }
+            currentRowNum += maxSubListSize;
+        }
+    }
+
+    /**
+     * 鑾峰彇瀛愬垪琛ㄦ渶澶ф暟
+     */
+    private int getCurrentMaxSubListSize(T vo)
+    {
+        int maxSubListSize = 1;
+        for (Object[] os : fields)
+        {
+            Field field = (Field) os[0];
+            if (Collection.class.isAssignableFrom(field.getType()))
+            {
+                try
+                {
+                    Collection<?> subList = (Collection<?>) getTargetValue(vo, field, (Excel) os[1]);
+                    if (subList != null && !subList.isEmpty())
+                    {
+                        maxSubListSize = Math.max(maxSubListSize, subList.size());
+                    }
+                }
+                catch (Exception e)
+                {
+                    log.error("鑾峰彇闆嗗悎澶у皬澶辫触", e);
+                }
+            }
+        }
+        return maxSubListSize;
+    }
+
+    /**
+     * 鍒涘缓琛ㄦ牸鏍峰紡
+     * 
+     * @param wb 宸ヤ綔钖勫璞�
+     * @return 鏍峰紡鍒楄〃
+     */
+    private Map<String, CellStyle> createStyles(Workbook wb)
+    {
+        // 鍐欏叆鍚勬潯璁板綍,姣忔潯璁板綍瀵瑰簲excel琛ㄤ腑鐨勪竴琛�
+        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+        CellStyle style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        Font titleFont = wb.createFont();
+        titleFont.setFontName("Arial");
+        titleFont.setFontHeightInPoints((short) 16);
+        titleFont.setBold(true);
+        style.setFont(titleFont);
+        DataFormat dataFormat = wb.createDataFormat();
+        style.setDataFormat(dataFormat.getFormat("@"));
+        styles.put("title", style);
+
+        style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderTop(BorderStyle.THIN);
+        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        Font dataFont = wb.createFont();
+        dataFont.setFontName("Arial");
+        dataFont.setFontHeightInPoints((short) 10);
+        style.setFont(dataFont);
+        styles.put("data", style);
+
+        style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setDataFormat(dataFormat.getFormat("######0.00"));
+        Font totalFont = wb.createFont();
+        totalFont.setFontName("Arial");
+        totalFont.setFontHeightInPoints((short) 10);
+        style.setFont(totalFont);
+        styles.put("total", style);
+
+        styles.putAll(annotationHeaderStyles(wb, styles));
+
+        styles.putAll(annotationDataStyles(wb));
+
+        return styles;
+    }
+
+    /**
+     * 鏍规嵁Excel娉ㄨВ鍒涘缓琛ㄦ牸澶存牱寮�
+     * 
+     * @param wb 宸ヤ綔钖勫璞�
+     * @return 鑷畾涔夋牱寮忓垪琛�
+     */
+    private Map<String, CellStyle> annotationHeaderStyles(Workbook wb, Map<String, CellStyle> styles)
+    {
+        Map<String, CellStyle> headerStyles = new HashMap<String, CellStyle>();
+        for (Object[] os : fields)
+        {
+            Excel excel = (Excel) os[1];
+            String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor());
+            if (!headerStyles.containsKey(key))
+            {
+                CellStyle style = wb.createCellStyle();
+                style.cloneStyleFrom(styles.get("data"));
+                style.setAlignment(HorizontalAlignment.CENTER);
+                style.setVerticalAlignment(VerticalAlignment.CENTER);
+                style.setFillForegroundColor(excel.headerBackgroundColor().index);
+                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+                Font headerFont = wb.createFont();
+                headerFont.setFontName("Arial");
+                headerFont.setFontHeightInPoints((short) 10);
+                headerFont.setBold(true);
+                headerFont.setColor(excel.headerColor().index);
+                style.setFont(headerFont);
+                // 璁剧疆琛ㄦ牸澶村崟鍏冩牸鏂囨湰褰㈠紡
+                DataFormat dataFormat = wb.createDataFormat();
+                style.setDataFormat(dataFormat.getFormat("@"));
+                headerStyles.put(key, style);
+            }
+        }
+        return headerStyles;
+    }
+
+    /**
+     * 鏍规嵁Excel娉ㄨВ鍒涘缓琛ㄦ牸鍒楁牱寮�
+     * 
+     * @param wb 宸ヤ綔钖勫璞�
+     * @return 鑷畾涔夋牱寮忓垪琛�
+     */
+    private Map<String, CellStyle> annotationDataStyles(Workbook wb)
+    {
+        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+        for (Object[] os : fields)
+        {
+            Field field = (Field) os[0];
+            Excel excel = (Excel) os[1];
+            if (Collection.class.isAssignableFrom(field.getType()))
+            {
+                ParameterizedType pt = (ParameterizedType) field.getGenericType();
+                Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
+                List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
+                for (Field subField : subFields)
+                {
+                    Excel subExcel = subField.getAnnotation(Excel.class);
+                    annotationDataStyles(styles, subField, subExcel);
+                }
+            }
+            else
+            {
+                annotationDataStyles(styles, field, excel);
+            }
+        }
+        return styles;
+    }
+
+    /**
+     * 鏍规嵁Excel娉ㄨВ鍒涘缓琛ㄦ牸鍒楁牱寮�
+     * 
+     * @param styles 鑷畾涔夋牱寮忓垪琛�
+     * @param field  灞炴�у垪淇℃伅
+     * @param excel  娉ㄨВ淇℃伅
+     */
+    public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
+    {
+        String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText());
+        if (!styles.containsKey(key))
+        {
+            CellStyle style = wb.createCellStyle();
+            style.setAlignment(excel.align());
+            style.setVerticalAlignment(VerticalAlignment.CENTER);
+            style.setBorderRight(BorderStyle.THIN);
+            style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+            style.setBorderLeft(BorderStyle.THIN);
+            style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+            style.setBorderTop(BorderStyle.THIN);
+            style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+            style.setBorderBottom(BorderStyle.THIN);
+            style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+            style.setFillForegroundColor(excel.backgroundColor().getIndex());
+            style.setWrapText(excel.wrapText());
+            Font dataFont = wb.createFont();
+            dataFont.setFontName("Arial");
+            dataFont.setFontHeightInPoints((short) 10);
+            dataFont.setColor(excel.color().index);
+            style.setFont(dataFont);
+            if (ColumnType.TEXT == excel.cellType())
+            {
+                DataFormat dataFormat = wb.createDataFormat();
+                style.setDataFormat(dataFormat.getFormat("@"));
+            }
+            styles.put(key, style);
+        }
+    }
+
+    /**
+     * 鍒涘缓鍗曞厓鏍�
+     */
+    public Cell createHeadCell(Excel attr, Row row, int column)
+    {
+        // 鍒涘缓鍒�
+        Cell cell = row.createCell(column);
+        // 鍐欏叆鍒椾俊鎭�
+        cell.setCellValue(attr.name());
+        setDataValidation(attr, row, column);
+        cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+        if (isSubList())
+        {
+            // 濉厖榛樿鏍峰紡锛岄槻姝㈠悎骞跺崟鍏冩牸鏍峰紡澶辨晥
+            sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
+            if (attr.needMerge())
+            {
+                sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
+            }
+        }
+        return cell;
+    }
+
+    /**
+     * 璁剧疆鍗曞厓鏍间俊鎭�
+     * 
+     * @param value 鍗曞厓鏍煎��
+     * @param attr 娉ㄨВ鐩稿叧
+     * @param cell 鍗曞厓鏍间俊鎭�
+     */
+    public void setCellVo(Object value, Excel attr, Cell cell)
+    {
+        if (ColumnType.STRING == attr.cellType() || ColumnType.TEXT == attr.cellType())
+        {
+            String cellValue = Convert.toStr(value);
+            // 瀵逛簬浠讳綍浠ヨ〃杈惧紡瑙﹀彂瀛楃 =-+@寮�澶寸殑鍗曞厓鏍硷紝鐩存帴浣跨敤tab瀛楃浣滀负鍓嶇紑锛岄槻姝SV娉ㄥ叆銆�
+            if (StringUtils.startsWithAny(cellValue, FORMULA_STR))
+            {
+                cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0");
+            }
+            if (value instanceof Collection && StringUtils.equals("[]", cellValue))
+            {
+                cellValue = StringUtils.EMPTY;
+            }
+            cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
+        }
+        else if (ColumnType.NUMERIC == attr.cellType())
+        {
+            if (StringUtils.isNotNull(value))
+            {
+                cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
+            }
+        }
+        else if (ColumnType.IMAGE == attr.cellType())
+        {
+            ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
+            String imagePath = Convert.toStr(value);
+            if (StringUtils.isNotEmpty(imagePath))
+            {
+                byte[] data = ImageUtils.getImage(imagePath);
+                getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
+                        cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
+            }
+        }
+    }
+
+    /**
+     * 鑾峰彇鐢诲竷
+     */
+    public static Drawing<?> getDrawingPatriarch(Sheet sheet)
+    {
+        if (sheet.getDrawingPatriarch() == null)
+        {
+            sheet.createDrawingPatriarch();
+        }
+        return sheet.getDrawingPatriarch();
+    }
+
+    /**
+     * 鑾峰彇鍥剧墖绫诲瀷,璁剧疆鍥剧墖鎻掑叆绫诲瀷
+     */
+    public int getImageType(byte[] value)
+    {
+        String type = FileTypeUtils.getFileExtendName(value);
+        if ("JPG".equalsIgnoreCase(type))
+        {
+            return Workbook.PICTURE_TYPE_JPEG;
+        }
+        else if ("PNG".equalsIgnoreCase(type))
+        {
+            return Workbook.PICTURE_TYPE_PNG;
+        }
+        return Workbook.PICTURE_TYPE_JPEG;
+    }
+
+    /**
+     * 鍒涘缓琛ㄦ牸鏍峰紡
+     */
+    public void setDataValidation(Excel attr, Row row, int column)
+    {
+        if (attr.name().indexOf("娉細") >= 0)
+        {
+            sheet.setColumnWidth(column, 6000);
+        }
+        else
+        {
+            // 璁剧疆鍒楀
+            sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
+        }
+        if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
+        {
+            if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255)
+            {
+                // 濡傛灉涓嬫媺鏁板ぇ浜�15鎴栧瓧绗︿覆闀垮害澶т簬255锛屽垯浣跨敤涓�涓柊sheet瀛樺偍锛岄伩鍏嶇敓鎴愮殑妯℃澘涓嬫媺鍊艰幏鍙栦笉鍒�
+                setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
+            }
+            else
+            {
+                // 鎻愮ず淇℃伅鎴栧彧鑳介�夋嫨涓嶈兘杈撳叆鐨勫垪鍐呭.
+                setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
+            }
+        }
+    }
+
+    /**
+     * 娣诲姞鍗曞厓鏍�
+     */
+    public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
+    {
+        Cell cell = null;
+        try
+        {
+            // 璁剧疆琛岄珮
+            row.setHeight(maxHeight);
+            // 鏍规嵁Excel涓缃儏鍐靛喅瀹氭槸鍚﹀鍑�,鏈変簺鎯呭喌闇�瑕佷繚鎸佷负绌�,甯屾湜鐢ㄦ埛濉啓杩欎竴鍒�.
+            if (attr.isExport())
+            {
+                // 鍒涘缓cell
+                cell = row.createCell(column);
+                if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
+                {
+                    if (subMergedLastRowNum >= subMergedFirstRowNum)
+                    {
+                        sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
+                    }
+                }
+                cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
+
+                // 鐢ㄤ簬璇诲彇瀵硅薄涓殑灞炴��
+                Object value = getTargetValue(vo, field, attr);
+                String dateFormat = attr.dateFormat();
+                String readConverterExp = attr.readConverterExp();
+                String separator = attr.separator();
+                if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
+                {
+                    cell.getCellStyle().setDataFormat(this.wb.getCreationHelper().createDataFormat().getFormat(dateFormat));
+                    cell.setCellValue(parseDateToStr(dateFormat, value));
+                }
+                else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
+                {
+                    cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
+                }
+                else if (value instanceof BigDecimal && -1 != attr.scale())
+                {
+                    cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
+                }
+                else if (!attr.handler().equals(ExcelHandlerAdapter.class))
+                {
+                    cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell));
+                }
+                else
+                {
+                    // 璁剧疆鍒楃被鍨�
+                    setCellVo(value, attr, cell);
+                }
+                addStatisticsData(column, Convert.toStr(value), attr);
+            }
+        }
+        catch (Exception e)
+        {
+            log.error("瀵煎嚭Excel澶辫触{}", e);
+        }
+        return cell;
+    }
+
+    /**
+     * 璁剧疆 POI XSSFSheet 鍗曞厓鏍兼彁绀烘垨閫夋嫨妗�
+     * 
+     * @param sheet 琛ㄥ崟
+     * @param textlist 涓嬫媺妗嗘樉绀虹殑鍐呭
+     * @param promptContent 鎻愮ず鍐呭
+     * @param firstRow 寮�濮嬭
+     * @param endRow 缁撴潫琛�
+     * @param firstCol 寮�濮嬪垪
+     * @param endCol 缁撴潫鍒�
+     */
+    public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow,
+            int firstCol, int endCol)
+    {
+        DataValidationHelper helper = sheet.getDataValidationHelper();
+        DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1");
+        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
+        DataValidation dataValidation = helper.createValidation(constraint, regions);
+        if (StringUtils.isNotEmpty(promptContent))
+        {
+            // 濡傛灉璁剧疆浜嗘彁绀轰俊鎭垯榧犳爣鏀句笂鍘绘彁绀�
+            dataValidation.createPromptBox("", promptContent);
+            dataValidation.setShowPromptBox(true);
+        }
+        // 澶勭悊Excel鍏煎鎬ч棶棰�
+        if (dataValidation instanceof XSSFDataValidation)
+        {
+            dataValidation.setSuppressDropDownArrow(true);
+            dataValidation.setShowErrorBox(true);
+        }
+        else
+        {
+            dataValidation.setSuppressDropDownArrow(false);
+        }
+        sheet.addValidationData(dataValidation);
+    }
+
+    /**
+     * 璁剧疆鏌愪簺鍒楃殑鍊煎彧鑳借緭鍏ラ鍒剁殑鏁版嵁,鏄剧ず涓嬫媺妗嗭紙鍏煎瓒呭嚭涓�瀹氭暟閲忕殑涓嬫媺妗嗭級.
+     * 
+     * @param sheet 瑕佽缃殑sheet.
+     * @param textlist 涓嬫媺妗嗘樉绀虹殑鍐呭
+     * @param promptContent 鎻愮ず鍐呭
+     * @param firstRow 寮�濮嬭
+     * @param endRow 缁撴潫琛�
+     * @param firstCol 寮�濮嬪垪
+     * @param endCol 缁撴潫鍒�
+     */
+    public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
+    {
+        String hideSheetName = "combo_" + firstCol + "_" + endCol;
+        Sheet hideSheet = wb.createSheet(hideSheetName); // 鐢ㄤ簬瀛樺偍 涓嬫媺鑿滃崟鏁版嵁
+        for (int i = 0; i < textlist.length; i++)
+        {
+            hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
+        }
+        // 鍒涘缓鍚嶇О锛屽彲琚叾浠栧崟鍏冩牸寮曠敤
+        Name name = wb.createName();
+        name.setNameName(hideSheetName + "_data");
+        name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
+        DataValidationHelper helper = sheet.getDataValidationHelper();
+        // 鍔犺浇涓嬫媺鍒楄〃鍐呭
+        DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
+        // 璁剧疆鏁版嵁鏈夋晥鎬у姞杞藉湪鍝釜鍗曞厓鏍间笂,鍥涗釜鍙傛暟鍒嗗埆鏄細璧峰琛屻�佺粓姝㈣銆佽捣濮嬪垪銆佺粓姝㈠垪
+        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
+        // 鏁版嵁鏈夋晥鎬у璞�
+        DataValidation dataValidation = helper.createValidation(constraint, regions);
+        if (StringUtils.isNotEmpty(promptContent))
+        {
+            // 濡傛灉璁剧疆浜嗘彁绀轰俊鎭垯榧犳爣鏀句笂鍘绘彁绀�
+            dataValidation.createPromptBox("", promptContent);
+            dataValidation.setShowPromptBox(true);
+        }
+        // 澶勭悊Excel鍏煎鎬ч棶棰�
+        if (dataValidation instanceof XSSFDataValidation)
+        {
+            dataValidation.setSuppressDropDownArrow(true);
+            dataValidation.setShowErrorBox(true);
+        }
+        else
+        {
+            dataValidation.setSuppressDropDownArrow(false);
+        }
+
+        sheet.addValidationData(dataValidation);
+        // 璁剧疆hiddenSheet闅愯棌
+        wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
+    }
+
+    /**
+     * 瑙f瀽瀵煎嚭鍊� 0=鐢�,1=濂�,2=鏈煡
+     * 
+     * @param propertyValue 鍙傛暟鍊�
+     * @param converterExp 缈昏瘧娉ㄨВ
+     * @param separator 鍒嗛殧绗�
+     * @return 瑙f瀽鍚庡��
+     */
+    public static String convertByExp(String propertyValue, String converterExp, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        String[] convertSource = converterExp.split(SEPARATOR);
+        for (String item : convertSource)
+        {
+            String[] itemArray = item.split("=");
+            if (StringUtils.containsAny(propertyValue, separator))
+            {
+                for (String value : propertyValue.split(separator))
+                {
+                    if (itemArray[0].equals(value))
+                    {
+                        propertyString.append(itemArray[1] + separator);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                if (itemArray[0].equals(propertyValue))
+                {
+                    return itemArray[1];
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 鍙嶅悜瑙f瀽鍊� 鐢�=0,濂�=1,鏈煡=2
+     * 
+     * @param propertyValue 鍙傛暟鍊�
+     * @param converterExp 缈昏瘧娉ㄨВ
+     * @param separator 鍒嗛殧绗�
+     * @return 瑙f瀽鍚庡��
+     */
+    public static String reverseByExp(String propertyValue, String converterExp, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        String[] convertSource = converterExp.split(SEPARATOR);
+        for (String item : convertSource)
+        {
+            String[] itemArray = item.split("=");
+            if (StringUtils.containsAny(propertyValue, separator))
+            {
+                for (String value : propertyValue.split(separator))
+                {
+                    if (itemArray[1].equals(value))
+                    {
+                        propertyString.append(itemArray[0] + separator);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                if (itemArray[1].equals(propertyValue))
+                {
+                    return itemArray[0];
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 鏁版嵁澶勭悊鍣�
+     *
+     * @param value 鏁版嵁鍊�
+     * @param excel 鏁版嵁娉ㄨВ
+     * @return
+     */
+    public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell)
+    {
+        try
+        {
+            Object instance = excel.handler().newInstance();
+            Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
+            value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
+        }
+        catch (Exception e)
+        {
+            log.error("涓嶈兘鏍煎紡鍖栨暟鎹� " + excel.handler(), e.getMessage());
+        }
+        return Convert.toStr(value);
+    }
+
+    /**
+     * 鍚堣缁熻淇℃伅
+     */
+    private void addStatisticsData(Integer index, String text, Excel entity)
+    {
+        if (entity != null && entity.isStatistics())
+        {
+            Double temp = 0D;
+            if (!statistics.containsKey(index))
+            {
+                statistics.put(index, temp);
+            }
+            try
+            {
+                temp = Double.valueOf(text);
+            }
+            catch (NumberFormatException e)
+            {
+            }
+            statistics.put(index, statistics.get(index) + temp);
+        }
+    }
+
+    /**
+     * 鍒涘缓缁熻琛�
+     */
+    public void addStatisticsRow()
+    {
+        if (statistics.size() > 0)
+        {
+            Row row = sheet.createRow(sheet.getLastRowNum() + 1);
+            Set<Integer> keys = statistics.keySet();
+            Cell cell = row.createCell(0);
+            cell.setCellStyle(styles.get("total"));
+            cell.setCellValue("鍚堣");
+
+            for (Integer key : keys)
+            {
+                cell = row.createCell(key);
+                cell.setCellStyle(styles.get("total"));
+                cell.setCellValue(statistics.get(key));
+            }
+            statistics.clear();
+        }
+    }
+
+    /**
+     * 鑾峰彇bean涓殑灞炴�у��
+     *
+     * @param vo 瀹炰綋瀵硅薄
+     * @param field 瀛楁
+     * @param excel 娉ㄨВ
+     * @return 鏈�缁堢殑灞炴�у��
+     * @throws Exception
+     */
+    private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
+    {
+        field.setAccessible(true);
+        Object o = field.get(vo);
+        if (StringUtils.isNotEmpty(excel.targetAttr()))
+        {
+            String target = excel.targetAttr();
+            if (target.contains("."))
+            {
+                String[] targets = target.split("[.]");
+                for (String name : targets)
+                {
+                    o = getValue(o, name);
+                }
+            }
+            else
+            {
+                o = getValue(o, target);
+            }
+        }
+        return o;
+    }
+
+    /**
+     * 浠ョ被鐨勫睘鎬х殑get鏂规硶鏂规硶褰㈠紡鑾峰彇鍊�
+     *
+     * @param o
+     * @param name
+     * @return value
+     * @throws Exception
+     */
+    private Object getValue(Object o, String name) throws Exception
+    {
+        if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
+        {
+            Class<?> clazz = o.getClass();
+            Field field = clazz.getDeclaredField(name);
+            field.setAccessible(true);
+            o = field.get(o);
+        }
+        return o;
+    }
+
+    /**
+     * 寰楀埌鎵�鏈夊畾涔夊瓧娈�
+     */
+    private void createExcelField()
+    {
+        this.fields = getFields();
+        this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
+        this.maxHeight = getRowHeight();
+    }
+
+    /**
+     * 鑾峰彇瀛楁娉ㄨВ淇℃伅
+     */
+    public List<Object[]> getFields()
+    {
+        List<Object[]> fields = new ArrayList<Object[]>();
+        List<Field> tempFields = new ArrayList<>();
+        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
+        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+        if (StringUtils.isNotEmpty(includeFields))
+        {
+            for (Field field : tempFields)
+            {
+                if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class))
+                {
+                    addField(fields, field);
+                }
+            }
+        }
+        else if (StringUtils.isNotEmpty(excludeFields))
+        {
+            for (Field field : tempFields)
+            {
+                if (!ArrayUtils.contains(this.excludeFields, field.getName()))
+                {
+                    addField(fields, field);
+                }
+            }
+        }
+        else
+        {
+            for (Field field : tempFields)
+            {
+                addField(fields, field);
+            }
+        }
+        return fields;
+    }
+
+    /**
+     * 娣诲姞瀛楁淇℃伅
+     */
+    public void addField(List<Object[]> fields, Field field)
+    {
+        // 鍗曟敞瑙�
+        if (field.isAnnotationPresent(Excel.class))
+        {
+            Excel attr = field.getAnnotation(Excel.class);
+            if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
+            {
+                fields.add(new Object[] { field, attr });
+            }
+            if (Collection.class.isAssignableFrom(field.getType()))
+            {
+                subMethod = getSubMethod(field.getName(), clazz);
+                ParameterizedType pt = (ParameterizedType) field.getGenericType();
+                Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
+                this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
+            }
+        }
+
+        // 澶氭敞瑙�
+        if (field.isAnnotationPresent(Excels.class))
+        {
+            Excels attrs = field.getAnnotation(Excels.class);
+            Excel[] excels = attrs.value();
+            for (Excel attr : excels)
+            {
+                if (StringUtils.isNotEmpty(includeFields))
+                {
+                    if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr())
+                            && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
+                    {
+                        fields.add(new Object[] { field, attr });
+                    }
+                }
+                else
+                {
+                    if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
+                            && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
+                    {
+                        fields.add(new Object[] { field, attr });
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 鏍规嵁娉ㄨВ鑾峰彇鏈�澶ц楂�
+     */
+    public short getRowHeight()
+    {
+        double maxHeight = 0;
+        for (Object[] os : this.fields)
+        {
+            Excel excel = (Excel) os[1];
+            maxHeight = Math.max(maxHeight, excel.height());
+        }
+        return (short) (maxHeight * 20);
+    }
+
+    /**
+     * 鍒涘缓涓�涓伐浣滅翱
+     */
+    public void createWorkbook()
+    {
+        this.wb = new SXSSFWorkbook(500);
+        this.sheet = wb.createSheet();
+        wb.setSheetName(0, sheetName);
+        this.styles = createStyles(wb);
+    }
+
+    /**
+     * 鍒涘缓宸ヤ綔琛�
+     * 
+     * @param sheetNo sheet鏁伴噺
+     * @param index 搴忓彿
+     */
+    public void createSheet(int sheetNo, int index)
+    {
+        // 璁剧疆宸ヤ綔琛ㄧ殑鍚嶇О.
+        if (sheetNo > 1 && index > 0)
+        {
+            this.sheet = wb.createSheet();
+            this.createTitle();
+            wb.setSheetName(index, sheetName + index);
+        }
+    }
+
+    /**
+     * 鑾峰彇鍗曞厓鏍煎��
+     * 
+     * @param row 鑾峰彇鐨勮
+     * @param column 鑾峰彇鍗曞厓鏍煎垪鍙�
+     * @return 鍗曞厓鏍煎��
+     */
+    public Object getCellValue(Row row, int column)
+    {
+        if (row == null)
+        {
+            return row;
+        }
+        Object val = "";
+        try
+        {
+            Cell cell = row.getCell(column);
+            if (StringUtils.isNotNull(cell))
+            {
+                if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
+                {
+                    val = cell.getNumericCellValue();
+                    if (DateUtil.isCellDateFormatted(cell))
+                    {
+                        val = DateUtil.getJavaDate((Double) val); // POI Excel 鏃ユ湡鏍煎紡杞崲
+                    }
+                    else
+                    {
+                        if ((Double) val % 1 != 0)
+                        {
+                            val = new BigDecimal(val.toString());
+                        }
+                        else
+                        {
+                            val = new DecimalFormat("0").format(val);
+                        }
+                    }
+                }
+                else if (cell.getCellType() == CellType.STRING)
+                {
+                    val = cell.getStringCellValue();
+                }
+                else if (cell.getCellType() == CellType.BOOLEAN)
+                {
+                    val = cell.getBooleanCellValue();
+                }
+                else if (cell.getCellType() == CellType.ERROR)
+                {
+                    val = cell.getErrorCellValue();
+                }
+
+            }
+        }
+        catch (Exception e)
+        {
+            return val;
+        }
+        return val;
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鏄┖琛�
+     * 
+     * @param row 鍒ゆ柇鐨勮
+     * @return
+     */
+    private boolean isRowEmpty(Row row)
+    {
+        if (row == null)
+        {
+            return true;
+        }
+        for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++)
+        {
+            Cell cell = row.getCell(i);
+            if (cell != null && cell.getCellType() != CellType.BLANK)
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 鏍煎紡鍖栦笉鍚岀被鍨嬬殑鏃ユ湡瀵硅薄
+     * 
+     * @param dateFormat 鏃ユ湡鏍煎紡
+     * @param val 琚牸寮忓寲鐨勬棩鏈熷璞�
+     * @return 鏍煎紡鍖栧悗鐨勬棩鏈熷瓧绗�
+     */
+    public String parseDateToStr(String dateFormat, Object val)
+    {
+        if (val == null)
+        {
+            return "";
+        }
+        String str;
+        if (val instanceof Date)
+        {
+            str = DateUtils.parseDateToStr(dateFormat, (Date) val);
+        }
+        else if (val instanceof LocalDateTime)
+        {
+            str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val));
+        }
+        else if (val instanceof LocalDate)
+        {
+            str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val));
+        }
+        else
+        {
+            str = val.toString();
+        }
+        return str;
+    }
+
+    /**
+     * 鏄惁鏈夊璞$殑瀛愬垪琛�
+     */
+    public boolean isSubList()
+    {
+        return StringUtils.isNotNull(subFields) && subFields.size() > 0;
+    }
+
+    /**
+     * 鏄惁鏈夊璞$殑瀛愬垪琛紝闆嗗悎涓嶄负绌�
+     */
+    public boolean isSubListValue(T vo)
+    {
+        return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
+    }
+
+    /**
+     * 鑾峰彇闆嗗悎鐨勫��
+     */
+    public Collection<?> getListCellValue(Object obj)
+    {
+        Object value;
+        try
+        {
+            value = subMethod.invoke(obj, new Object[] {});
+        }
+        catch (Exception e)
+        {
+            return new ArrayList<Object>();
+        }
+        return (Collection<?>) value;
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄鐨勫瓙鍒楄〃鏂规硶
+     * 
+     * @param name 鍚嶇О
+     * @param pojoClass 绫诲璞�
+     * @return 瀛愬垪琛ㄦ柟娉�
+     */
+    public Method getSubMethod(String name, Class<?> pojoClass)
+    {
+        StringBuffer getMethodName = new StringBuffer("get");
+        getMethodName.append(name.substring(0, 1).toUpperCase());
+        getMethodName.append(name.substring(1));
+        Method method = null;
+        try
+        {
+            method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
+        }
+        catch (Exception e)
+        {
+            log.error("鑾峰彇瀵硅薄寮傚父{}", e.getMessage());
+        }
+        return method;
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/reflect/ReflectUtils.java b/se-common/src/main/java/com/terra/common/utils/reflect/ReflectUtils.java
new file mode 100644
index 0000000..5c705c3
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/reflect/ReflectUtils.java
@@ -0,0 +1,410 @@
+package com.terra.common.utils.reflect;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Date;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.terra.common.text.Convert;
+import com.terra.common.utils.DateUtils;
+
+/**
+ * 鍙嶅皠宸ュ叿绫�. 鎻愪緵璋冪敤getter/setter鏂规硶, 璁块棶绉佹湁鍙橀噺, 璋冪敤绉佹湁鏂规硶, 鑾峰彇娉涘瀷绫诲瀷Class, 琚獳OP杩囩殑鐪熷疄绫荤瓑宸ュ叿鍑芥暟.
+ * 
+ * @author ruoyi
+ */
+@SuppressWarnings("rawtypes")
+public class ReflectUtils
+{
+    private static final String SETTER_PREFIX = "set";
+
+    private static final String GETTER_PREFIX = "get";
+
+    private static final String CGLIB_CLASS_SEPARATOR = "$$";
+
+    private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
+
+    /**
+     * 璋冪敤Getter鏂规硶.
+     * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeGetter(Object obj, String propertyName)
+    {
+        Object object = obj;
+        for (String name : StringUtils.split(propertyName, "."))
+        {
+            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
+            object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+        }
+        return (E) object;
+    }
+
+    /**
+     * 璋冪敤Setter鏂规硶, 浠呭尮閰嶆柟娉曞悕銆�
+     * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
+     */
+    public static <E> void invokeSetter(Object obj, String propertyName, E value)
+    {
+        Object object = obj;
+        String[] names = StringUtils.split(propertyName, ".");
+        for (int i = 0; i < names.length; i++)
+        {
+            if (i < names.length - 1)
+            {
+                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
+                object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+            }
+            else
+            {
+                String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
+                invokeMethodByName(object, setterMethodName, new Object[] { value });
+            }
+        }
+    }
+
+    /**
+     * 鐩存帴璇诲彇瀵硅薄灞炴�у��, 鏃犺private/protected淇グ绗�, 涓嶇粡杩噂etter鍑芥暟.
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E getFieldValue(final Object obj, final String fieldName)
+    {
+        Field field = getAccessibleField(obj, fieldName);
+        if (field == null)
+        {
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+            return null;
+        }
+        E result = null;
+        try
+        {
+            result = (E) field.get(obj);
+        }
+        catch (IllegalAccessException e)
+        {
+            logger.error("涓嶅彲鑳芥姏鍑虹殑寮傚父{}", e.getMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 鐩存帴璁剧疆瀵硅薄灞炴�у��, 鏃犺private/protected淇グ绗�, 涓嶇粡杩噑etter鍑芥暟.
+     */
+    public static <E> void setFieldValue(final Object obj, final String fieldName, final E value)
+    {
+        Field field = getAccessibleField(obj, fieldName);
+        if (field == null)
+        {
+            // throw new IllegalArgumentException("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+            return;
+        }
+        try
+        {
+            field.set(obj, value);
+        }
+        catch (IllegalAccessException e)
+        {
+            logger.error("涓嶅彲鑳芥姏鍑虹殑寮傚父: {}", e.getMessage());
+        }
+    }
+
+    /**
+     * 鐩存帴璋冪敤瀵硅薄鏂规硶, 鏃犺private/protected淇グ绗�.
+     * 鐢ㄤ簬涓�娆℃�ц皟鐢ㄧ殑鎯呭喌锛屽惁鍒欏簲浣跨敤getAccessibleMethod()鍑芥暟鑾峰緱Method鍚庡弽澶嶈皟鐢�.
+     * 鍚屾椂鍖归厤鏂规硶鍚�+鍙傛暟绫诲瀷锛�
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
+            final Object[] args)
+    {
+        if (obj == null || methodName == null)
+        {
+            return null;
+        }
+        Method method = getAccessibleMethod(obj, methodName, parameterTypes);
+        if (method == null)
+        {
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + methodName + "] 鏂规硶 ");
+            return null;
+        }
+        try
+        {
+            return (E) method.invoke(obj, args);
+        }
+        catch (Exception e)
+        {
+            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
+            throw convertReflectionExceptionToUnchecked(msg, e);
+        }
+    }
+
+    /**
+     * 鐩存帴璋冪敤瀵硅薄鏂规硶, 鏃犺private/protected淇グ绗︼紝
+     * 鐢ㄤ簬涓�娆℃�ц皟鐢ㄧ殑鎯呭喌锛屽惁鍒欏簲浣跨敤getAccessibleMethodByName()鍑芥暟鑾峰緱Method鍚庡弽澶嶈皟鐢�.
+     * 鍙尮閰嶅嚱鏁板悕锛屽鏋滄湁澶氫釜鍚屽悕鍑芥暟璋冪敤绗竴涓��
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args)
+    {
+        Method method = getAccessibleMethodByName(obj, methodName, args.length);
+        if (method == null)
+        {
+            // 濡傛灉涓虹┖涓嶆姤閿欙紝鐩存帴杩斿洖绌恒��
+            logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + methodName + "] 鏂规硶 ");
+            return null;
+        }
+        try
+        {
+            // 绫诲瀷杞崲锛堝皢鍙傛暟鏁版嵁绫诲瀷杞崲涓虹洰鏍囨柟娉曞弬鏁扮被鍨嬶級
+            Class<?>[] cs = method.getParameterTypes();
+            for (int i = 0; i < cs.length; i++)
+            {
+                if (args[i] != null && !args[i].getClass().equals(cs[i]))
+                {
+                    if (cs[i] == String.class)
+                    {
+                        args[i] = Convert.toStr(args[i]);
+                        if (StringUtils.endsWith((String) args[i], ".0"))
+                        {
+                            args[i] = StringUtils.substringBefore((String) args[i], ".0");
+                        }
+                    }
+                    else if (cs[i] == Integer.class)
+                    {
+                        args[i] = Convert.toInt(args[i]);
+                    }
+                    else if (cs[i] == Long.class)
+                    {
+                        args[i] = Convert.toLong(args[i]);
+                    }
+                    else if (cs[i] == Double.class)
+                    {
+                        args[i] = Convert.toDouble(args[i]);
+                    }
+                    else if (cs[i] == Float.class)
+                    {
+                        args[i] = Convert.toFloat(args[i]);
+                    }
+                    else if (cs[i] == Date.class)
+                    {
+                        if (args[i] instanceof String)
+                        {
+                            args[i] = DateUtils.parseDate(args[i]);
+                        }
+                        else
+                        {
+                            args[i] = DateUtil.getJavaDate((Double) args[i]);
+                        }
+                    }
+                    else if (cs[i] == boolean.class || cs[i] == Boolean.class)
+                    {
+                        args[i] = Convert.toBool(args[i]);
+                    }
+                }
+            }
+            return (E) method.invoke(obj, args);
+        }
+        catch (Exception e)
+        {
+            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
+            throw convertReflectionExceptionToUnchecked(msg, e);
+        }
+    }
+
+    /**
+     * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredField, 骞跺己鍒惰缃负鍙闂�.
+     * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+     */
+    public static Field getAccessibleField(final Object obj, final String fieldName)
+    {
+        // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(fieldName, "fieldName can't be blank");
+        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
+        {
+            try
+            {
+                Field field = superClass.getDeclaredField(fieldName);
+                makeAccessible(field);
+                return field;
+            }
+            catch (NoSuchFieldException e)
+            {
+                continue;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredMethod,骞跺己鍒惰缃负鍙闂�.
+     * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+     * 鍖归厤鍑芥暟鍚�+鍙傛暟绫诲瀷銆�
+     * 鐢ㄤ簬鏂规硶闇�瑕佽澶氭璋冪敤鐨勬儏鍐�. 鍏堜娇鐢ㄦ湰鍑芥暟鍏堝彇寰桵ethod,鐒跺悗璋冪敤Method.invoke(Object obj, Object... args)
+     */
+    public static Method getAccessibleMethod(final Object obj, final String methodName,
+            final Class<?>... parameterTypes)
+    {
+        // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(methodName, "methodName can't be blank");
+        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
+        {
+            try
+            {
+                Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
+                makeAccessible(method);
+                return method;
+            }
+            catch (NoSuchMethodException e)
+            {
+                continue;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredMethod,骞跺己鍒惰缃负鍙闂�.
+     * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+     * 鍙尮閰嶅嚱鏁板悕銆�
+     * 鐢ㄤ簬鏂规硶闇�瑕佽澶氭璋冪敤鐨勬儏鍐�. 鍏堜娇鐢ㄦ湰鍑芥暟鍏堝彇寰桵ethod,鐒跺悗璋冪敤Method.invoke(Object obj, Object... args)
+     */
+    public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum)
+    {
+        // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(methodName, "methodName can't be blank");
+        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
+        {
+            Method[] methods = searchType.getDeclaredMethods();
+            for (Method method : methods)
+            {
+                if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum)
+                {
+                    makeAccessible(method);
+                    return method;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 鏀瑰彉private/protected鐨勬柟娉曚负public锛屽敖閲忎笉璋冪敤瀹為檯鏀瑰姩鐨勮鍙ワ紝閬垮厤JDK鐨凷ecurityManager鎶辨�ㄣ��
+     */
+    public static void makeAccessible(Method method)
+    {
+        if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
+                && !method.isAccessible())
+        {
+            method.setAccessible(true);
+        }
+    }
+
+    /**
+     * 鏀瑰彉private/protected鐨勬垚鍛樺彉閲忎负public锛屽敖閲忎笉璋冪敤瀹為檯鏀瑰姩鐨勮鍙ワ紝閬垮厤JDK鐨凷ecurityManager鎶辨�ㄣ��
+     */
+    public static void makeAccessible(Field field)
+    {
+        if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
+                || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
+        {
+            field.setAccessible(true);
+        }
+    }
+
+    /**
+     * 閫氳繃鍙嶅皠, 鑾峰緱Class瀹氫箟涓0鏄庣殑娉涘瀷鍙傛暟鐨勭被鍨�, 娉ㄦ剰娉涘瀷蹇呴』瀹氫箟鍦ㄧ埗绫诲
+     * 濡傛棤娉曟壘鍒�, 杩斿洖Object.class.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Class<T> getClassGenricType(final Class clazz)
+    {
+        return getClassGenricType(clazz, 0);
+    }
+
+    /**
+     * 閫氳繃鍙嶅皠, 鑾峰緱Class瀹氫箟涓0鏄庣殑鐖剁被鐨勬硾鍨嬪弬鏁扮殑绫诲瀷.
+     * 濡傛棤娉曟壘鍒�, 杩斿洖Object.class.
+     */
+    public static Class getClassGenricType(final Class clazz, final int index)
+    {
+        Type genType = clazz.getGenericSuperclass();
+
+        if (!(genType instanceof ParameterizedType))
+        {
+            logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
+            return Object.class;
+        }
+
+        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
+
+        if (index >= params.length || index < 0)
+        {
+            logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+                    + params.length);
+            return Object.class;
+        }
+        if (!(params[index] instanceof Class))
+        {
+            logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
+            return Object.class;
+        }
+
+        return (Class) params[index];
+    }
+
+    public static Class<?> getUserClass(Object instance)
+    {
+        if (instance == null)
+        {
+            throw new RuntimeException("Instance must not be null");
+        }
+        Class clazz = instance.getClass();
+        if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR))
+        {
+            Class<?> superClass = clazz.getSuperclass();
+            if (superClass != null && !Object.class.equals(superClass))
+            {
+                return superClass;
+            }
+        }
+        return clazz;
+
+    }
+
+    /**
+     * 灏嗗弽灏勬椂鐨刢hecked exception杞崲涓簎nchecked exception.
+     */
+    public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e)
+    {
+        if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
+                || e instanceof NoSuchMethodException)
+        {
+            return new IllegalArgumentException(msg, e);
+        }
+        else if (e instanceof InvocationTargetException)
+        {
+            return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
+        }
+        return new RuntimeException(msg, e);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/sign/Base64.java b/se-common/src/main/java/com/terra/common/utils/sign/Base64.java
new file mode 100644
index 0000000..9729ef5
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/sign/Base64.java
@@ -0,0 +1,291 @@
+package com.terra.common.utils.sign;
+
+/**
+ * Base64宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public final class Base64
+{
+    static private final int     BASELENGTH           = 128;
+    static private final int     LOOKUPLENGTH         = 64;
+    static private final int     TWENTYFOURBITGROUP   = 24;
+    static private final int     EIGHTBIT             = 8;
+    static private final int     SIXTEENBIT           = 16;
+    static private final int     FOURBYTE             = 4;
+    static private final int     SIGN                 = -128;
+    static private final char    PAD                  = '=';
+    static final private byte[]  base64Alphabet       = new byte[BASELENGTH];
+    static final private char[]  lookUpBase64Alphabet = new char[LOOKUPLENGTH];
+
+    static
+    {
+        for (int i = 0; i < BASELENGTH; ++i)
+        {
+            base64Alphabet[i] = -1;
+        }
+        for (int i = 'Z'; i >= 'A'; i--)
+        {
+            base64Alphabet[i] = (byte) (i - 'A');
+        }
+        for (int i = 'z'; i >= 'a'; i--)
+        {
+            base64Alphabet[i] = (byte) (i - 'a' + 26);
+        }
+
+        for (int i = '9'; i >= '0'; i--)
+        {
+            base64Alphabet[i] = (byte) (i - '0' + 52);
+        }
+
+        base64Alphabet['+'] = 62;
+        base64Alphabet['/'] = 63;
+
+        for (int i = 0; i <= 25; i++)
+        {
+            lookUpBase64Alphabet[i] = (char) ('A' + i);
+        }
+
+        for (int i = 26, j = 0; i <= 51; i++, j++)
+        {
+            lookUpBase64Alphabet[i] = (char) ('a' + j);
+        }
+
+        for (int i = 52, j = 0; i <= 61; i++, j++)
+        {
+            lookUpBase64Alphabet[i] = (char) ('0' + j);
+        }
+        lookUpBase64Alphabet[62] = (char) '+';
+        lookUpBase64Alphabet[63] = (char) '/';
+    }
+
+    private static boolean isWhiteSpace(char octect)
+    {
+        return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
+    }
+
+    private static boolean isPad(char octect)
+    {
+        return (octect == PAD);
+    }
+
+    private static boolean isData(char octect)
+    {
+        return (octect < BASELENGTH && base64Alphabet[octect] != -1);
+    }
+
+    /**
+     * Encodes hex octects into Base64
+     *
+     * @param binaryData Array containing binaryData
+     * @return Encoded Base64 array
+     */
+    public static String encode(byte[] binaryData)
+    {
+        if (binaryData == null)
+        {
+            return null;
+        }
+
+        int lengthDataBits = binaryData.length * EIGHTBIT;
+        if (lengthDataBits == 0)
+        {
+            return "";
+        }
+
+        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
+        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
+        int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
+        char encodedData[] = null;
+
+        encodedData = new char[numberQuartet * 4];
+
+        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
+
+        int encodedIndex = 0;
+        int dataIndex = 0;
+
+        for (int i = 0; i < numberTriplets; i++)
+        {
+            b1 = binaryData[dataIndex++];
+            b2 = binaryData[dataIndex++];
+            b3 = binaryData[dataIndex++];
+
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+            byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
+
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
+        }
+
+        // form integral number of 6-bit groups
+        if (fewerThan24bits == EIGHTBIT)
+        {
+            b1 = binaryData[dataIndex];
+            k = (byte) (b1 & 0x03);
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
+            encodedData[encodedIndex++] = PAD;
+            encodedData[encodedIndex++] = PAD;
+        }
+        else if (fewerThan24bits == SIXTEENBIT)
+        {
+            b1 = binaryData[dataIndex];
+            b2 = binaryData[dataIndex + 1];
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
+            encodedData[encodedIndex++] = PAD;
+        }
+        return new String(encodedData);
+    }
+
+    /**
+     * Decodes Base64 data into octects
+     *
+     * @param encoded string containing Base64 data
+     * @return Array containind decoded data.
+     */
+    public static byte[] decode(String encoded)
+    {
+        if (encoded == null)
+        {
+            return null;
+        }
+
+        char[] base64Data = encoded.toCharArray();
+        // remove white spaces
+        int len = removeWhiteSpace(base64Data);
+
+        if (len % FOURBYTE != 0)
+        {
+            return null;// should be divisible by four
+        }
+
+        int numberQuadruple = (len / FOURBYTE);
+
+        if (numberQuadruple == 0)
+        {
+            return new byte[0];
+        }
+
+        byte decodedData[] = null;
+        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
+        char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
+
+        int i = 0;
+        int encodedIndex = 0;
+        int dataIndex = 0;
+        decodedData = new byte[(numberQuadruple) * 3];
+
+        for (; i < numberQuadruple - 1; i++)
+        {
+
+            if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
+                    || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++])))
+            {
+                return null;
+            } // if found "no data" just return null
+
+            b1 = base64Alphabet[d1];
+            b2 = base64Alphabet[d2];
+            b3 = base64Alphabet[d3];
+            b4 = base64Alphabet[d4];
+
+            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+        }
+
+        if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])))
+        {
+            return null;// if found "no data" just return null
+        }
+
+        b1 = base64Alphabet[d1];
+        b2 = base64Alphabet[d2];
+
+        d3 = base64Data[dataIndex++];
+        d4 = base64Data[dataIndex++];
+        if (!isData((d3)) || !isData((d4)))
+        {// Check if they are PAD characters
+            if (isPad(d3) && isPad(d4))
+            {
+                if ((b2 & 0xf) != 0)// last 4 bits should be zero
+                {
+                    return null;
+                }
+                byte[] tmp = new byte[i * 3 + 1];
+                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+                tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+                return tmp;
+            }
+            else if (!isPad(d3) && isPad(d4))
+            {
+                b3 = base64Alphabet[d3];
+                if ((b3 & 0x3) != 0)// last 2 bits should be zero
+                {
+                    return null;
+                }
+                byte[] tmp = new byte[i * 3 + 2];
+                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+                tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+                tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+                return tmp;
+            }
+            else
+            {
+                return null;
+            }
+        }
+        else
+        { // No PAD e.g 3cQl
+            b3 = base64Alphabet[d3];
+            b4 = base64Alphabet[d4];
+            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+
+        }
+        return decodedData;
+    }
+
+    /**
+     * remove WhiteSpace from MIME containing encoded Base64 data.
+     *
+     * @param data the byte array of base64 data (with WS)
+     * @return the new length
+     */
+    private static int removeWhiteSpace(char[] data)
+    {
+        if (data == null)
+        {
+            return 0;
+        }
+
+        // count characters that's not whitespace
+        int newSize = 0;
+        int len = data.length;
+        for (int i = 0; i < len; i++)
+        {
+            if (!isWhiteSpace(data[i]))
+            {
+                data[newSize++] = data[i];
+            }
+        }
+        return newSize;
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/sql/SqlUtil.java b/se-common/src/main/java/com/terra/common/utils/sql/SqlUtil.java
new file mode 100644
index 0000000..f1cbaa0
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/sql/SqlUtil.java
@@ -0,0 +1,70 @@
+package com.terra.common.utils.sql;
+
+import com.terra.common.exception.UtilException;
+import com.terra.common.utils.StringUtils;
+
+/**
+ * sql鎿嶄綔宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class SqlUtil
+{
+    /**
+     * 瀹氫箟甯哥敤鐨� sql鍏抽敭瀛�
+     */
+    public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
+
+    /**
+     * 浠呮敮鎸佸瓧姣嶃�佹暟瀛椼�佷笅鍒掔嚎銆佺┖鏍笺�侀�楀彿銆佸皬鏁扮偣锛堟敮鎸佸涓瓧娈垫帓搴忥級
+     */
+    public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
+
+    /**
+     * 闄愬埗orderBy鏈�澶ч暱搴�
+     */
+    private static final int ORDER_BY_MAX_LENGTH = 500;
+
+    /**
+     * 妫�鏌ュ瓧绗︼紝闃叉娉ㄥ叆缁曡繃
+     */
+    public static String escapeOrderBySql(String value)
+    {
+        if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
+        {
+            throw new UtilException("鍙傛暟涓嶇鍚堣鑼冿紝涓嶈兘杩涜鏌ヨ");
+        }
+        if (StringUtils.length(value) > ORDER_BY_MAX_LENGTH)
+        {
+            throw new UtilException("鍙傛暟宸茶秴杩囨渶澶ч檺鍒讹紝涓嶈兘杩涜鏌ヨ");
+        }
+        return value;
+    }
+
+    /**
+     * 楠岃瘉 order by 璇硶鏄惁绗﹀悎瑙勮寖
+     */
+    public static boolean isValidOrderBySql(String value)
+    {
+        return value.matches(SQL_PATTERN);
+    }
+
+    /**
+     * SQL鍏抽敭瀛楁鏌�
+     */
+    public static void filterKeyword(String value)
+    {
+        if (StringUtils.isEmpty(value))
+        {
+            return;
+        }
+        String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
+        for (String sqlKeyword : sqlKeywords)
+        {
+            if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
+            {
+                throw new UtilException("鍙傛暟瀛樺湪SQL娉ㄥ叆椋庨櫓");
+            }
+        }
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/uuid/IdUtils.java b/se-common/src/main/java/com/terra/common/utils/uuid/IdUtils.java
new file mode 100644
index 0000000..87f2426
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/uuid/IdUtils.java
@@ -0,0 +1,49 @@
+package com.terra.common.utils.uuid;
+
+/**
+ * ID鐢熸垚鍣ㄥ伐鍏风被
+ * 
+ * @author ruoyi
+ */
+public class IdUtils
+{
+    /**
+     * 鑾峰彇闅忔満UUID
+     * 
+     * @return 闅忔満UUID
+     */
+    public static String randomUUID()
+    {
+        return UUID.randomUUID().toString();
+    }
+
+    /**
+     * 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+     * 
+     * @return 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+     */
+    public static String simpleUUID()
+    {
+        return UUID.randomUUID().toString(true);
+    }
+
+    /**
+     * 鑾峰彇闅忔満UUID锛屼娇鐢ㄦ�ц兘鏇村ソ鐨凾hreadLocalRandom鐢熸垚UUID
+     * 
+     * @return 闅忔満UUID
+     */
+    public static String fastUUID()
+    {
+        return UUID.fastUUID().toString();
+    }
+
+    /**
+     * 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎锛屼娇鐢ㄦ�ц兘鏇村ソ鐨凾hreadLocalRandom鐢熸垚UUID
+     * 
+     * @return 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+     */
+    public static String fastSimpleUUID()
+    {
+        return UUID.fastUUID().toString(true);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/uuid/Seq.java b/se-common/src/main/java/com/terra/common/utils/uuid/Seq.java
new file mode 100644
index 0000000..a0ef134
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/uuid/Seq.java
@@ -0,0 +1,86 @@
+package com.terra.common.utils.uuid;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import com.terra.common.utils.DateUtils;
+import com.terra.common.utils.StringUtils;
+
+/**
+ * @author ruoyi 搴忓垪鐢熸垚绫�
+ */
+public class Seq
+{
+    // 閫氱敤搴忓垪绫诲瀷
+    public static final String commSeqType = "COMMON";
+
+    // 涓婁紶搴忓垪绫诲瀷
+    public static final String uploadSeqType = "UPLOAD";
+
+    // 閫氱敤鎺ュ彛搴忓垪鏁�
+    private static AtomicInteger commSeq = new AtomicInteger(1);
+
+    // 涓婁紶鎺ュ彛搴忓垪鏁�
+    private static AtomicInteger uploadSeq = new AtomicInteger(1);
+
+    // 鏈哄櫒鏍囪瘑
+    private static final String machineCode = "A";
+
+    /**
+     * 鑾峰彇閫氱敤搴忓垪鍙�
+     * 
+     * @return 搴忓垪鍊�
+     */
+    public static String getId()
+    {
+        return getId(commSeqType);
+    }
+    
+    /**
+     * 榛樿16浣嶅簭鍒楀彿 yyMMddHHmmss + 涓�浣嶆満鍣ㄦ爣璇� + 3闀垮害寰幆閫掑瀛楃涓�
+     * 
+     * @return 搴忓垪鍊�
+     */
+    public static String getId(String type)
+    {
+        AtomicInteger atomicInt = commSeq;
+        if (uploadSeqType.equals(type))
+        {
+            atomicInt = uploadSeq;
+        }
+        return getId(atomicInt, 3);
+    }
+
+    /**
+     * 閫氱敤鎺ュ彛搴忓垪鍙� yyMMddHHmmss + 涓�浣嶆満鍣ㄦ爣璇� + length闀垮害寰幆閫掑瀛楃涓�
+     * 
+     * @param atomicInt 搴忓垪鏁�
+     * @param length 鏁板�奸暱搴�
+     * @return 搴忓垪鍊�
+     */
+    public static String getId(AtomicInteger atomicInt, int length)
+    {
+        String result = DateUtils.dateTimeNow();
+        result += machineCode;
+        result += getSeq(atomicInt, length);
+        return result;
+    }
+
+    /**
+     * 搴忓垪寰幆閫掑瀛楃涓瞇1, 10 鐨� (length)骞傛鏂�), 鐢�0宸﹁ˉ榻恖ength浣嶆暟
+     * 
+     * @return 搴忓垪鍊�
+     */
+    private synchronized static String getSeq(AtomicInteger atomicInt, int length)
+    {
+        // 鍏堝彇鍊煎啀+1
+        int value = atomicInt.getAndIncrement();
+
+        // 濡傛灉鏇存柊鍚庡��>=10 鐨� (length)骞傛鏂瑰垯閲嶇疆涓�1
+        int maxSeq = (int) Math.pow(10, length);
+        if (atomicInt.get() >= maxSeq)
+        {
+            atomicInt.set(1);
+        }
+        // 杞瓧绗︿覆锛岀敤0宸﹁ˉ榻�
+        return StringUtils.padl(value, length);
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/utils/uuid/UUID.java b/se-common/src/main/java/com/terra/common/utils/uuid/UUID.java
new file mode 100644
index 0000000..52295cd
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/utils/uuid/UUID.java
@@ -0,0 +1,484 @@
+package com.terra.common.utils.uuid;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+import com.terra.common.exception.UtilException;
+
+/**
+ * 鎻愪緵閫氱敤鍞竴璇嗗埆鐮侊紙universally unique identifier锛夛紙UUID锛夊疄鐜�
+ *
+ * @author ruoyi
+ */
+public final class UUID implements java.io.Serializable, Comparable<UUID>
+{
+    private static final long serialVersionUID = -1185015143654744140L;
+
+    /**
+     * SecureRandom 鐨勫崟渚�
+     *
+     */
+    private static class Holder
+    {
+        static final SecureRandom numberGenerator = getSecureRandom();
+    }
+
+    /** 姝UID鐨勬渶楂�64鏈夋晥浣� */
+    private final long mostSigBits;
+
+    /** 姝UID鐨勬渶浣�64鏈夋晥浣� */
+    private final long leastSigBits;
+
+    /**
+     * 绉佹湁鏋勯��
+     * 
+     * @param data 鏁版嵁
+     */
+    private UUID(byte[] data)
+    {
+        long msb = 0;
+        long lsb = 0;
+        assert data.length == 16 : "data must be 16 bytes in length";
+        for (int i = 0; i < 8; i++)
+        {
+            msb = (msb << 8) | (data[i] & 0xff);
+        }
+        for (int i = 8; i < 16; i++)
+        {
+            lsb = (lsb << 8) | (data[i] & 0xff);
+        }
+        this.mostSigBits = msb;
+        this.leastSigBits = lsb;
+    }
+
+    /**
+     * 浣跨敤鎸囧畾鐨勬暟鎹瀯閫犳柊鐨� UUID銆�
+     *
+     * @param mostSigBits 鐢ㄤ簬 {@code UUID} 鐨勬渶楂樻湁鏁� 64 浣�
+     * @param leastSigBits 鐢ㄤ簬 {@code UUID} 鐨勬渶浣庢湁鏁� 64 浣�
+     */
+    public UUID(long mostSigBits, long leastSigBits)
+    {
+        this.mostSigBits = mostSigBits;
+        this.leastSigBits = leastSigBits;
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘�� 
+     * 
+     * @return 闅忔満鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID fastUUID()
+    {
+        return randomUUID(false);
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘�� 浣跨敤鍔犲瘑鐨勫己浼殢鏈烘暟鐢熸垚鍣ㄧ敓鎴愯 UUID銆�
+     * 
+     * @return 闅忔満鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID randomUUID()
+    {
+        return randomUUID(true);
+    }
+
+    /**
+     * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘�� 浣跨敤鍔犲瘑鐨勫己浼殢鏈烘暟鐢熸垚鍣ㄧ敓鎴愯 UUID銆�
+     * 
+     * @param isSecure 鏄惁浣跨敤{@link SecureRandom}濡傛灉鏄彲浠ヨ幏寰楁洿瀹夊叏鐨勯殢鏈虹爜锛屽惁鍒欏彲浠ュ緱鍒版洿濂界殑鎬ц兘
+     * @return 闅忔満鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID randomUUID(boolean isSecure)
+    {
+        final Random ng = isSecure ? Holder.numberGenerator : getRandom();
+
+        byte[] randomBytes = new byte[16];
+        ng.nextBytes(randomBytes);
+        randomBytes[6] &= 0x0f; /* clear version */
+        randomBytes[6] |= 0x40; /* set to version 4 */
+        randomBytes[8] &= 0x3f; /* clear variant */
+        randomBytes[8] |= 0x80; /* set to IETF variant */
+        return new UUID(randomBytes);
+    }
+
+    /**
+     * 鏍规嵁鎸囧畾鐨勫瓧鑺傛暟缁勮幏鍙栫被鍨� 3锛堝熀浜庡悕绉扮殑锛塙UID 鐨勯潤鎬佸伐鍘傘��
+     *
+     * @param name 鐢ㄤ簬鏋勯�� UUID 鐨勫瓧鑺傛暟缁勩��
+     *
+     * @return 鏍规嵁鎸囧畾鏁扮粍鐢熸垚鐨� {@code UUID}
+     */
+    public static UUID nameUUIDFromBytes(byte[] name)
+    {
+        MessageDigest md;
+        try
+        {
+            md = MessageDigest.getInstance("MD5");
+        }
+        catch (NoSuchAlgorithmException nsae)
+        {
+            throw new InternalError("MD5 not supported");
+        }
+        byte[] md5Bytes = md.digest(name);
+        md5Bytes[6] &= 0x0f; /* clear version */
+        md5Bytes[6] |= 0x30; /* set to version 3 */
+        md5Bytes[8] &= 0x3f; /* clear variant */
+        md5Bytes[8] |= 0x80; /* set to IETF variant */
+        return new UUID(md5Bytes);
+    }
+
+    /**
+     * 鏍规嵁 {@link #toString()} 鏂规硶涓弿杩扮殑瀛楃涓叉爣鍑嗚〃绀哄舰寮忓垱寤簕@code UUID}銆�
+     *
+     * @param name 鎸囧畾 {@code UUID} 瀛楃涓�
+     * @return 鍏锋湁鎸囧畾鍊肩殑 {@code UUID}
+     * @throws IllegalArgumentException 濡傛灉 name 涓� {@link #toString} 涓弿杩扮殑瀛楃涓茶〃绀哄舰寮忎笉绗︽姏鍑烘寮傚父
+     *
+     */
+    public static UUID fromString(String name)
+    {
+        String[] components = name.split("-");
+        if (components.length != 5)
+        {
+            throw new IllegalArgumentException("Invalid UUID string: " + name);
+        }
+        for (int i = 0; i < 5; i++)
+        {
+            components[i] = "0x" + components[i];
+        }
+
+        long mostSigBits = Long.decode(components[0]).longValue();
+        mostSigBits <<= 16;
+        mostSigBits |= Long.decode(components[1]).longValue();
+        mostSigBits <<= 16;
+        mostSigBits |= Long.decode(components[2]).longValue();
+
+        long leastSigBits = Long.decode(components[3]).longValue();
+        leastSigBits <<= 48;
+        leastSigBits |= Long.decode(components[4]).longValue();
+
+        return new UUID(mostSigBits, leastSigBits);
+    }
+
+    /**
+     * 杩斿洖姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶浣庢湁鏁� 64 浣嶃��
+     *
+     * @return 姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶浣庢湁鏁� 64 浣嶃��
+     */
+    public long getLeastSignificantBits()
+    {
+        return leastSigBits;
+    }
+
+    /**
+     * 杩斿洖姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶楂樻湁鏁� 64 浣嶃��
+     *
+     * @return 姝� UUID 鐨� 128 浣嶅�间腑鏈�楂樻湁鏁� 64 浣嶃��
+     */
+    public long getMostSignificantBits()
+    {
+        return mostSigBits;
+    }
+
+    /**
+     * 涓庢 {@code UUID} 鐩稿叧鑱旂殑鐗堟湰鍙�. 鐗堟湰鍙锋弿杩版 {@code UUID} 鏄浣曠敓鎴愮殑銆�
+     * <p>
+     * 鐗堟湰鍙峰叿鏈変互涓嬪惈鎰�:
+     * <ul>
+     * <li>1 鍩轰簬鏃堕棿鐨� UUID
+     * <li>2 DCE 瀹夊叏 UUID
+     * <li>3 鍩轰簬鍚嶇О鐨� UUID
+     * <li>4 闅忔満鐢熸垚鐨� UUID
+     * </ul>
+     *
+     * @return 姝� {@code UUID} 鐨勭増鏈彿
+     */
+    public int version()
+    {
+        // Version is bits masked by 0x000000000000F000 in MS long
+        return (int) ((mostSigBits >> 12) & 0x0f);
+    }
+
+    /**
+     * 涓庢 {@code UUID} 鐩稿叧鑱旂殑鍙樹綋鍙枫�傚彉浣撳彿鎻忚堪 {@code UUID} 鐨勫竷灞�銆�
+     * <p>
+     * 鍙樹綋鍙峰叿鏈変互涓嬪惈鎰忥細
+     * <ul>
+     * <li>0 涓� NCS 鍚戝悗鍏煎淇濈暀
+     * <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>(Leach-Salz), 鐢ㄤ簬姝ょ被
+     * <li>6 淇濈暀锛屽井杞悜鍚庡吋瀹�
+     * <li>7 淇濈暀渚涗互鍚庡畾涔変娇鐢�
+     * </ul>
+     *
+     * @return 姝� {@code UUID} 鐩稿叧鑱旂殑鍙樹綋鍙�
+     */
+    public int variant()
+    {
+        // This field is composed of a varying number of bits.
+        // 0 - - Reserved for NCS backward compatibility
+        // 1 0 - The IETF aka Leach-Salz variant (used by this class)
+        // 1 1 0 Reserved, Microsoft backward compatibility
+        // 1 1 1 Reserved for future definition.
+        return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
+    }
+
+    /**
+     * 涓庢 UUID 鐩稿叧鑱旂殑鏃堕棿鎴冲�笺��
+     *
+     * <p>
+     * 60 浣嶇殑鏃堕棿鎴冲�兼牴鎹 {@code UUID} 鐨� time_low銆乼ime_mid 鍜� time_hi 瀛楁鏋勯�犮��<br>
+     * 鎵�寰楀埌鐨勬椂闂存埑浠� 100 姣井绉掍负鍗曚綅锛屼粠 UTC锛堥�氱敤鍗忚皟鏃堕棿锛� 1582 骞� 10 鏈� 15 鏃ラ浂鏃跺紑濮嬨��
+     *
+     * <p>
+     * 鏃堕棿鎴冲�间粎鍦ㄥ湪鍩轰簬鏃堕棿鐨� UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆�<br>
+     * 濡傛灉姝� {@code UUID} 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑� UnsupportedOperationException銆�
+     *
+     * @throws UnsupportedOperationException 濡傛灉姝� {@code UUID} 涓嶆槸 version 涓� 1 鐨� UUID銆�
+     */
+    public long timestamp() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return (mostSigBits & 0x0FFFL) << 48//
+                | ((mostSigBits >> 16) & 0x0FFFFL) << 32//
+                | mostSigBits >>> 32;
+    }
+
+    /**
+     * 涓庢 UUID 鐩稿叧鑱旂殑鏃堕挓搴忓垪鍊笺��
+     *
+     * <p>
+     * 14 浣嶇殑鏃堕挓搴忓垪鍊兼牴鎹 UUID 鐨� clock_seq 瀛楁鏋勯�犮�俢lock_seq 瀛楁鐢ㄤ簬淇濊瘉鍦ㄥ熀浜庢椂闂寸殑 UUID 涓殑鏃堕棿鍞竴鎬с��
+     * <p>
+     * {@code clockSequence} 鍊间粎鍦ㄥ熀浜庢椂闂寸殑 UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆� 濡傛灉姝� UUID 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑�
+     * UnsupportedOperationException銆�
+     *
+     * @return 姝� {@code UUID} 鐨勬椂閽熷簭鍒�
+     *
+     * @throws UnsupportedOperationException 濡傛灉姝� UUID 鐨� version 涓嶄负 1
+     */
+    public int clockSequence() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
+    }
+
+    /**
+     * 涓庢 UUID 鐩稿叧鐨勮妭鐐瑰�笺��
+     *
+     * <p>
+     * 48 浣嶇殑鑺傜偣鍊兼牴鎹 UUID 鐨� node 瀛楁鏋勯�犮�傛瀛楁鏃ㄥ湪鐢ㄤ簬淇濆瓨鏈哄櫒鐨� IEEE 802 鍦板潃锛岃鍦板潃鐢ㄤ簬鐢熸垚姝� UUID 浠ヤ繚璇佺┖闂村敮涓�鎬с��
+     * <p>
+     * 鑺傜偣鍊间粎鍦ㄥ熀浜庢椂闂寸殑 UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆�<br>
+     * 濡傛灉姝� UUID 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑� UnsupportedOperationException銆�
+     *
+     * @return 姝� {@code UUID} 鐨勮妭鐐瑰��
+     *
+     * @throws UnsupportedOperationException 濡傛灉姝� UUID 鐨� version 涓嶄负 1
+     */
+    public long node() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return leastSigBits & 0x0000FFFFFFFFFFFFL;
+    }
+
+    /**
+     * 杩斿洖姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡銆�
+     *
+     * <p>
+     * UUID 鐨勫瓧绗︿覆琛ㄧず褰㈠紡鐢辨 BNF 鎻忚堪锛�
+     * 
+     * <pre>
+     * {@code
+     * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
+     * time_low               = 4*<hexOctet>
+     * time_mid               = 2*<hexOctet>
+     * time_high_and_version  = 2*<hexOctet>
+     * variant_and_sequence   = 2*<hexOctet>
+     * node                   = 6*<hexOctet>
+     * hexOctet               = <hexDigit><hexDigit>
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * </pre>
+     * 
+     * </blockquote>
+     *
+     * @return 姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡
+     * @see #toString(boolean)
+     */
+    @Override
+    public String toString()
+    {
+        return toString(false);
+    }
+
+    /**
+     * 杩斿洖姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡銆�
+     *
+     * <p>
+     * UUID 鐨勫瓧绗︿覆琛ㄧず褰㈠紡鐢辨 BNF 鎻忚堪锛�
+     * 
+     * <pre>
+     * {@code
+     * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
+     * time_low               = 4*<hexOctet>
+     * time_mid               = 2*<hexOctet>
+     * time_high_and_version  = 2*<hexOctet>
+     * variant_and_sequence   = 2*<hexOctet>
+     * node                   = 6*<hexOctet>
+     * hexOctet               = <hexDigit><hexDigit>
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * </pre>
+     * 
+     * </blockquote>
+     *
+     * @param isSimple 鏄惁绠�鍗曟ā寮忥紝绠�鍗曟ā寮忎负涓嶅甫'-'鐨刄UID瀛楃涓�
+     * @return 姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡
+     */
+    public String toString(boolean isSimple)
+    {
+        final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
+        // time_low
+        builder.append(digits(mostSigBits >> 32, 8));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // time_mid
+        builder.append(digits(mostSigBits >> 16, 4));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // time_high_and_version
+        builder.append(digits(mostSigBits, 4));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // variant_and_sequence
+        builder.append(digits(leastSigBits >> 48, 4));
+        if (!isSimple)
+        {
+            builder.append('-');
+        }
+        // node
+        builder.append(digits(leastSigBits, 12));
+
+        return builder.toString();
+    }
+
+    /**
+     * 杩斿洖姝� UUID 鐨勫搱甯岀爜銆�
+     *
+     * @return UUID 鐨勫搱甯岀爜鍊笺��
+     */
+    @Override
+    public int hashCode()
+    {
+        long hilo = mostSigBits ^ leastSigBits;
+        return ((int) (hilo >> 32)) ^ (int) hilo;
+    }
+
+    /**
+     * 灏嗘瀵硅薄涓庢寚瀹氬璞℃瘮杈冦��
+     * <p>
+     * 褰撲笖浠呭綋鍙傛暟涓嶄负 {@code null}銆佽�屾槸涓�涓� UUID 瀵硅薄銆佸叿鏈変笌姝� UUID 鐩稿悓鐨� varriant銆佸寘鍚浉鍚岀殑鍊硷紙姣忎竴浣嶅潎鐩稿悓锛夋椂锛岀粨鏋滄墠涓� {@code true}銆�
+     *
+     * @param obj 瑕佷笌涔嬫瘮杈冪殑瀵硅薄
+     *
+     * @return 濡傛灉瀵硅薄鐩稿悓锛屽垯杩斿洖 {@code true}锛涘惁鍒欒繑鍥� {@code false}
+     */
+    @Override
+    public boolean equals(Object obj)
+    {
+        if ((null == obj) || (obj.getClass() != UUID.class))
+        {
+            return false;
+        }
+        UUID id = (UUID) obj;
+        return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
+    }
+
+    // Comparison Operations
+
+    /**
+     * 灏嗘 UUID 涓庢寚瀹氱殑 UUID 姣旇緝銆�
+     *
+     * <p>
+     * 濡傛灉涓や釜 UUID 涓嶅悓锛屼笖绗竴涓� UUID 鐨勬渶楂樻湁鏁堝瓧娈靛ぇ浜庣浜屼釜 UUID 鐨勫搴斿瓧娈碉紝鍒欑涓�涓� UUID 澶т簬绗簩涓� UUID銆�
+     *
+     * @param val 涓庢 UUID 姣旇緝鐨� UUID
+     *
+     * @return 鍦ㄦ UUID 灏忎簬銆佺瓑浜庢垨澶т簬 val 鏃讹紝鍒嗗埆杩斿洖 -1銆�0 鎴� 1銆�
+     *
+     */
+    @Override
+    public int compareTo(UUID val)
+    {
+        // The ordering is intentionally set up so that the UUIDs
+        // can simply be numerically compared as two numbers
+        return (this.mostSigBits < val.mostSigBits ? -1 : //
+                (this.mostSigBits > val.mostSigBits ? 1 : //
+                        (this.leastSigBits < val.leastSigBits ? -1 : //
+                                (this.leastSigBits > val.leastSigBits ? 1 : //
+                                        0))));
+    }
+
+    // -------------------------------------------------------------------------------------------------------------------
+    // Private method start
+    /**
+     * 杩斿洖鎸囧畾鏁板瓧瀵瑰簲鐨刪ex鍊�
+     * 
+     * @param val 鍊�
+     * @param digits 浣�
+     * @return 鍊�
+     */
+    private static String digits(long val, int digits)
+    {
+        long hi = 1L << (digits * 4);
+        return Long.toHexString(hi | (val & (hi - 1))).substring(1);
+    }
+
+    /**
+     * 妫�鏌ユ槸鍚︿负time-based鐗堟湰UUID
+     */
+    private void checkTimeBase()
+    {
+        if (version() != 1)
+        {
+            throw new UnsupportedOperationException("Not a time-based UUID");
+        }
+    }
+
+    /**
+     * 鑾峰彇{@link SecureRandom}锛岀被鎻愪緵鍔犲瘑鐨勫己闅忔満鏁扮敓鎴愬櫒 (RNG)
+     * 
+     * @return {@link SecureRandom}
+     */
+    public static SecureRandom getSecureRandom()
+    {
+        try
+        {
+            return SecureRandom.getInstance("SHA1PRNG");
+        }
+        catch (NoSuchAlgorithmException e)
+        {
+            throw new UtilException(e);
+        }
+    }
+
+    /**
+     * 鑾峰彇闅忔満鏁扮敓鎴愬櫒瀵硅薄<br>
+     * ThreadLocalRandom鏄疛DK 7涔嬪悗鎻愪緵骞跺彂浜х敓闅忔満鏁帮紝鑳藉瑙e喅澶氫釜绾跨▼鍙戠敓鐨勭珵浜変簤澶恒��
+     * 
+     * @return {@link ThreadLocalRandom}
+     */
+    public static ThreadLocalRandom getRandom()
+    {
+        return ThreadLocalRandom.current();
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/web/controller/BaseController.java b/se-common/src/main/java/com/terra/common/web/controller/BaseController.java
new file mode 100644
index 0000000..d4470a8
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/web/controller/BaseController.java
@@ -0,0 +1,160 @@
+package com.terra.common.web.controller;
+
+import java.beans.PropertyEditorSupport;
+import java.util.Date;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.terra.common.constant.HttpStatus;
+import com.terra.common.utils.DateUtils;
+import com.terra.common.utils.PageUtils;
+import com.terra.common.utils.StringUtils;
+import com.terra.common.utils.sql.SqlUtil;
+import com.terra.common.web.domain.AjaxResult;
+import com.terra.common.web.page.PageDomain;
+import com.terra.common.web.page.TableDataInfo;
+import com.terra.common.web.page.TableSupport;
+
+/**
+ * web灞傞�氱敤鏁版嵁澶勭悊
+ * 
+ * @author ruoyi
+ */
+public class BaseController
+{
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * 灏嗗墠鍙颁紶閫掕繃鏉ョ殑鏃ユ湡鏍煎紡鐨勫瓧绗︿覆锛岃嚜鍔ㄨ浆鍖栦负Date绫诲瀷
+     */
+    @InitBinder
+    public void initBinder(WebDataBinder binder)
+    {
+        // Date 绫诲瀷杞崲
+        binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
+        {
+            @Override
+            public void setAsText(String text)
+            {
+                setValue(DateUtils.parseDate(text));
+            }
+        });
+    }
+
+    /**
+     * 璁剧疆璇锋眰鍒嗛〉鏁版嵁
+     */
+    protected void startPage()
+    {
+        PageUtils.startPage();
+    }
+
+    /**
+     * 璁剧疆璇锋眰鎺掑簭鏁版嵁
+     */
+    protected void startOrderBy()
+    {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
+        {
+            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+            PageHelper.orderBy(orderBy);
+        }
+    }
+
+    /**
+     * 娓呯悊鍒嗛〉鐨勭嚎绋嬪彉閲�
+     */
+    protected void clearPage()
+    {
+        PageUtils.clearPage();
+    }
+
+    /**
+     * 鍝嶅簲璇锋眰鍒嗛〉鏁版嵁
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    protected TableDataInfo getDataTable(List<?> list)
+    {
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setRows(list);
+        rspData.setMsg("鏌ヨ鎴愬姛");
+        rspData.setTotal(new PageInfo(list).getTotal());
+        return rspData;
+    }
+
+    /**
+     * 杩斿洖鎴愬姛
+     */
+    public AjaxResult success()
+    {
+        return AjaxResult.success();
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     */
+    public AjaxResult success(String message)
+    {
+        return AjaxResult.success(message);
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     */
+    public AjaxResult success(Object data)
+    {
+        return AjaxResult.success(data);
+    }
+
+    /**
+     * 杩斿洖澶辫触娑堟伅
+     */
+    public AjaxResult error()
+    {
+        return AjaxResult.error();
+    }
+
+    /**
+     * 杩斿洖澶辫触娑堟伅
+     */
+    public AjaxResult error(String message)
+    {
+        return AjaxResult.error(message);
+    }
+
+    /**
+     * 杩斿洖璀﹀憡娑堟伅
+     */
+    public AjaxResult warn(String message)
+    {
+        return AjaxResult.warn(message);
+    }
+
+    /**
+     * 鍝嶅簲杩斿洖缁撴灉
+     * 
+     * @param rows 褰卞搷琛屾暟
+     * @return 鎿嶄綔缁撴灉
+     */
+    protected AjaxResult toAjax(int rows)
+    {
+        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    /**
+     * 鍝嶅簲杩斿洖缁撴灉
+     * 
+     * @param result 缁撴灉
+     * @return 鎿嶄綔缁撴灉
+     */
+    protected AjaxResult toAjax(boolean result)
+    {
+        return result ? success() : error();
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/web/domain/AjaxResult.java b/se-common/src/main/java/com/terra/common/web/domain/AjaxResult.java
new file mode 100644
index 0000000..a44c3ac
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/web/domain/AjaxResult.java
@@ -0,0 +1,216 @@
+package com.terra.common.web.domain;
+
+import java.util.HashMap;
+import java.util.Objects;
+import com.terra.common.constant.HttpStatus;
+import com.terra.common.utils.StringUtils;
+
+/**
+ * 鎿嶄綔娑堟伅鎻愰啋
+ * 
+ * @author ruoyi
+ */
+public class AjaxResult extends HashMap<String, Object>
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鐘舵�佺爜 */
+    public static final String CODE_TAG = "code";
+
+    /** 杩斿洖鍐呭 */
+    public static final String MSG_TAG = "msg";
+
+    /** 鏁版嵁瀵硅薄 */
+    public static final String DATA_TAG = "data";
+
+    /**
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄锛屼娇鍏惰〃绀轰竴涓┖娑堟伅銆�
+     */
+    public AjaxResult()
+    {
+    }
+
+    /**
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄
+     * 
+     * @param code 鐘舵�佺爜
+     * @param msg 杩斿洖鍐呭
+     */
+    public AjaxResult(int code, String msg)
+    {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+    }
+
+    /**
+     * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄
+     * 
+     * @param code 鐘舵�佺爜
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     */
+    public AjaxResult(int code, String msg, Object data)
+    {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+        if (StringUtils.isNotNull(data))
+        {
+            super.put(DATA_TAG, data);
+        }
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     * 
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success()
+    {
+        return AjaxResult.success("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 杩斿洖鎴愬姛鏁版嵁
+     * 
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success(Object data)
+    {
+        return AjaxResult.success("鎿嶄綔鎴愬姛", data);
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success(String msg)
+    {
+        return AjaxResult.success(msg, null);
+    }
+
+    /**
+     * 杩斿洖鎴愬姛娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     * @return 鎴愬姛娑堟伅
+     */
+    public static AjaxResult success(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.SUCCESS, msg, data);
+    }
+
+    /**
+     * 杩斿洖璀﹀憡娑堟伅
+     *
+     * @param msg 杩斿洖鍐呭
+     * @return 璀﹀憡娑堟伅
+     */
+    public static AjaxResult warn(String msg)
+    {
+        return AjaxResult.warn(msg, null);
+    }
+
+    /**
+     * 杩斿洖璀﹀憡娑堟伅
+     *
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     * @return 璀﹀憡娑堟伅
+     */
+    public static AjaxResult warn(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.WARN, msg, data);
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error()
+    {
+        return AjaxResult.error("鎿嶄綔澶辫触");
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error(String msg)
+    {
+        return AjaxResult.error(msg, null);
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.ERROR, msg, data);
+    }
+
+    /**
+     * 杩斿洖閿欒娑堟伅
+     * 
+     * @param code 鐘舵�佺爜
+     * @param msg 杩斿洖鍐呭
+     * @return 閿欒娑堟伅
+     */
+    public static AjaxResult error(int code, String msg)
+    {
+        return new AjaxResult(code, msg, null);
+    }
+
+    /**
+     * 鏄惁涓烘垚鍔熸秷鎭�
+     *
+     * @return 缁撴灉
+     */
+    public boolean isSuccess()
+    {
+        return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
+    }
+
+    /**
+     * 鏄惁涓鸿鍛婃秷鎭�
+     *
+     * @return 缁撴灉
+     */
+    public boolean isWarn()
+    {
+        return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
+    }
+
+    /**
+     * 鏄惁涓洪敊璇秷鎭�
+     *
+     * @return 缁撴灉
+     */
+    public boolean isError()
+    {
+        return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
+    }
+
+    /**
+     * 鏂逛究閾惧紡璋冪敤
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    @Override
+    public AjaxResult put(String key, Object value)
+    {
+        super.put(key, value);
+        return this;
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/web/domain/BaseEntity.java b/se-common/src/main/java/com/terra/common/web/domain/BaseEntity.java
new file mode 100644
index 0000000..8f212b2
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/web/domain/BaseEntity.java
@@ -0,0 +1,118 @@
+package com.terra.common.web.domain;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+/**
+ * Entity鍩虹被
+ * 
+ * @author ruoyi
+ */
+public class BaseEntity implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鎼滅储鍊� */
+    @JsonIgnore
+    private String searchValue;
+
+    /** 鍒涘缓鑰� */
+    private String createBy;
+
+    /** 鍒涘缓鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /** 鏇存柊鑰� */
+    private String updateBy;
+
+    /** 鏇存柊鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /** 澶囨敞 */
+    private String remark;
+
+    /** 璇锋眰鍙傛暟 */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private Map<String, Object> params;
+
+    public String getSearchValue()
+    {
+        return searchValue;
+    }
+
+    public void setSearchValue(String searchValue)
+    {
+        this.searchValue = searchValue;
+    }
+
+    public String getCreateBy()
+    {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy)
+    {
+        this.createBy = createBy;
+    }
+
+    public Date getCreateTime()
+    {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime)
+    {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateBy()
+    {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy)
+    {
+        this.updateBy = updateBy;
+    }
+
+    public Date getUpdateTime()
+    {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime)
+    {
+        this.updateTime = updateTime;
+    }
+
+    public String getRemark()
+    {
+        return remark;
+    }
+
+    public void setRemark(String remark)
+    {
+        this.remark = remark;
+    }
+
+    public Map<String, Object> getParams()
+    {
+        if (params == null)
+        {
+            params = new HashMap<>();
+        }
+        return params;
+    }
+
+    public void setParams(Map<String, Object> params)
+    {
+        this.params = params;
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/web/domain/TreeEntity.java b/se-common/src/main/java/com/terra/common/web/domain/TreeEntity.java
new file mode 100644
index 0000000..7c58299
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/web/domain/TreeEntity.java
@@ -0,0 +1,79 @@
+package com.terra.common.web.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tree鍩虹被
+ * 
+ * @author ruoyi
+ */
+public class TreeEntity extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鐖惰彍鍗曞悕绉� */
+    private String parentName;
+
+    /** 鐖惰彍鍗旾D */
+    private Long parentId;
+
+    /** 鏄剧ず椤哄簭 */
+    private Integer orderNum;
+
+    /** 绁栫骇鍒楄〃 */
+    private String ancestors;
+
+    /** 瀛愰儴闂� */
+    private List<?> children = new ArrayList<>();
+
+    public String getParentName()
+    {
+        return parentName;
+    }
+
+    public void setParentName(String parentName)
+    {
+        this.parentName = parentName;
+    }
+
+    public Long getParentId()
+    {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId)
+    {
+        this.parentId = parentId;
+    }
+
+    public Integer getOrderNum()
+    {
+        return orderNum;
+    }
+
+    public void setOrderNum(Integer orderNum)
+    {
+        this.orderNum = orderNum;
+    }
+
+    public String getAncestors()
+    {
+        return ancestors;
+    }
+
+    public void setAncestors(String ancestors)
+    {
+        this.ancestors = ancestors;
+    }
+
+    public List<?> getChildren()
+    {
+        return children;
+    }
+
+    public void setChildren(List<?> children)
+    {
+        this.children = children;
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/web/page/PageDomain.java b/se-common/src/main/java/com/terra/common/web/page/PageDomain.java
new file mode 100644
index 0000000..88dd503
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/web/page/PageDomain.java
@@ -0,0 +1,101 @@
+package com.terra.common.web.page;
+
+import com.terra.common.utils.StringUtils;
+
+/**
+ * 鍒嗛〉鏁版嵁
+ * 
+ * @author ruoyi
+ */
+public class PageDomain
+{
+    /** 褰撳墠璁板綍璧峰绱㈠紩 */
+    private Integer pageNum;
+
+    /** 姣忛〉鏄剧ず璁板綍鏁� */
+    private Integer pageSize;
+
+    /** 鎺掑簭鍒� */
+    private String orderByColumn;
+
+    /** 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc */
+    private String isAsc = "asc";
+
+    /** 鍒嗛〉鍙傛暟鍚堢悊鍖� */
+    private Boolean reasonable = true;
+
+    public String getOrderBy()
+    {
+        if (StringUtils.isEmpty(orderByColumn))
+        {
+            return "";
+        }
+        return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
+    }
+
+    public Integer getPageNum()
+    {
+        return pageNum;
+    }
+
+    public void setPageNum(Integer pageNum)
+    {
+        this.pageNum = pageNum;
+    }
+
+    public Integer getPageSize()
+    {
+        return pageSize;
+    }
+
+    public void setPageSize(Integer pageSize)
+    {
+        this.pageSize = pageSize;
+    }
+
+    public String getOrderByColumn()
+    {
+        return orderByColumn;
+    }
+
+    public void setOrderByColumn(String orderByColumn)
+    {
+        this.orderByColumn = orderByColumn;
+    }
+
+    public String getIsAsc()
+    {
+        return isAsc;
+    }
+
+    public void setIsAsc(String isAsc)
+    {
+        if (StringUtils.isNotEmpty(isAsc))
+        {
+            // 鍏煎鍓嶇鎺掑簭绫诲瀷
+            if ("ascending".equals(isAsc))
+            {
+                isAsc = "asc";
+            }
+            else if ("descending".equals(isAsc))
+            {
+                isAsc = "desc";
+            }
+            this.isAsc = isAsc;
+        }
+    }
+
+    public Boolean getReasonable()
+    {
+        if (StringUtils.isNull(reasonable))
+        {
+            return Boolean.TRUE;
+        }
+        return reasonable;
+    }
+
+    public void setReasonable(Boolean reasonable)
+    {
+        this.reasonable = reasonable;
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/web/page/TableDataInfo.java b/se-common/src/main/java/com/terra/common/web/page/TableDataInfo.java
new file mode 100644
index 0000000..59b3178
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/web/page/TableDataInfo.java
@@ -0,0 +1,85 @@
+package com.terra.common.web.page;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 琛ㄦ牸鍒嗛〉鏁版嵁瀵硅薄
+ * 
+ * @author ruoyi
+ */
+public class TableDataInfo implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 鎬昏褰曟暟 */
+    private long total;
+
+    /** 鍒楄〃鏁版嵁 */
+    private List<?> rows;
+
+    /** 娑堟伅鐘舵�佺爜 */
+    private int code;
+
+    /** 娑堟伅鍐呭 */
+    private String msg;
+
+    /**
+     * 琛ㄦ牸鏁版嵁瀵硅薄
+     */
+    public TableDataInfo()
+    {
+    }
+
+    /**
+     * 鍒嗛〉
+     * 
+     * @param list 鍒楄〃鏁版嵁
+     * @param total 鎬昏褰曟暟
+     */
+    public TableDataInfo(List<?> list, long total)
+    {
+        this.rows = list;
+        this.total = total;
+    }
+
+    public long getTotal()
+    {
+        return total;
+    }
+
+    public void setTotal(long total)
+    {
+        this.total = total;
+    }
+
+    public List<?> getRows()
+    {
+        return rows;
+    }
+
+    public void setRows(List<?> rows)
+    {
+        this.rows = rows;
+    }
+
+    public int getCode()
+    {
+        return code;
+    }
+
+    public void setCode(int code)
+    {
+        this.code = code;
+    }
+
+    public String getMsg()
+    {
+        return msg;
+    }
+
+    public void setMsg(String msg)
+    {
+        this.msg = msg;
+    }
+}
\ No newline at end of file
diff --git a/se-common/src/main/java/com/terra/common/web/page/TableSupport.java b/se-common/src/main/java/com/terra/common/web/page/TableSupport.java
new file mode 100644
index 0000000..b4852ba
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/web/page/TableSupport.java
@@ -0,0 +1,56 @@
+package com.terra.common.web.page;
+
+import com.terra.common.text.Convert;
+import com.terra.common.utils.ServletUtils;
+
+/**
+ * 琛ㄦ牸鏁版嵁澶勭悊
+ * 
+ * @author ruoyi
+ */
+public class TableSupport
+{
+    /**
+     * 褰撳墠璁板綍璧峰绱㈠紩
+     */
+    public static final String PAGE_NUM = "pageNum";
+
+    /**
+     * 姣忛〉鏄剧ず璁板綍鏁�
+     */
+    public static final String PAGE_SIZE = "pageSize";
+
+    /**
+     * 鎺掑簭鍒�
+     */
+    public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+    /**
+     * 鎺掑簭鐨勬柟鍚� "desc" 鎴栬�� "asc".
+     */
+    public static final String IS_ASC = "isAsc";
+
+    /**
+     * 鍒嗛〉鍙傛暟鍚堢悊鍖�
+     */
+    public static final String REASONABLE = "reasonable";
+
+    /**
+     * 灏佽鍒嗛〉瀵硅薄
+     */
+    public static PageDomain getPageDomain()
+    {
+        PageDomain pageDomain = new PageDomain();
+        pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
+        pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
+        pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
+        pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
+        pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
+        return pageDomain;
+    }
+
+    public static PageDomain buildPageRequest()
+    {
+        return getPageDomain();
+    }
+}
diff --git a/se-common/src/main/java/com/terra/common/xss/Xss.java b/se-common/src/main/java/com/terra/common/xss/Xss.java
new file mode 100644
index 0000000..8ec1d3a
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/xss/Xss.java
@@ -0,0 +1,27 @@
+package com.terra.common.xss;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 鑷畾涔墄ss鏍¢獙娉ㄨВ
+ * 
+ * @author ruoyi
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
+@Constraint(validatedBy = { XssValidator.class })
+public @interface Xss
+{
+    String message()
+
+    default "涓嶅厑璁镐换浣曡剼鏈繍琛�";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}
diff --git a/se-common/src/main/java/com/terra/common/xss/XssValidator.java b/se-common/src/main/java/com/terra/common/xss/XssValidator.java
new file mode 100644
index 0000000..234918c
--- /dev/null
+++ b/se-common/src/main/java/com/terra/common/xss/XssValidator.java
@@ -0,0 +1,39 @@
+package com.terra.common.xss;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import com.terra.common.utils.StringUtils;
+
+/**
+ * 鑷畾涔墄ss鏍¢獙娉ㄨВ瀹炵幇
+ * 
+ * @author ruoyi
+ */
+public class XssValidator implements ConstraintValidator<Xss, String>
+{
+    private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";
+
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext)
+    {
+        if (StringUtils.isBlank(value))
+        {
+            return true;
+        }
+        return !containsHtml(value);
+    }
+
+    public static boolean containsHtml(String value)
+    {
+        StringBuilder sHtml = new StringBuilder();
+        Pattern pattern = Pattern.compile(HTML_PATTERN);
+        Matcher matcher = pattern.matcher(value);
+        while (matcher.find())
+        {
+            sHtml.append(matcher.group());
+        }
+        return pattern.matcher(sHtml).matches();
+    }
+}
\ No newline at end of file
diff --git a/se-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/se-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..d374be8
--- /dev/null
+++ b/se-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.terra.common.utils.SpringUtils

--
Gitblit v1.9.3