From 2297b10a86a233155006297d451b142d3f7ce3db Mon Sep 17 00:00:00 2001
From: guifei zhu <guifeizhu@guifeideiMac.local>
Date: 星期三, 21 八月 2024 17:06:41 +0800
Subject: [PATCH] mqtt初步实现

---
 jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java                                    | 1484 ++++++++++++++++++-----------------
 .gitignore                                                                                                 |    5 
 jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/impl/BaseCommonServiceImpl.java          |  142 ++-
 jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttConfig.java             |  182 ++++
 jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/MqttConstant.java                             |   45 +
 jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttUtil.java               |   12 
 jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/api/EmqxApi.java                 |   53 +
 jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/vo/MoEquVo.java                  |   24 
 jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/CommonConstant.java                           |   15 
 jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttSampleCallback.java     |  199 ++++
 jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/api/EmqxApi.txt                  |  180 ++++
 jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/controller/MobileController.java |   97 ++
 jeecg-boot-base-core/pom.xml                                                                               |   11 
 jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/BaseCommonService.java                   |    8 
 14 files changed, 1,673 insertions(+), 784 deletions(-)

diff --git a/.gitignore b/.gitignore
index a0b9717..08cb379 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,8 @@
 /.vscode/
 /.history/
 /svn clear.bat
+
+
+/target/
+**/target
+**/logs
diff --git a/jeecg-boot-base-core/pom.xml b/jeecg-boot-base-core/pom.xml
index 7a3c88b..77acfc8 100644
--- a/jeecg-boot-base-core/pom.xml
+++ b/jeecg-boot-base-core/pom.xml
@@ -252,6 +252,13 @@
 			<groupId>commons-fileupload</groupId>
 			<artifactId>commons-fileupload</artifactId>
 		</dependency>
-	</dependencies>
+    <!--MQTT client -->
+    <dependency>
+      <groupId>org.eclipse.paho</groupId>
+      <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
+      <version>1.2.5</version>
+    </dependency>
 
-</project>
\ No newline at end of file
+  </dependencies>
+
+</project>
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/CommonConstant.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/CommonConstant.java
index 684e5db..4958f11 100644
--- a/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/CommonConstant.java
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/CommonConstant.java
@@ -35,6 +35,10 @@
 	 * 绯荤粺鏃ュ織绫诲瀷锛� 鎿嶄綔
 	 */
 	int LOG_TYPE_2 = 2;
+  /**
+   * MQTT鏃ュ織
+   */
+  int LOG_TYPE_MQTT = 100;
 
 	/**
 	 * 鎿嶄綔鏃ュ織绫诲瀷锛� 鏌ヨ
@@ -65,7 +69,16 @@
 	 * 鎿嶄綔鏃ュ織绫诲瀷锛� 瀵煎嚭
 	 */
 	int OPERATE_TYPE_6 = 6;
-	
+
+
+  /**
+   * MQTT鏃ュ織
+   * 100-璁㈤槄
+   * 200-鍙戝竷
+   */
+  int OPERATE_MQTT_1 = 100;
+  int OPERATE_MQTT_2 = 200;
+
 	
 	/** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
     Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/MqttConstant.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/MqttConstant.java
new file mode 100644
index 0000000..a04fbb6
--- /dev/null
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/MqttConstant.java
@@ -0,0 +1,45 @@
+package org.jeecg.common.constant;
+
+/**
+ * Mqtt鎸囦护甯搁噺
+ */
+public interface MqttConstant {
+
+  /**************************绯荤粺璁㈤槄strat*******************************/
+  //涓婄嚎璁㈤槄
+  String MQTT_TOPIC_ONLINE = "$SYS/brokers/+/clients/+/connected";
+  //涓嬬嚎璁㈤槄
+  String MQTT_TOPIC_OFFLINE = "$SYS/brokers/+/clients/+/disconnected";
+  /**************************绯荤粺璁㈤槄end*******************************/
+
+  /**************************绉诲姩绔悜鏈嶅姟绔姹傛寚浠tart*******************************/
+  //绉诲姩绔浉鍏�
+  String MOBILE_UP = "mobile/up/#";
+
+  //鏌ヨ璁惧鐘舵��
+  //绉诲姩绔笂琛屾寚浠ゅ墠缂�锛堢Щ鍔ㄧ璇锋眰锛�
+  String MOBILE_UP_PREFIX = "mobile/up";
+
+  //璇锋眰鏌ヨ璁惧鐘舵��
+  String MOBILE_QUERY_EQU_STATU = MOBILE_UP_PREFIX + "/query/equ/statu";
+  //绉诲姩绔繙绋嬭姹傛寚浠�
+  String MOBILE_REQ_EQU_CMD = MOBILE_UP_PREFIX + "/req/equ/cmd";
+  /**************************绉诲姩绔悜鏈嶅姟绔姹傛寚浠nd*******************************/
+
+
+  /**************************鏈嶅姟绔悜绉诲姩绔搷搴旀寚浠tart*******************************/
+  //杩斿洖鏁版嵁浠呰繑鍥炵粰璇锋眰鐨勫鎴风 %s鍙戣捣璇锋眰瀹㈡埛绔痠d
+  //鏈嶅姟绔笅琛屾寚浠ゅ墠缂�锛堣繑鍥炵粰绉诲姩绔級
+  String SERVICE_DOWN_PREFIX = "service/down/res";
+  //杩斿洖绉诲姩绔煡璇㈣澶囩姸鎬�
+  String SERVICE_RES_EQU_STATU = SERVICE_DOWN_PREFIX + "/%s/statu";
+  //杩斿洖绉诲姩绔繙绋嬭姹傛寚浠�
+  String SERVICE_RES_EQU_CMD = SERVICE_DOWN_PREFIX + "/%s/cmd";
+  /**************************鏈嶅姟绔悜绉诲姩绔搷搴旀寚浠nd*******************************/
+
+
+  //redis缂撳瓨
+  String MQTT_ONLINE_CLIENT = "mqtt:online:client::";
+
+
+}
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java
index e063da5..427d8c5 100644
--- a/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java
@@ -8,6 +8,8 @@
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.GregorianCalendar;
@@ -21,743 +23,777 @@
  */
 public class DateUtils extends PropertyEditorSupport {
 
-    public static ThreadLocal<SimpleDateFormat> date_sdf = new ThreadLocal<SimpleDateFormat>() {
-        @Override
-        protected SimpleDateFormat initialValue() {
-            return new SimpleDateFormat("yyyy-MM-dd");
-        }
-    };
-    public static ThreadLocal<SimpleDateFormat> yyyyMMdd = new ThreadLocal<SimpleDateFormat>() {
-        @Override
-        protected SimpleDateFormat initialValue() {
-            return new SimpleDateFormat("yyyyMMdd");
-        }
-    };
-    public static ThreadLocal<SimpleDateFormat> date_sdf_wz = new ThreadLocal<SimpleDateFormat>() {
-        @Override
-        protected SimpleDateFormat initialValue() {
-            return new SimpleDateFormat("yyyy骞碝M鏈坉d鏃�");
-        }
-    };
-    public static ThreadLocal<SimpleDateFormat> time_sdf = new ThreadLocal<SimpleDateFormat>() {
-        @Override
-        protected SimpleDateFormat initialValue() {
-            return new SimpleDateFormat("yyyy-MM-dd HH:mm");
-        }
-    };
-    public static ThreadLocal<SimpleDateFormat> yyyymmddhhmmss = new ThreadLocal<SimpleDateFormat>() {
-        @Override
-        protected SimpleDateFormat initialValue() {
-            return new SimpleDateFormat("yyyyMMddHHmmss");
-        }
-    };
-    public static ThreadLocal<SimpleDateFormat> short_time_sdf = new ThreadLocal<SimpleDateFormat>() {
-        @Override
-        protected SimpleDateFormat initialValue() {
-            return new SimpleDateFormat("HH:mm");
-        }
-    };
-    public static ThreadLocal<SimpleDateFormat> datetimeFormat = new ThreadLocal<SimpleDateFormat>() {
-        @Override
-        protected SimpleDateFormat initialValue() {
-            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        }
-    };
-
-    /**
-     * 浠ユ绉掕〃绀虹殑鏃堕棿
-     */
-    private static final long DAY_IN_MILLIS = 24 * 3600 * 1000;
-    private static final long HOUR_IN_MILLIS = 3600 * 1000;
-    private static final long MINUTE_IN_MILLIS = 60 * 1000;
-    private static final long SECOND_IN_MILLIS = 1000;
-
-    /**
-     * 鎸囧畾妯″紡鐨勬椂闂存牸寮�
-     * @param pattern
-     * @return
-     */
-    private static SimpleDateFormat getSdFormat(String pattern) {
-        return new SimpleDateFormat(pattern);
-    }
-
-    /**
-     * 褰撳墠鏃ュ巻锛岃繖閲岀敤涓浗鏃堕棿琛ㄧず
-     *
-     * @return 浠ュ綋鍦版椂鍖鸿〃绀虹殑绯荤粺褰撳墠鏃ュ巻
-     */
-    public static Calendar getCalendar() {
-        return Calendar.getInstance();
-    }
-
-    /**
-     * 鎸囧畾姣鏁拌〃绀虹殑鏃ュ巻
-     *
-     * @param millis 姣鏁�
-     * @return 鎸囧畾姣鏁拌〃绀虹殑鏃ュ巻
-     */
-    public static Calendar getCalendar(long millis) {
-        Calendar cal = Calendar.getInstance();
-        // --------------------cal.setTimeInMillis(millis);
-        cal.setTime(new Date(millis));
-        return cal;
-    }
-
-    // ////////////////////////////////////////////////////////////////////////////
-    // getDate
-    // 鍚勭鏂瑰紡鑾峰彇鐨凞ate
-    // ////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * 褰撳墠鏃ユ湡
-     *
-     * @return 绯荤粺褰撳墠鏃堕棿
-     */
-    public static Date getDate() {
-        return new Date();
-    }
-
-    /**
-     * 鎸囧畾姣鏁拌〃绀虹殑鏃ユ湡
-     *
-     * @param millis 姣鏁�
-     * @return 鎸囧畾姣鏁拌〃绀虹殑鏃ユ湡
-     */
-    public static Date getDate(long millis) {
-        return new Date(millis);
-    }
-
-    /**
-     * 鏃堕棿鎴宠浆鎹负瀛楃涓�
-     *
-     * @param time
-     * @return
-     */
-    public static String timestamptoStr(Timestamp time) {
-        Date date = null;
-        if (null != time) {
-            date = new Date(time.getTime());
-        }
-        return date2Str(date_sdf.get());
-    }
-
-    /**
-     * 瀛楃涓茶浆鎹㈡椂闂存埑
-     *
-     * @param str
-     * @return
-     */
-    public static Timestamp str2Timestamp(String str) {
-        Date date = str2Date(str, date_sdf.get());
-        return new Timestamp(date.getTime());
-    }
-
-    /**
-     * 瀛楃涓茶浆鎹㈡垚鏃ユ湡
-     *
-     * @param str
-     * @param sdf
-     * @return
-     */
-    public static Date str2Date(String str, SimpleDateFormat sdf) {
-        if (null == str || "".equals(str)) {
-            return null;
-        }
-        Date date = null;
-        try {
-            date = sdf.parse(str);
-            return date;
-        } catch (ParseException e) {
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-    /**
-     * 鏃ユ湡杞崲涓哄瓧绗︿覆
-     *
-     * @param dateSdf 鏃ユ湡鏍煎紡
-     * @return 瀛楃涓�
-     */
-    public static String date2Str(SimpleDateFormat dateSdf) {
-        synchronized (dateSdf) {
-            Date date = getDate();
-            if (null == date) {
-                return null;
-            }
-            return dateSdf.format(date);
-        }
-    }
-
-    /**
-     * 鏍煎紡鍖栨椂闂�
-     *
-     * @param date
-     * @param format
-     * @return
-     */
-    public static String dateformat(String date, String format) {
-        SimpleDateFormat sformat = new SimpleDateFormat(format);
-        Date nowDate = null;
-        try {
-            nowDate = sformat.parse(date);
-        } catch (ParseException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-        return sformat.format(nowDate);
-    }
-
-    /**
-     * 鏃ユ湡杞崲涓哄瓧绗︿覆
-     *
-     * @param date     鏃ユ湡
-     * @param dateSdf 鏃ユ湡鏍煎紡
-     * @return 瀛楃涓�
-     */
-    public static String date2Str(Date date, SimpleDateFormat dateSdf) {
-        synchronized (dateSdf) {
-            if (null == date) {
-                return null;
-            }
-            return dateSdf.format(date);
-        }
-    }
-
-    /**
-     * 鏃ユ湡杞崲涓哄瓧绗︿覆
-     *
-     * @param format 鏃ユ湡鏍煎紡
-     * @return 瀛楃涓�
-     */
-    public static String getDate(String format) {
-        Date date = new Date();
-        if (null == date) {
-            return null;
-        }
-        SimpleDateFormat sdf = new SimpleDateFormat(format);
-        return sdf.format(date);
-    }
-
-    /**
-     * 鎸囧畾姣鏁扮殑鏃堕棿鎴�
-     *
-     * @param millis 姣鏁�
-     * @return 鎸囧畾姣鏁扮殑鏃堕棿鎴�
-     */
-    public static Timestamp getTimestamp(long millis) {
-        return new Timestamp(millis);
-    }
-
-    /**
-     * 浠ュ瓧绗﹀舰寮忚〃绀虹殑鏃堕棿鎴�
-     *
-     * @param time 姣鏁�
-     * @return 浠ュ瓧绗﹀舰寮忚〃绀虹殑鏃堕棿鎴�
-     */
-    public static Timestamp getTimestamp(String time) {
-        return new Timestamp(Long.parseLong(time));
-    }
-
-    /**
-     * 绯荤粺褰撳墠鐨勬椂闂存埑
-     *
-     * @return 绯荤粺褰撳墠鐨勬椂闂存埑
-     */
-    public static Timestamp getTimestamp() {
-        return new Timestamp(System.currentTimeMillis());
-    }
-
-    /**
-     * 褰撳墠鏃堕棿锛屾牸寮� yyyy-MM-dd HH:mm:ss
-     *
-     * @return 褰撳墠鏃堕棿鐨勬爣鍑嗗舰寮忓瓧绗︿覆
-     */
-    public static String now() {
-        return datetimeFormat.get().format(getCalendar().getTime());
-    }
-
-    /**
-     * 鎸囧畾鏃ユ湡鐨勬椂闂存埑
-     *
-     * @param date 鎸囧畾鏃ユ湡
-     * @return 鎸囧畾鏃ユ湡鐨勬椂闂存埑
-     */
-    public static Timestamp getTimestamp(Date date) {
-        return new Timestamp(date.getTime());
-    }
-
-    /**
-     * 鎸囧畾鏃ュ巻鐨勬椂闂存埑
-     *
-     * @param cal 鎸囧畾鏃ュ巻
-     * @return 鎸囧畾鏃ュ巻鐨勬椂闂存埑
-     */
-    public static Timestamp getCalendarTimestamp(Calendar cal) {
-        // ---------------------return new Timestamp(cal.getTimeInMillis());
-        return new Timestamp(cal.getTime().getTime());
-    }
-
-    public static Timestamp gettimestamp() {
-        Date dt = new Date();
-        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        String nowTime = df.format(dt);
-        java.sql.Timestamp buydate = java.sql.Timestamp.valueOf(nowTime);
-        return buydate;
-    }
-
-    // ////////////////////////////////////////////////////////////////////////////
-    // getMillis
-    // 鍚勭鏂瑰紡鑾峰彇鐨凪illis
-    // ////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * 绯荤粺鏃堕棿鐨勬绉掓暟
-     *
-     * @return 绯荤粺鏃堕棿鐨勬绉掓暟
-     */
-    public static long getMillis() {
-        return System.currentTimeMillis();
-    }
-
-    /**
-     * 鎸囧畾鏃ュ巻鐨勬绉掓暟
-     *
-     * @param cal 鎸囧畾鏃ュ巻
-     * @return 鎸囧畾鏃ュ巻鐨勬绉掓暟
-     */
-    public static long getMillis(Calendar cal) {
-        // --------------------return cal.getTimeInMillis();
-        return cal.getTime().getTime();
-    }
-
-    /**
-     * 鎸囧畾鏃ユ湡鐨勬绉掓暟
-     *
-     * @param date 鎸囧畾鏃ユ湡
-     * @return 鎸囧畾鏃ユ湡鐨勬绉掓暟
-     */
-    public static long getMillis(Date date) {
-        return date.getTime();
-    }
-
-    /**
-     * 鎸囧畾鏃堕棿鎴崇殑姣鏁�
-     *
-     * @param ts 鎸囧畾鏃堕棿鎴�
-     * @return 鎸囧畾鏃堕棿鎴崇殑姣鏁�
-     */
-    public static long getMillis(Timestamp ts) {
-        return ts.getTime();
-    }
-
-    // ////////////////////////////////////////////////////////////////////////////
-    // formatDate
-    // 灏嗘棩鏈熸寜鐓т竴瀹氱殑鏍煎紡杞寲涓哄瓧绗︿覆
-    // ////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * 榛樿鏂瑰紡琛ㄧず鐨勭郴缁熷綋鍓嶆棩鏈燂紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃�
-     *
-     * @return 榛樿鏃ユ湡鎸夆�滃勾-鏈�-鏃モ�滄牸寮忔樉绀�
-     */
-    public static String formatDate() {
-        return date_sdf.get().format(getCalendar().getTime());
-    }
-
-    /**
-     * 榛樿鏂瑰紡琛ㄧず鐨勭郴缁熷綋鍓嶆棩鏈燂紝鍏蜂綋鏍煎紡锛歽yyy-MM-dd HH:mm:ss
-     *
-     * @return 榛樿鏃ユ湡鎸夆�測yyy-MM-dd HH:mm:ss鈥滄牸寮忔樉绀�
-     */
-    public static String formatDateTime() {
-        return datetimeFormat.get().format(getCalendar().getTime());
-    }
-
-    /**
-     * 鑾峰彇鏃堕棿瀛楃涓�
-     */
-    public static String getDataString(SimpleDateFormat formatstr) {
-        synchronized (formatstr) {
-            return formatstr.format(getCalendar().getTime());
-        }
-    }
-
-    /**
-     * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃�
-     *
-     * @param cal 鎸囧畾鐨勬棩鏈�
-     * @return 鎸囧畾鏃ユ湡鎸夆�滃勾-鏈�-鏃モ�滄牸寮忔樉绀�
-     */
-    public static String formatDate(Calendar cal) {
-        return date_sdf.get().format(cal.getTime());
-    }
-
-    /**
-     * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃�
-     *
-     * @param date 鎸囧畾鐨勬棩鏈�
-     * @return 鎸囧畾鏃ユ湡鎸夆�滃勾-鏈�-鏃モ�滄牸寮忔樉绀�
-     */
-    public static String formatDate(Date date) {
-        return date_sdf.get().format(date);
-    }
-
-    /**
-     * 鎸囧畾姣鏁拌〃绀烘棩鏈熺殑榛樿鏄剧ず锛屽叿浣撴牸寮忥細骞�-鏈�-鏃�
-     *
-     * @param millis 鎸囧畾鐨勬绉掓暟
-     * @return 鎸囧畾姣鏁拌〃绀烘棩鏈熸寜鈥滃勾-鏈�-鏃モ�滄牸寮忔樉绀�
-     */
-    public static String formatDate(long millis) {
-        return date_sdf.get().format(new Date(millis));
-    }
-
-    /**
-     * 榛樿鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
-     *
-     * @param pattern 鎸囧畾鐨勬牸寮�
-     * @return 榛樿鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
-     */
-    public static String formatDate(String pattern) {
-        return getSdFormat(pattern).format(getCalendar().getTime());
-    }
-
-    /**
-     * 鎸囧畾鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
-     *
-     * @param cal     鎸囧畾鐨勬棩鏈�
-     * @param pattern 鎸囧畾鐨勬牸寮�
-     * @return 鎸囧畾鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
-     */
-    public static String formatDate(Calendar cal, String pattern) {
-        return getSdFormat(pattern).format(cal.getTime());
-    }
-
-    /**
-     * 鎸囧畾鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
-     *
-     * @param date    鎸囧畾鐨勬棩鏈�
-     * @param pattern 鎸囧畾鐨勬牸寮�
-     * @return 鎸囧畾鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
-     */
-    public static String formatDate(Date date, String pattern) {
-        return getSdFormat(pattern).format(date);
-    }
-
-    // ////////////////////////////////////////////////////////////////////////////
-    // formatTime
-    // 灏嗘棩鏈熸寜鐓т竴瀹氱殑鏍煎紡杞寲涓哄瓧绗︿覆
-    // ////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * 榛樿鏂瑰紡琛ㄧず鐨勭郴缁熷綋鍓嶆棩鏈燂紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃� 鏃讹細鍒�
-     *
-     * @return 榛樿鏃ユ湡鎸夆�滃勾-鏈�-鏃� 鏃讹細鍒嗏�滄牸寮忔樉绀�
-     */
-    public static String formatTime() {
-        return time_sdf.get().format(getCalendar().getTime());
-    }
-
-    /**
-     * 鎸囧畾姣鏁拌〃绀烘棩鏈熺殑榛樿鏄剧ず锛屽叿浣撴牸寮忥細骞�-鏈�-鏃� 鏃讹細鍒�
-     *
-     * @param millis 鎸囧畾鐨勬绉掓暟
-     * @return 鎸囧畾姣鏁拌〃绀烘棩鏈熸寜鈥滃勾-鏈�-鏃� 鏃讹細鍒嗏�滄牸寮忔樉绀�
-     */
-    public static String formatTime(long millis) {
-        return time_sdf.get().format(new Date(millis));
-    }
-
-    /**
-     * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃� 鏃讹細鍒�
-     *
-     * @param cal 鎸囧畾鐨勬棩鏈�
-     * @return 鎸囧畾鏃ユ湡鎸夆�滃勾-鏈�-鏃� 鏃讹細鍒嗏�滄牸寮忔樉绀�
-     */
-    public static String formatTime(Calendar cal) {
-        return time_sdf.get().format(cal.getTime());
-    }
-
-    /**
-     * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃� 鏃讹細鍒�
-     *
-     * @param date 鎸囧畾鐨勬棩鏈�
-     * @return 鎸囧畾鏃ユ湡鎸夆�滃勾-鏈�-鏃� 鏃讹細鍒嗏�滄牸寮忔樉绀�
-     */
-    public static String formatTime(Date date) {
-        return time_sdf.get().format(date);
-    }
-
-    // ////////////////////////////////////////////////////////////////////////////
-    // formatShortTime
-    // 灏嗘棩鏈熸寜鐓т竴瀹氱殑鏍煎紡杞寲涓哄瓧绗︿覆
-    // ////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * 榛樿鏂瑰紡琛ㄧず鐨勭郴缁熷綋鍓嶆棩鏈燂紝鍏蜂綋鏍煎紡锛氭椂锛氬垎
-     *
-     * @return 榛樿鏃ユ湡鎸夆�滄椂锛氬垎鈥滄牸寮忔樉绀�
-     */
-    public static String formatShortTime() {
-        return short_time_sdf.get().format(getCalendar().getTime());
-    }
-
-    /**
-     * 鎸囧畾姣鏁拌〃绀烘棩鏈熺殑榛樿鏄剧ず锛屽叿浣撴牸寮忥細鏃讹細鍒�
-     *
-     * @param millis 鎸囧畾鐨勬绉掓暟
-     * @return 鎸囧畾姣鏁拌〃绀烘棩鏈熸寜鈥滄椂锛氬垎鈥滄牸寮忔樉绀�
-     */
-    public static String formatShortTime(long millis) {
-        return short_time_sdf.get().format(new Date(millis));
-    }
-
-    /**
-     * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氭椂锛氬垎
-     *
-     * @param cal 鎸囧畾鐨勬棩鏈�
-     * @return 鎸囧畾鏃ユ湡鎸夆�滄椂锛氬垎鈥滄牸寮忔樉绀�
-     */
-    public static String formatShortTime(Calendar cal) {
-        return short_time_sdf.get().format(cal.getTime());
-    }
-
-    /**
-     * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氭椂锛氬垎
-     *
-     * @param date 鎸囧畾鐨勬棩鏈�
-     * @return 鎸囧畾鏃ユ湡鎸夆�滄椂锛氬垎鈥滄牸寮忔樉绀�
-     */
-    public static String formatShortTime(Date date) {
-        return short_time_sdf.get().format(date);
-    }
-
-    // ////////////////////////////////////////////////////////////////////////////
-    // parseDate
-    // parseCalendar
-    // parseTimestamp
-    // 灏嗗瓧绗︿覆鎸夌収涓�瀹氱殑鏍煎紡杞寲涓烘棩鏈熸垨鏃堕棿
-    // ////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * 鏍规嵁鎸囧畾鐨勬牸寮忓皢瀛楃涓茶浆鎹㈡垚Date 濡傝緭鍏ワ細2003-11-19 11:20:20灏嗘寜鐓ц繖涓浆鎴愭椂闂�
-     *
-     * @param src     灏嗚杞崲鐨勫師濮嬪瓧绗︾獪
-     * @param pattern 杞崲鐨勫尮閰嶆牸寮�
-     * @return 濡傛灉杞崲鎴愬姛鍒欒繑鍥炶浆鎹㈠悗鐨勬棩鏈�
-     * @throws ParseException
-     */
-    public static Date parseDate(String src, String pattern) throws ParseException {
-        return getSdFormat(pattern).parse(src);
-
-    }
-
-    /**
-     * 鏍规嵁鎸囧畾鐨勬牸寮忓皢瀛楃涓茶浆鎹㈡垚Date 濡傝緭鍏ワ細2003-11-19 11:20:20灏嗘寜鐓ц繖涓浆鎴愭椂闂�
-     *
-     * @param src     灏嗚杞崲鐨勫師濮嬪瓧绗︾獪
-     * @param pattern 杞崲鐨勫尮閰嶆牸寮�
-     * @return 濡傛灉杞崲鎴愬姛鍒欒繑鍥炶浆鎹㈠悗鐨勬棩鏈�
-     * @throws ParseException
-     */
-    public static Calendar parseCalendar(String src, String pattern) throws ParseException {
-
-        Date date = parseDate(src, pattern);
-        Calendar cal = Calendar.getInstance();
-        cal.setTime(date);
-        return cal;
-    }
-
-    public static String formatAddDate(String src, String pattern, int amount) throws ParseException {
-        Calendar cal;
-        cal = parseCalendar(src, pattern);
-        cal.add(Calendar.DATE, amount);
-        return formatDate(cal);
-    }
-
-    /**
-     * 鏍规嵁鎸囧畾鐨勬牸寮忓皢瀛楃涓茶浆鎹㈡垚Date 濡傝緭鍏ワ細2003-11-19 11:20:20灏嗘寜鐓ц繖涓浆鎴愭椂闂�
-     *
-     * @param src     灏嗚杞崲鐨勫師濮嬪瓧绗︾獪
-     * @param pattern 杞崲鐨勫尮閰嶆牸寮�
-     * @return 濡傛灉杞崲鎴愬姛鍒欒繑鍥炶浆鎹㈠悗鐨勬椂闂存埑
-     * @throws ParseException
-     */
-    public static Timestamp parseTimestamp(String src, String pattern) throws ParseException {
-        Date date = parseDate(src, pattern);
-        return new Timestamp(date.getTime());
-    }
-
-    // ////////////////////////////////////////////////////////////////////////////
-    // dateDiff
-    // 璁$畻涓や釜鏃ユ湡涔嬮棿鐨勫樊鍊�
-    // ////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * 璁$畻涓や釜鏃堕棿涔嬮棿鐨勫樊鍊硷紝鏍规嵁鏍囧織鐨勪笉鍚岃�屼笉鍚�
-     *
-     * @param flag   璁$畻鏍囧織锛岃〃绀烘寜鐓у勾/鏈�/鏃�/鏃�/鍒�/绉掔瓑璁$畻
-     * @param calSrc 鍑忔暟
-     * @param calDes 琚噺鏁�
-     * @return 涓や釜鏃ユ湡涔嬮棿鐨勫樊鍊�
-     */
-    public static int dateDiff(char flag, Calendar calSrc, Calendar calDes) {
-
-        long millisDiff = getMillis(calSrc) - getMillis(calDes);
-        char year = 'y';
-        char day = 'd';
-        char hour = 'h';
-        char minute = 'm';
-        char second = 's';
-
-        if (flag == year) {
-            return (calSrc.get(Calendar.YEAR) - calDes.get(Calendar.YEAR));
-        }
-
-        if (flag == day) {
-            return (int) (millisDiff / DAY_IN_MILLIS);
-        }
-
-        if (flag == hour) {
-            return (int) (millisDiff / HOUR_IN_MILLIS);
-        }
-
-        if (flag == minute) {
-            return (int) (millisDiff / MINUTE_IN_MILLIS);
-        }
-
-        if (flag == second) {
-            return (int) (millisDiff / SECOND_IN_MILLIS);
-        }
-
-        return 0;
-    }
-
-    public static Long getCurrentTimestamp() {
-        return Long.valueOf(DateUtils.yyyymmddhhmmss.get().format(new Date()));
-    }
-
-    /**
-     * String绫诲瀷 杞崲涓篋ate, 濡傛灉鍙傛暟闀垮害涓�10 杞崲鏍煎紡鈥漼yyy-MM-dd鈥� 濡傛灉鍙傛暟闀垮害涓�19 杞崲鏍煎紡鈥漼yyy-MM-dd
-     * HH:mm:ss鈥� * @param text String绫诲瀷鐨勬椂闂村��
-     */
+  public static ThreadLocal<SimpleDateFormat> date_sdf = new ThreadLocal<SimpleDateFormat>() {
     @Override
-    public void setAsText(String text) throws IllegalArgumentException {
-        if (StringUtils.hasText(text)) {
-            try {
-                int length10 = 10;
-                int length19 = 19;
-                if (text.indexOf(SymbolConstant.COLON) == -1 && text.length() == length10) {
-                    setValue(DateUtils.date_sdf.get().parse(text));
-                } else if (text.indexOf(SymbolConstant.COLON) > 0 && text.length() == length19) {
-                    setValue(DateUtils.datetimeFormat.get().parse(text));
-                } else {
-                    throw new IllegalArgumentException("Could not parse date, date format is error ");
-                }
-            } catch (ParseException ex) {
-                IllegalArgumentException iae = new IllegalArgumentException("Could not parse date: " + ex.getMessage());
-                iae.initCause(ex);
-                throw iae;
-            }
-        } else {
-            setValue(null);
-        }
+    protected SimpleDateFormat initialValue() {
+      return new SimpleDateFormat("yyyy-MM-dd");
     }
-
-    public static int getYear() {
-        GregorianCalendar calendar = new GregorianCalendar();
-        calendar.setTime(getDate());
-        return calendar.get(Calendar.YEAR);
+  };
+  public static ThreadLocal<SimpleDateFormat> yyyyMMdd = new ThreadLocal<SimpleDateFormat>() {
+    @Override
+    protected SimpleDateFormat initialValue() {
+      return new SimpleDateFormat("yyyyMMdd");
     }
+  };
+  public static ThreadLocal<SimpleDateFormat> date_sdf_wz = new ThreadLocal<SimpleDateFormat>() {
+    @Override
+    protected SimpleDateFormat initialValue() {
+      return new SimpleDateFormat("yyyy骞碝M鏈坉d鏃�");
+    }
+  };
+  public static ThreadLocal<SimpleDateFormat> time_sdf = new ThreadLocal<SimpleDateFormat>() {
+    @Override
+    protected SimpleDateFormat initialValue() {
+      return new SimpleDateFormat("yyyy-MM-dd HH:mm");
+    }
+  };
+  public static ThreadLocal<SimpleDateFormat> yyyymmddhhmmss = new ThreadLocal<SimpleDateFormat>() {
+    @Override
+    protected SimpleDateFormat initialValue() {
+      return new SimpleDateFormat("yyyyMMddHHmmss");
+    }
+  };
+  public static ThreadLocal<SimpleDateFormat> short_time_sdf = new ThreadLocal<SimpleDateFormat>() {
+    @Override
+    protected SimpleDateFormat initialValue() {
+      return new SimpleDateFormat("HH:mm");
+    }
+  };
+  public static ThreadLocal<SimpleDateFormat> datetimeFormat = new ThreadLocal<SimpleDateFormat>() {
+    @Override
+    protected SimpleDateFormat initialValue() {
+      return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    }
+  };
 
-    /**
-     * 灏嗗瓧绗︿覆杞垚鏃堕棿
-     * @param str
-     * @return
-     */
-    public static Date parseDatetime(String str){
-        try {
-            return datetimeFormat.get().parse(str);
-        }catch (Exception e){
-        }
+  /**
+   * 浠ユ绉掕〃绀虹殑鏃堕棿
+   */
+  private static final long DAY_IN_MILLIS = 24 * 3600 * 1000;
+  private static final long HOUR_IN_MILLIS = 3600 * 1000;
+  private static final long MINUTE_IN_MILLIS = 60 * 1000;
+  private static final long SECOND_IN_MILLIS = 1000;
+
+  /**
+   * 鎸囧畾妯″紡鐨勬椂闂存牸寮�
+   *
+   * @param pattern
+   * @return
+   */
+  private static SimpleDateFormat getSdFormat(String pattern) {
+    return new SimpleDateFormat(pattern);
+  }
+
+  /**
+   * 褰撳墠鏃ュ巻锛岃繖閲岀敤涓浗鏃堕棿琛ㄧず
+   *
+   * @return 浠ュ綋鍦版椂鍖鸿〃绀虹殑绯荤粺褰撳墠鏃ュ巻
+   */
+  public static Calendar getCalendar() {
+    return Calendar.getInstance();
+  }
+
+  /**
+   * 鎸囧畾姣鏁拌〃绀虹殑鏃ュ巻
+   *
+   * @param millis 姣鏁�
+   * @return 鎸囧畾姣鏁拌〃绀虹殑鏃ュ巻
+   */
+  public static Calendar getCalendar(long millis) {
+    Calendar cal = Calendar.getInstance();
+    // --------------------cal.setTimeInMillis(millis);
+    cal.setTime(new Date(millis));
+    return cal;
+  }
+
+  // ////////////////////////////////////////////////////////////////////////////
+  // getDate
+  // 鍚勭鏂瑰紡鑾峰彇鐨凞ate
+  // ////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * 褰撳墠鏃ユ湡
+   *
+   * @return 绯荤粺褰撳墠鏃堕棿
+   */
+  public static Date getDate() {
+    return new Date();
+  }
+
+  /**
+   * 鎸囧畾姣鏁拌〃绀虹殑鏃ユ湡
+   *
+   * @param millis 姣鏁�
+   * @return 鎸囧畾姣鏁拌〃绀虹殑鏃ユ湡
+   */
+  public static Date getDate(long millis) {
+    return new Date(millis);
+  }
+
+  /**
+   * 鏃堕棿鎴宠浆鎹负瀛楃涓�
+   *
+   * @param time
+   * @return
+   */
+  public static String timestamptoStr(Timestamp time) {
+    Date date = null;
+    if (null != time) {
+      date = new Date(time.getTime());
+    }
+    return date2Str(date_sdf.get());
+  }
+  /**
+   * 鏃堕棿鎴宠浆鎹负瀛楃涓�
+   *
+   * @param time
+   * @return
+   */
+  public static String timestamptoStr(Long time, SimpleDateFormat sdf) {
+    Date date = null;
+    if (null != time) {
+      date = new Date(time);
+    }
+    return date2Str(date, sdf);
+  }
+
+
+  /**
+   * 瀛楃涓茶浆鎹㈡椂闂存埑
+   *
+   * @param str
+   * @return
+   */
+  public static Timestamp str2Timestamp(String str) {
+    Date date = str2Date(str, date_sdf.get());
+    return new Timestamp(date.getTime());
+  }
+
+  /**
+   * 瀛楃涓茶浆鎹㈡垚鏃ユ湡
+   *
+   * @param str
+   * @param sdf
+   * @return
+   */
+  public static Date str2Date(String str, SimpleDateFormat sdf) {
+    if (null == str || "".equals(str)) {
+      return null;
+    }
+    Date date = null;
+    try {
+      date = sdf.parse(str);
+      return date;
+    } catch (ParseException e) {
+      e.printStackTrace();
+    }
+    return null;
+  }
+
+  /**
+   * 鏃ユ湡杞崲涓哄瓧绗︿覆
+   *
+   * @param dateSdf 鏃ユ湡鏍煎紡
+   * @return 瀛楃涓�
+   */
+  public static String date2Str(SimpleDateFormat dateSdf) {
+    synchronized (dateSdf) {
+      Date date = getDate();
+      if (null == date) {
         return null;
+      }
+      return dateSdf.format(date);
+    }
+  }
+
+  /**
+   * 鏍煎紡鍖栨椂闂�
+   *
+   * @param date
+   * @param format
+   * @return
+   */
+  public static String dateformat(String date, String format) {
+    SimpleDateFormat sformat = new SimpleDateFormat(format);
+    Date nowDate = null;
+    try {
+      nowDate = sformat.parse(date);
+    } catch (ParseException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    return sformat.format(nowDate);
+  }
+
+  /**
+   * 鏃ユ湡杞崲涓哄瓧绗︿覆
+   *
+   * @param date    鏃ユ湡
+   * @param dateSdf 鏃ユ湡鏍煎紡
+   * @return 瀛楃涓�
+   */
+  public static String date2Str(Date date, SimpleDateFormat dateSdf) {
+    synchronized (dateSdf) {
+      if (null == date) {
+        return null;
+      }
+      return dateSdf.format(date);
+    }
+  }
+
+  /**
+   * 鏃ユ湡杞崲涓哄瓧绗︿覆
+   *
+   * @param format 鏃ユ湡鏍煎紡
+   * @return 瀛楃涓�
+   */
+  public static String getDate(String format) {
+    Date date = new Date();
+    if (null == date) {
+      return null;
+    }
+    SimpleDateFormat sdf = new SimpleDateFormat(format);
+    return sdf.format(date);
+  }
+
+  /**
+   * 鎸囧畾姣鏁扮殑鏃堕棿鎴�
+   *
+   * @param millis 姣鏁�
+   * @return 鎸囧畾姣鏁扮殑鏃堕棿鎴�
+   */
+  public static Timestamp getTimestamp(long millis) {
+    return new Timestamp(millis);
+  }
+
+  /**
+   * 浠ュ瓧绗﹀舰寮忚〃绀虹殑鏃堕棿鎴�
+   *
+   * @param time 姣鏁�
+   * @return 浠ュ瓧绗﹀舰寮忚〃绀虹殑鏃堕棿鎴�
+   */
+  public static Timestamp getTimestamp(String time) {
+    return new Timestamp(Long.parseLong(time));
+  }
+
+  /**
+   * 绯荤粺褰撳墠鐨勬椂闂存埑
+   *
+   * @return 绯荤粺褰撳墠鐨勬椂闂存埑
+   */
+  public static Timestamp getTimestamp() {
+    return new Timestamp(System.currentTimeMillis());
+  }
+
+  /**
+   * 褰撳墠鏃堕棿锛屾牸寮� yyyy-MM-dd HH:mm:ss
+   *
+   * @return 褰撳墠鏃堕棿鐨勬爣鍑嗗舰寮忓瓧绗︿覆
+   */
+  public static String now() {
+    return datetimeFormat.get().format(getCalendar().getTime());
+  }
+
+  /**
+   * 鎸囧畾鏃ユ湡鐨勬椂闂存埑
+   *
+   * @param date 鎸囧畾鏃ユ湡
+   * @return 鎸囧畾鏃ユ湡鐨勬椂闂存埑
+   */
+  public static Timestamp getTimestamp(Date date) {
+    return new Timestamp(date.getTime());
+  }
+
+  /**
+   * 鎸囧畾鏃ュ巻鐨勬椂闂存埑
+   *
+   * @param cal 鎸囧畾鏃ュ巻
+   * @return 鎸囧畾鏃ュ巻鐨勬椂闂存埑
+   */
+  public static Timestamp getCalendarTimestamp(Calendar cal) {
+    // ---------------------return new Timestamp(cal.getTimeInMillis());
+    return new Timestamp(cal.getTime().getTime());
+  }
+
+  public static Timestamp gettimestamp() {
+    Date dt = new Date();
+    DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    String nowTime = df.format(dt);
+    java.sql.Timestamp buydate = java.sql.Timestamp.valueOf(nowTime);
+    return buydate;
+  }
+
+  // ////////////////////////////////////////////////////////////////////////////
+  // getMillis
+  // 鍚勭鏂瑰紡鑾峰彇鐨凪illis
+  // ////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * 绯荤粺鏃堕棿鐨勬绉掓暟
+   *
+   * @return 绯荤粺鏃堕棿鐨勬绉掓暟
+   */
+  public static long getMillis() {
+    return System.currentTimeMillis();
+  }
+
+  /**
+   * 鎸囧畾鏃ュ巻鐨勬绉掓暟
+   *
+   * @param cal 鎸囧畾鏃ュ巻
+   * @return 鎸囧畾鏃ュ巻鐨勬绉掓暟
+   */
+  public static long getMillis(Calendar cal) {
+    // --------------------return cal.getTimeInMillis();
+    return cal.getTime().getTime();
+  }
+
+  /**
+   * 鎸囧畾鏃ユ湡鐨勬绉掓暟
+   *
+   * @param date 鎸囧畾鏃ユ湡
+   * @return 鎸囧畾鏃ユ湡鐨勬绉掓暟
+   */
+  public static long getMillis(Date date) {
+    return date.getTime();
+  }
+
+  /**
+   * 鎸囧畾鏃堕棿鎴崇殑姣鏁�
+   *
+   * @param ts 鎸囧畾鏃堕棿鎴�
+   * @return 鎸囧畾鏃堕棿鎴崇殑姣鏁�
+   */
+  public static long getMillis(Timestamp ts) {
+    return ts.getTime();
+  }
+
+  // ////////////////////////////////////////////////////////////////////////////
+  // formatDate
+  // 灏嗘棩鏈熸寜鐓т竴瀹氱殑鏍煎紡杞寲涓哄瓧绗︿覆
+  // ////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * 榛樿鏂瑰紡琛ㄧず鐨勭郴缁熷綋鍓嶆棩鏈燂紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃�
+   *
+   * @return 榛樿鏃ユ湡鎸夆�滃勾-鏈�-鏃モ�滄牸寮忔樉绀�
+   */
+  public static String formatDate() {
+    return date_sdf.get().format(getCalendar().getTime());
+  }
+
+  /**
+   * 榛樿鏂瑰紡琛ㄧず鐨勭郴缁熷綋鍓嶆棩鏈燂紝鍏蜂綋鏍煎紡锛歽yyy-MM-dd HH:mm:ss
+   *
+   * @return 榛樿鏃ユ湡鎸夆�測yyy-MM-dd HH:mm:ss鈥滄牸寮忔樉绀�
+   */
+  public static String formatDateTime() {
+    return datetimeFormat.get().format(getCalendar().getTime());
+  }
+
+  /**
+   * 鑾峰彇鏃堕棿瀛楃涓�
+   */
+  public static String getDataString(SimpleDateFormat formatstr) {
+    synchronized (formatstr) {
+      return formatstr.format(getCalendar().getTime());
+    }
+  }
+
+  /**
+   * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃�
+   *
+   * @param cal 鎸囧畾鐨勬棩鏈�
+   * @return 鎸囧畾鏃ユ湡鎸夆�滃勾-鏈�-鏃モ�滄牸寮忔樉绀�
+   */
+  public static String formatDate(Calendar cal) {
+    return date_sdf.get().format(cal.getTime());
+  }
+
+  /**
+   * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃�
+   *
+   * @param date 鎸囧畾鐨勬棩鏈�
+   * @return 鎸囧畾鏃ユ湡鎸夆�滃勾-鏈�-鏃モ�滄牸寮忔樉绀�
+   */
+  public static String formatDate(Date date) {
+    return date_sdf.get().format(date);
+  }
+
+  /**
+   * 鎸囧畾姣鏁拌〃绀烘棩鏈熺殑榛樿鏄剧ず锛屽叿浣撴牸寮忥細骞�-鏈�-鏃�
+   *
+   * @param millis 鎸囧畾鐨勬绉掓暟
+   * @return 鎸囧畾姣鏁拌〃绀烘棩鏈熸寜鈥滃勾-鏈�-鏃モ�滄牸寮忔樉绀�
+   */
+  public static String formatDate(long millis) {
+    return date_sdf.get().format(new Date(millis));
+  }
+
+  /**
+   * 榛樿鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
+   *
+   * @param pattern 鎸囧畾鐨勬牸寮�
+   * @return 榛樿鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
+   */
+  public static String formatDate(String pattern) {
+    return getSdFormat(pattern).format(getCalendar().getTime());
+  }
+
+  /**
+   * 鎸囧畾鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
+   *
+   * @param cal     鎸囧畾鐨勬棩鏈�
+   * @param pattern 鎸囧畾鐨勬牸寮�
+   * @return 鎸囧畾鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
+   */
+  public static String formatDate(Calendar cal, String pattern) {
+    return getSdFormat(pattern).format(cal.getTime());
+  }
+
+  /**
+   * 鎸囧畾鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
+   *
+   * @param date    鎸囧畾鐨勬棩鏈�
+   * @param pattern 鎸囧畾鐨勬牸寮�
+   * @return 鎸囧畾鏃ユ湡鎸夋寚瀹氭牸寮忔樉绀�
+   */
+  public static String formatDate(Date date, String pattern) {
+    return getSdFormat(pattern).format(date);
+  }
+
+  // ////////////////////////////////////////////////////////////////////////////
+  // formatTime
+  // 灏嗘棩鏈熸寜鐓т竴瀹氱殑鏍煎紡杞寲涓哄瓧绗︿覆
+  // ////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * 榛樿鏂瑰紡琛ㄧず鐨勭郴缁熷綋鍓嶆棩鏈燂紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃� 鏃讹細鍒�
+   *
+   * @return 榛樿鏃ユ湡鎸夆�滃勾-鏈�-鏃� 鏃讹細鍒嗏�滄牸寮忔樉绀�
+   */
+  public static String formatTime() {
+    return time_sdf.get().format(getCalendar().getTime());
+  }
+
+  /**
+   * 鎸囧畾姣鏁拌〃绀烘棩鏈熺殑榛樿鏄剧ず锛屽叿浣撴牸寮忥細骞�-鏈�-鏃� 鏃讹細鍒�
+   *
+   * @param millis 鎸囧畾鐨勬绉掓暟
+   * @return 鎸囧畾姣鏁拌〃绀烘棩鏈熸寜鈥滃勾-鏈�-鏃� 鏃讹細鍒嗏�滄牸寮忔樉绀�
+   */
+  public static String formatTime(long millis) {
+    return time_sdf.get().format(new Date(millis));
+  }
+
+  /**
+   * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃� 鏃讹細鍒�
+   *
+   * @param cal 鎸囧畾鐨勬棩鏈�
+   * @return 鎸囧畾鏃ユ湡鎸夆�滃勾-鏈�-鏃� 鏃讹細鍒嗏�滄牸寮忔樉绀�
+   */
+  public static String formatTime(Calendar cal) {
+    return time_sdf.get().format(cal.getTime());
+  }
+
+  /**
+   * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氬勾-鏈�-鏃� 鏃讹細鍒�
+   *
+   * @param date 鎸囧畾鐨勬棩鏈�
+   * @return 鎸囧畾鏃ユ湡鎸夆�滃勾-鏈�-鏃� 鏃讹細鍒嗏�滄牸寮忔樉绀�
+   */
+  public static String formatTime(Date date) {
+    return time_sdf.get().format(date);
+  }
+
+  // ////////////////////////////////////////////////////////////////////////////
+  // formatShortTime
+  // 灏嗘棩鏈熸寜鐓т竴瀹氱殑鏍煎紡杞寲涓哄瓧绗︿覆
+  // ////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * 榛樿鏂瑰紡琛ㄧず鐨勭郴缁熷綋鍓嶆棩鏈燂紝鍏蜂綋鏍煎紡锛氭椂锛氬垎
+   *
+   * @return 榛樿鏃ユ湡鎸夆�滄椂锛氬垎鈥滄牸寮忔樉绀�
+   */
+  public static String formatShortTime() {
+    return short_time_sdf.get().format(getCalendar().getTime());
+  }
+
+  /**
+   * 鎸囧畾姣鏁拌〃绀烘棩鏈熺殑榛樿鏄剧ず锛屽叿浣撴牸寮忥細鏃讹細鍒�
+   *
+   * @param millis 鎸囧畾鐨勬绉掓暟
+   * @return 鎸囧畾姣鏁拌〃绀烘棩鏈熸寜鈥滄椂锛氬垎鈥滄牸寮忔樉绀�
+   */
+  public static String formatShortTime(long millis) {
+    return short_time_sdf.get().format(new Date(millis));
+  }
+
+  /**
+   * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氭椂锛氬垎
+   *
+   * @param cal 鎸囧畾鐨勬棩鏈�
+   * @return 鎸囧畾鏃ユ湡鎸夆�滄椂锛氬垎鈥滄牸寮忔樉绀�
+   */
+  public static String formatShortTime(Calendar cal) {
+    return short_time_sdf.get().format(cal.getTime());
+  }
+
+  /**
+   * 鎸囧畾鏃ユ湡鐨勯粯璁ゆ樉绀猴紝鍏蜂綋鏍煎紡锛氭椂锛氬垎
+   *
+   * @param date 鎸囧畾鐨勬棩鏈�
+   * @return 鎸囧畾鏃ユ湡鎸夆�滄椂锛氬垎鈥滄牸寮忔樉绀�
+   */
+  public static String formatShortTime(Date date) {
+    return short_time_sdf.get().format(date);
+  }
+
+  // ////////////////////////////////////////////////////////////////////////////
+  // parseDate
+  // parseCalendar
+  // parseTimestamp
+  // 灏嗗瓧绗︿覆鎸夌収涓�瀹氱殑鏍煎紡杞寲涓烘棩鏈熸垨鏃堕棿
+  // ////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * 鏍规嵁鎸囧畾鐨勬牸寮忓皢瀛楃涓茶浆鎹㈡垚Date 濡傝緭鍏ワ細2003-11-19 11:20:20灏嗘寜鐓ц繖涓浆鎴愭椂闂�
+   *
+   * @param src     灏嗚杞崲鐨勫師濮嬪瓧绗︾獪
+   * @param pattern 杞崲鐨勫尮閰嶆牸寮�
+   * @return 濡傛灉杞崲鎴愬姛鍒欒繑鍥炶浆鎹㈠悗鐨勬棩鏈�
+   * @throws ParseException
+   */
+  public static Date parseDate(String src, String pattern) throws ParseException {
+    return getSdFormat(pattern).parse(src);
+
+  }
+
+  /**
+   * 鏍规嵁鎸囧畾鐨勬牸寮忓皢瀛楃涓茶浆鎹㈡垚Date 濡傝緭鍏ワ細2003-11-19 11:20:20灏嗘寜鐓ц繖涓浆鎴愭椂闂�
+   *
+   * @param src     灏嗚杞崲鐨勫師濮嬪瓧绗︾獪
+   * @param pattern 杞崲鐨勫尮閰嶆牸寮�
+   * @return 濡傛灉杞崲鎴愬姛鍒欒繑鍥炶浆鎹㈠悗鐨勬棩鏈�
+   * @throws ParseException
+   */
+  public static Calendar parseCalendar(String src, String pattern) throws ParseException {
+
+    Date date = parseDate(src, pattern);
+    Calendar cal = Calendar.getInstance();
+    cal.setTime(date);
+    return cal;
+  }
+
+  public static String formatAddDate(String src, String pattern, int amount) throws ParseException {
+    Calendar cal;
+    cal = parseCalendar(src, pattern);
+    cal.add(Calendar.DATE, amount);
+    return formatDate(cal);
+  }
+
+  /**
+   * 鏍规嵁鎸囧畾鐨勬牸寮忓皢瀛楃涓茶浆鎹㈡垚Date 濡傝緭鍏ワ細2003-11-19 11:20:20灏嗘寜鐓ц繖涓浆鎴愭椂闂�
+   *
+   * @param src     灏嗚杞崲鐨勫師濮嬪瓧绗︾獪
+   * @param pattern 杞崲鐨勫尮閰嶆牸寮�
+   * @return 濡傛灉杞崲鎴愬姛鍒欒繑鍥炶浆鎹㈠悗鐨勬椂闂存埑
+   * @throws ParseException
+   */
+  public static Timestamp parseTimestamp(String src, String pattern) throws ParseException {
+    Date date = parseDate(src, pattern);
+    return new Timestamp(date.getTime());
+  }
+
+  // ////////////////////////////////////////////////////////////////////////////
+  // dateDiff
+  // 璁$畻涓や釜鏃ユ湡涔嬮棿鐨勫樊鍊�
+  // ////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * 璁$畻涓や釜鏃堕棿涔嬮棿鐨勫樊鍊硷紝鏍规嵁鏍囧織鐨勪笉鍚岃�屼笉鍚�
+   *
+   * @param flag   璁$畻鏍囧織锛岃〃绀烘寜鐓у勾/鏈�/鏃�/鏃�/鍒�/绉掔瓑璁$畻
+   * @param calSrc 鍑忔暟
+   * @param calDes 琚噺鏁�
+   * @return 涓や釜鏃ユ湡涔嬮棿鐨勫樊鍊�
+   */
+  public static int dateDiff(char flag, Calendar calSrc, Calendar calDes) {
+
+    long millisDiff = getMillis(calSrc) - getMillis(calDes);
+    char year = 'y';
+    char day = 'd';
+    char hour = 'h';
+    char minute = 'm';
+    char second = 's';
+
+    if (flag == year) {
+      return (calSrc.get(Calendar.YEAR) - calDes.get(Calendar.YEAR));
     }
 
-    /**
-     * 鍒ゆ柇涓や釜鏃堕棿鏄惁鏄悓涓�澶�
-     *
-     * @param date1
-     * @param date2
-     * @return
-     */
-    public static boolean isSameDay(Date date1, Date date2) {
-        if (date1 == null || date2 == null) {
-            return false;
+    if (flag == day) {
+      return (int) (millisDiff / DAY_IN_MILLIS);
+    }
+
+    if (flag == hour) {
+      return (int) (millisDiff / HOUR_IN_MILLIS);
+    }
+
+    if (flag == minute) {
+      return (int) (millisDiff / MINUTE_IN_MILLIS);
+    }
+
+    if (flag == second) {
+      return (int) (millisDiff / SECOND_IN_MILLIS);
+    }
+
+    return 0;
+  }
+
+  public static Long getCurrentTimestamp() {
+    return Long.valueOf(DateUtils.yyyymmddhhmmss.get().format(new Date()));
+  }
+
+  /**
+   * String绫诲瀷 杞崲涓篋ate, 濡傛灉鍙傛暟闀垮害涓�10 杞崲鏍煎紡鈥漼yyy-MM-dd鈥� 濡傛灉鍙傛暟闀垮害涓�19 杞崲鏍煎紡鈥漼yyy-MM-dd
+   * HH:mm:ss鈥� * @param text String绫诲瀷鐨勬椂闂村��
+   */
+  @Override
+  public void setAsText(String text) throws IllegalArgumentException {
+    if (StringUtils.hasText(text)) {
+      try {
+        int length10 = 10;
+        int length19 = 19;
+        if (text.indexOf(SymbolConstant.COLON) == -1 && text.length() == length10) {
+          setValue(DateUtils.date_sdf.get().parse(text));
+        } else if (text.indexOf(SymbolConstant.COLON) > 0 && text.length() == length19) {
+          setValue(DateUtils.datetimeFormat.get().parse(text));
+        } else {
+          throw new IllegalArgumentException("Could not parse date, date format is error ");
         }
-        Calendar calendar1 = Calendar.getInstance();
-        calendar1.setTime(date1);
-        Calendar calendar2 = Calendar.getInstance();
-        calendar2.setTime(date2);
-        boolean isSameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
-        boolean isSameMonth = isSameYear && calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
-        return isSameMonth && calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH);
+      } catch (ParseException ex) {
+        IllegalArgumentException iae = new IllegalArgumentException("Could not parse date: " + ex.getMessage());
+        iae.initCause(ex);
+        throw iae;
+      }
+    } else {
+      setValue(null);
     }
+  }
 
-    /**
-     * 鍒ゆ柇涓や釜鏃堕棿鏄惁鏄悓涓�鍛�
-     *
-     * @param date1
-     * @param date2
-     * @return
-     */
-    public static boolean isSameWeek(Date date1, Date date2) {
-        if (date1 == null || date2 == null) {
-            return false;
-        }
-        Calendar calendar1 = Calendar.getInstance();
-        calendar1.setTime(date1);
-        Calendar calendar2 = Calendar.getInstance();
-        calendar2.setTime(date2);
-        boolean isSameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
-        return isSameYear && calendar1.get(Calendar.WEEK_OF_YEAR) == calendar2.get(Calendar.WEEK_OF_YEAR);
+  public static int getYear() {
+    GregorianCalendar calendar = new GregorianCalendar();
+    calendar.setTime(getDate());
+    return calendar.get(Calendar.YEAR);
+  }
+
+  /**
+   * 灏嗗瓧绗︿覆杞垚鏃堕棿
+   *
+   * @param str
+   * @return
+   */
+  public static Date parseDatetime(String str) {
+    try {
+      return datetimeFormat.get().parse(str);
+    } catch (Exception e) {
     }
+    return null;
+  }
 
-    /**
-     * 鍒ゆ柇涓や釜鏃堕棿鏄惁鏄悓涓�鏈�
-     *
-     * @param date1
-     * @param date2
-     * @return
-     */
-    public static boolean isSameMonth(Date date1, Date date2) {
-        if (date1 == null || date2 == null) {
-            return false;
-        }
-        Calendar calendar1 = Calendar.getInstance();
-        calendar1.setTime(date1);
-        Calendar calendar2 = Calendar.getInstance();
-        calendar2.setTime(date2);
-        boolean isSameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
-        return isSameYear && calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
+  /**
+   * 鍒ゆ柇涓や釜鏃堕棿鏄惁鏄悓涓�澶�
+   *
+   * @param date1
+   * @param date2
+   * @return
+   */
+  public static boolean isSameDay(Date date1, Date date2) {
+    if (date1 == null || date2 == null) {
+      return false;
     }
+    Calendar calendar1 = Calendar.getInstance();
+    calendar1.setTime(date1);
+    Calendar calendar2 = Calendar.getInstance();
+    calendar2.setTime(date2);
+    boolean isSameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
+    boolean isSameMonth = isSameYear && calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
+    return isSameMonth && calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH);
+  }
 
-    /**
-     * 鍒ゆ柇涓や釜鏃堕棿鏄惁鏄悓涓�骞�
-     *
-     * @param date1
-     * @param date2
-     * @return
-     */
-    public static boolean isSameYear(Date date1, Date date2) {
-        if (date1 == null || date2 == null) {
-            return false;
-        }
-        Calendar calendar1 = Calendar.getInstance();
-        calendar1.setTime(date1);
-        Calendar calendar2 = Calendar.getInstance();
-        calendar2.setTime(date2);
-        return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
+  /**
+   * 鍒ゆ柇涓や釜鏃堕棿鏄惁鏄悓涓�鍛�
+   *
+   * @param date1
+   * @param date2
+   * @return
+   */
+  public static boolean isSameWeek(Date date1, Date date2) {
+    if (date1 == null || date2 == null) {
+      return false;
     }
+    Calendar calendar1 = Calendar.getInstance();
+    calendar1.setTime(date1);
+    Calendar calendar2 = Calendar.getInstance();
+    calendar2.setTime(date2);
+    boolean isSameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
+    return isSameYear && calendar1.get(Calendar.WEEK_OF_YEAR) == calendar2.get(Calendar.WEEK_OF_YEAR);
+  }
 
-}
\ No newline at end of file
+  /**
+   * 鍒ゆ柇涓や釜鏃堕棿鏄惁鏄悓涓�鏈�
+   *
+   * @param date1
+   * @param date2
+   * @return
+   */
+  public static boolean isSameMonth(Date date1, Date date2) {
+    if (date1 == null || date2 == null) {
+      return false;
+    }
+    Calendar calendar1 = Calendar.getInstance();
+    calendar1.setTime(date1);
+    Calendar calendar2 = Calendar.getInstance();
+    calendar2.setTime(date2);
+    boolean isSameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
+    return isSameYear && calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
+  }
+
+  /**
+   * 鐗规畩鏃堕棿str杞甯竤tr
+   *
+   * @param st 2024-08-14T01:07:36.761+00:00
+   * @return
+   */
+  public static String zone2Str(String st) {
+    // 瑙f瀽瀛楃涓蹭负ZonedDateTime瀵硅薄
+    ZonedDateTime zonedDateTime = ZonedDateTime.parse(st);
+    // 杞崲涓轰腑鍥芥爣鍑嗘椂闂达紙UTC+8锛�
+    ZonedDateTime cstDateTime = zonedDateTime.withZoneSameInstant(java.time.ZoneOffset.ofHours(8));
+    // 瀹氫箟鎯宠鐨勮緭鍑烘牸寮�
+    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    // 鏍煎紡鍖栦负鎯宠鐨勫瓧绗︿覆
+    String str = cstDateTime.format(formatter);
+    return str;
+  }
+
+  /**
+   * 鍒ゆ柇涓や釜鏃堕棿鏄惁鏄悓涓�骞�
+   *
+   * @param date1
+   * @param date2
+   * @return
+   */
+  public static boolean isSameYear(Date date1, Date date2) {
+    if (date1 == null || date2 == null) {
+      return false;
+    }
+    Calendar calendar1 = Calendar.getInstance();
+    calendar1.setTime(date1);
+    Calendar calendar2 = Calendar.getInstance();
+    calendar2.setTime(date2);
+    return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
+  }
+
+}
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/BaseCommonService.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/BaseCommonService.java
index 6c1de28..4b91b44 100644
--- a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/BaseCommonService.java
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/BaseCommonService.java
@@ -32,4 +32,12 @@
      */
     void addLog(String logContent, Integer logType, Integer operateType);
 
+  /**
+   * 淇濆瓨鏃ュ織
+   * @param logContent
+   * @param logType
+   * @param operateType
+   */
+  void addLog(String logContent, Integer logType, Integer operateType,Integer tenantId,String methods);
+
 }
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/impl/BaseCommonServiceImpl.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/impl/BaseCommonServiceImpl.java
index 3bd057c..dc7f7cf 100644
--- a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/impl/BaseCommonServiceImpl.java
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/impl/BaseCommonServiceImpl.java
@@ -24,67 +24,95 @@
 @Slf4j
 public class BaseCommonServiceImpl implements BaseCommonService {
 
-    @Resource
-    private BaseCommonMapper baseCommonMapper;
+  @Resource
+  private BaseCommonMapper baseCommonMapper;
 
-    @Override
-    public void addLog(LogDTO logDTO) {
-        if(oConvertUtils.isEmpty(logDTO.getId())){
-            logDTO.setId(String.valueOf(IdWorker.getId()));
-        }
-        //淇濆瓨鏃ュ織锛堝紓甯告崟鑾峰鐞嗭紝闃叉鏁版嵁澶ぇ瀛樺偍澶辫触锛屽鑷翠笟鍔″け璐ワ級JT-238
-        try {
-            logDTO.setCreateTime(new Date());
-            baseCommonMapper.saveLog(logDTO);
-        } catch (Exception e) {
-            log.warn(" LogContent length : "+logDTO.getLogContent().length());
-            log.warn(e.getMessage());
-        }
+  @Override
+  public void addLog(LogDTO logDTO) {
+    if (oConvertUtils.isEmpty(logDTO.getId())) {
+      logDTO.setId(String.valueOf(IdWorker.getId()));
+    }
+    //淇濆瓨鏃ュ織锛堝紓甯告崟鑾峰鐞嗭紝闃叉鏁版嵁澶ぇ瀛樺偍澶辫触锛屽鑷翠笟鍔″け璐ワ級JT-238
+    try {
+      logDTO.setCreateTime(new Date());
+      baseCommonMapper.saveLog(logDTO);
+    } catch (Exception e) {
+      log.warn(" LogContent length : " + logDTO.getLogContent().length());
+      log.warn(e.getMessage());
+    }
+  }
+
+  @Override
+  public void addLog(String logContent, Integer logType, Integer operatetype, LoginUser user) {
+    LogDTO sysLog = new LogDTO();
+    sysLog.setId(String.valueOf(IdWorker.getId()));
+    //娉ㄨВ涓婄殑鎻忚堪,鎿嶄綔鏃ュ織鍐呭
+    sysLog.setLogContent(logContent);
+    sysLog.setLogType(logType);
+    sysLog.setOperateType(operatetype);
+    try {
+      //鑾峰彇request
+      HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
+      //璁剧疆IP鍦板潃
+      sysLog.setIp(IpUtils.getIpAddr(request));
+    } catch (Exception e) {
+      sysLog.setIp("127.0.0.1");
+    }
+    //鑾峰彇鐧诲綍鐢ㄦ埛淇℃伅
+    if (user == null) {
+      try {
+        user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+      } catch (Exception e) {
+        //e.printStackTrace();
+      }
+    }
+    if (user != null) {
+      sysLog.setUserid(user.getUsername());
+      sysLog.setUsername(user.getRealname());
+    }
+    sysLog.setCreateTime(new Date());
+    //淇濆瓨鏃ュ織锛堝紓甯告崟鑾峰鐞嗭紝闃叉鏁版嵁澶ぇ瀛樺偍澶辫触锛屽鑷翠笟鍔″け璐ワ級JT-238
+    try {
+      baseCommonMapper.saveLog(sysLog);
+    } catch (Exception e) {
+      log.warn(" LogContent length : " + sysLog.getLogContent().length());
+      log.warn(e.getMessage());
+    }
+  }
+
+  @Override
+  public void addLog(String logContent, Integer logType, Integer operateType) {
+    addLog(logContent, logType, operateType, null);
+  }
+
+  @Override
+  public void addLog(String logContent, Integer logType, Integer operatetype, Integer tenantId, String methods) {
+    LogDTO sysLog = new LogDTO();
+    sysLog.setId(String.valueOf(IdWorker.getId()));
+    //娉ㄨВ涓婄殑鎻忚堪,鎿嶄綔鏃ュ織鍐呭
+    sysLog.setLogContent(logContent);
+    sysLog.setLogType(logType);
+    sysLog.setOperateType(operatetype);
+    sysLog.setMethod(methods);
+    sysLog.setTenantId(tenantId);
+    try {
+      //鑾峰彇request
+      HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
+      //璁剧疆IP鍦板潃
+      sysLog.setIp(IpUtils.getIpAddr(request));
+    } catch (Exception e) {
+      sysLog.setIp("127.0.0.1");
     }
 
-    @Override
-    public void addLog(String logContent, Integer logType, Integer operatetype, LoginUser user) {
-        LogDTO sysLog = new LogDTO();
-        sysLog.setId(String.valueOf(IdWorker.getId()));
-        //娉ㄨВ涓婄殑鎻忚堪,鎿嶄綔鏃ュ織鍐呭
-        sysLog.setLogContent(logContent);
-        sysLog.setLogType(logType);
-        sysLog.setOperateType(operatetype);
-        try {
-            //鑾峰彇request
-            HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
-            //璁剧疆IP鍦板潃
-            sysLog.setIp(IpUtils.getIpAddr(request));
-        } catch (Exception e) {
-            sysLog.setIp("127.0.0.1");
-        }
-        //鑾峰彇鐧诲綍鐢ㄦ埛淇℃伅
-        if(user==null){
-            try {
-                user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
-            } catch (Exception e) {
-                //e.printStackTrace();
-            }
-        }
-        if(user!=null){
-            sysLog.setUserid(user.getUsername());
-            sysLog.setUsername(user.getRealname());
-        }
-        sysLog.setCreateTime(new Date());
-        //淇濆瓨鏃ュ織锛堝紓甯告崟鑾峰鐞嗭紝闃叉鏁版嵁澶ぇ瀛樺偍澶辫触锛屽鑷翠笟鍔″け璐ワ級JT-238
-        try {
-            baseCommonMapper.saveLog(sysLog);
-        } catch (Exception e) {
-            log.warn(" LogContent length : "+sysLog.getLogContent().length());
-            log.warn(e.getMessage());
-        }
+    sysLog.setCreateTime(new Date());
+    //淇濆瓨鏃ュ織锛堝紓甯告崟鑾峰鐞嗭紝闃叉鏁版嵁澶ぇ瀛樺偍澶辫触锛屽鑷翠笟鍔″け璐ワ級JT-238
+    try {
+      baseCommonMapper.saveLog(sysLog);
+    } catch (Exception e) {
+      log.warn(" LogContent length : " + sysLog.getLogContent().length());
+      log.warn(e.getMessage());
     }
-
-    @Override
-    public void addLog(String logContent, Integer logType, Integer operateType) {
-        addLog(logContent, logType, operateType, null);
-    }
-
+  }
 
 
 }
diff --git a/jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/api/EmqxApi.java b/jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/api/EmqxApi.java
new file mode 100644
index 0000000..9e0fdc6
--- /dev/null
+++ b/jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/api/EmqxApi.java
@@ -0,0 +1,53 @@
+package org.jeecg.modules.dry.api;
+
+import com.alibaba.fastjson.JSONObject;
+import okhttp3.Credentials;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+/**
+ * emqx rest api
+ * 鍏ュ弬鍑哄弬鍙傝�冿細https://docs.emqx.com/zh/emqx/v5.7/admin/api-docs.html
+ */
+@Component
+public class EmqxApi {
+  @Value(value = "${jeecg.mqtt.emqx_api_key}")
+  private String emqxApiKey;
+  @Value(value = "${jeecg.mqtt.emqx_secret_key}")
+  private String emqxSecretKey;
+  @Value(value = "${jeecg.mqtt.emqx_base}")
+  private String emqxBaseUrl;
+
+  //鎵�鏈夊鎴风
+  public static final String CMD_CLIENTS = "/clients";
+  //鏌ヨ涓�涓鎴风鐘舵��
+  public static final String CMD_CLIENTS_CLIENT = "/clients/%s";
+
+  /**
+   * EMQX鎺ュ彛
+   *
+   * @return
+   */
+  public JSONObject queryEmqx(String cmd) {
+    try {
+      OkHttpClient client = new OkHttpClient();
+      Request request = new Request.Builder()
+        .url(emqxBaseUrl + cmd)
+        .header("Content-Type", "application/json")
+        .header("Authorization", Credentials.basic(emqxApiKey, emqxSecretKey))
+        .build();
+
+      Response response = client.newCall(request).execute();
+      String res = response.body().string();
+      return JSONObject.parseObject(res);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return null;
+  }
+}
diff --git a/jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/api/EmqxApi.txt b/jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/api/EmqxApi.txt
new file mode 100644
index 0000000..064d6bd
--- /dev/null
+++ b/jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/api/EmqxApi.txt
@@ -0,0 +1,180 @@
+//鎺ュ彛杩斿洖鏁版嵁绀轰緥
+1.clients:
+{
+    "data": [
+        {
+            "recv_msg.qos0": 0,
+            "recv_oct": 603,
+            "recv_msg.qos2": 0,
+            "clean_start": true,
+            "enable_authn": true,
+            "send_msg.dropped.queue_full": 0,
+            "proto_name": "MQTT",
+            "listener": "tcp:default",
+            "send_msg.qos0": 28,
+            "user_property": {},
+            "keepalive": 60,
+            "username": "tongjitang",
+            "proto_ver": 5,
+            "node": "emqx@172.17.0.2",
+            "mqueue_dropped": 0,
+            "send_cnt": 243,
+            "ip_address": "172.17.0.1",
+            "created_at": "2024-08-07T01:23:29.226+00:00",
+            "auth_expire_at": null,
+            "recv_msg.qos1": 0,
+            "durable": false,
+            "is_bridge": false,
+            "recv_msg.dropped": 0,
+            "subscriptions_cnt": 5,
+            "send_oct": 5886,
+            "expiry_interval": 0,
+            "heap_size": 610,
+            "awaiting_rel_cnt": 0,
+            "connected_at": "2024-08-07T01:23:29.226+00:00",
+            "clientid": "1000_GM003",
+            "inflight_cnt": 0,
+            "port": 38422,
+            "send_msg.dropped.expired": 0,
+            "send_msg": 28,
+            "mailbox_len": 0,
+            "mountpoint": null,
+            "send_msg.qos2": 0,
+            "recv_msg.dropped.await_pubrel_timeout": 0,
+            "recv_msg": 0,
+            "send_msg.qos1": 0,
+            "send_msg.dropped.too_large": 0,
+            "send_msg.dropped": 0,
+            "subscriptions_max": "infinity",
+            "send_pkt": 243,
+            "inflight_max": 32,
+            "recv_pkt": 215,
+            "client_attrs": {},
+            "connected": true,
+            "reductions": 204416,
+            "awaiting_rel_max": 100,
+            "is_persistent": false,
+            "mqueue_max": 1000,
+            "mqueue_len": 0,
+            "recv_cnt": 215,
+            "is_expired": false
+        },
+        {
+            "recv_msg.qos0": 0,
+            "recv_oct": 468,
+            "recv_msg.qos2": 0,
+            "clean_start": true,
+            "enable_authn": true,
+            "send_msg.dropped.queue_full": 0,
+            "proto_name": "MQTT",
+            "listener": "tcp:default",
+            "send_msg.qos0": 0,
+            "user_property": {},
+            "keepalive": 60,
+            "username": "tongjitang",
+            "proto_ver": 5,
+            "node": "emqx@172.17.0.2",
+            "mqueue_dropped": 0,
+            "send_cnt": 210,
+            "ip_address": "172.17.0.1",
+            "created_at": "2024-08-07T01:23:50.589+00:00",
+            "auth_expire_at": null,
+            "recv_msg.qos1": 0,
+            "durable": false,
+            "is_bridge": false,
+            "recv_msg.dropped": 0,
+            "subscriptions_cnt": 0,
+            "send_oct": 442,
+            "expiry_interval": 0,
+            "heap_size": 610,
+            "awaiting_rel_cnt": 0,
+            "connected_at": "2024-08-07T01:23:50.589+00:00",
+            "clientid": "1000_GM002",
+            "inflight_cnt": 0,
+            "port": 38424,
+            "send_msg.dropped.expired": 0,
+            "send_msg": 0,
+            "mailbox_len": 0,
+            "mountpoint": null,
+            "send_msg.qos2": 0,
+            "recv_msg.dropped.await_pubrel_timeout": 0,
+            "recv_msg": 0,
+            "send_msg.qos1": 0,
+            "send_msg.dropped.too_large": 0,
+            "send_msg.dropped": 0,
+            "subscriptions_max": "infinity",
+            "send_pkt": 210,
+            "inflight_max": 32,
+            "recv_pkt": 210,
+            "client_attrs": {},
+            "connected": true,
+            "reductions": 171935,
+            "awaiting_rel_max": 100,
+            "is_persistent": false,
+            "mqueue_max": 1000,
+            "mqueue_len": 0,
+            "recv_cnt": 210,
+            "is_expired": false
+        },
+        {
+            "recv_msg.qos0": 1,
+            "recv_msg.qos2": 0,
+            "clean_start": false,
+            "enable_authn": true,
+            "send_msg.dropped.queue_full": 0,
+            "proto_name": "MQTT",
+            "listener": "tcp:default",
+            "send_msg.qos0": 0,
+            "user_property": {},
+            "keepalive": 10,
+            "username": "tongjitang",
+            "proto_ver": 4,
+            "node": "emqx@172.17.0.2",
+            "mqueue_dropped": 0,
+            "ip_address": "172.17.0.1",
+            "created_at": "2024-08-07T01:23:13.724+00:00",
+            "auth_expire_at": null,
+            "recv_msg.qos1": 0,
+            "durable": false,
+            "is_bridge": false,
+            "recv_msg.dropped": 0,
+            "subscriptions_cnt": 1,
+            "disconnected_at": "2024-08-07T04:52:44.267+00:00",
+            "expiry_interval": 7200,
+            "heap_size": 610,
+            "awaiting_rel_cnt": 0,
+            "connected_at": "2024-08-07T02:41:51.865+00:00",
+            "clientid": "1000_GM001",
+            "inflight_cnt": 0,
+            "port": 38454,
+            "send_msg.dropped.expired": 0,
+            "send_msg": 0,
+            "mailbox_len": 0,
+            "mountpoint": null,
+            "send_msg.qos2": 0,
+            "recv_msg.dropped.await_pubrel_timeout": 0,
+            "recv_msg": 1,
+            "send_msg.qos1": 0,
+            "send_msg.dropped.too_large": 0,
+            "send_msg.dropped": 0,
+            "subscriptions_max": "infinity",
+            "send_pkt": 786,
+            "inflight_max": 32,
+            "recv_pkt": 787,
+            "client_attrs": {},
+            "connected": false,
+            "reductions": 386694,
+            "awaiting_rel_max": 100,
+            "is_persistent": true,
+            "mqueue_max": 1000,
+            "mqueue_len": 0,
+            "is_expired": false
+        }
+    ],
+    "meta": {
+        "count": 3,
+        "limit": 100,
+        "page": 1,
+        "hasnext": false
+    }
+}
diff --git a/jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/vo/MoEquVo.java b/jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/vo/MoEquVo.java
new file mode 100644
index 0000000..43436ca
--- /dev/null
+++ b/jeecg-module-dry/jeecg-module-dry-api/src/main/java/org/jeecg/modules/dry/vo/MoEquVo.java
@@ -0,0 +1,24 @@
+package org.jeecg.modules.dry.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.jeecg.modules.dry.entity.DryEquipment;
+import org.springframework.beans.BeanUtils;
+
+/**
+ * 绉诲姩绔�-骞茬嚗鏈�
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class MoEquVo extends DryEquipment {
+  //璁惧鏄惁鍦ㄧ嚎
+  private Boolean online;
+  //璁惧宸ヤ綔鐘舵��
+  private Integer statu;
+  //寮�鏈烘椂闂�
+  private String upTime;
+  //MQTT瀹㈡埛绔痠d
+  private String clientId;
+
+
+}
diff --git a/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/controller/MobileController.java b/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/controller/MobileController.java
new file mode 100644
index 0000000..d67b9d5
--- /dev/null
+++ b/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/controller/MobileController.java
@@ -0,0 +1,97 @@
+package org.jeecg.modules.dry.controller;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.config.TenantContext;
+import org.jeecg.common.constant.MqttConstant;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.common.util.RedisUtil;
+import org.jeecg.common.util.oConvertUtils;
+import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
+import org.jeecg.modules.dry.api.EmqxApi;
+import org.jeecg.modules.dry.entity.DryEquipment;
+import org.jeecg.modules.dry.service.IDryEquipmentService;
+import org.jeecg.modules.dry.vo.MoEquVo;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Api(tags = "绉诲姩绔�")
+@RestController
+@RequestMapping("/mobile")
+@Slf4j
+public class MobileController {
+  @Autowired
+  private IDryEquipmentService dryEquipmentService;
+  @Autowired
+  private RedisUtil redisUtil;
+
+  @ApiOperation(value = "璁惧鍒楄〃鏌ヨ", notes = "璁惧鍒楄〃鏌ヨ")
+  @GetMapping(value = "/equ/list")
+  public Result<IPage<MoEquVo>> queryPageList(DryEquipment dryEquipment, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
+    //------------------------------------------------------------------------------------------------
+    //鏄惁寮�鍚郴缁熺鐞嗘ā鍧楃殑澶氱鎴锋暟鎹殧绂汇�怱AAS澶氱鎴锋ā寮忋��
+    if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
+      dryEquipment.setTenantId(oConvertUtils.getInt(TenantContext.getTenant(), 0));
+    }
+    //------------------------------------------------------------------------------------------------
+    QueryWrapper<DryEquipment> queryWrapper = QueryGenerator.initQueryWrapper(dryEquipment, req.getParameterMap());
+    Page<DryEquipment> page = new Page<DryEquipment>(pageNo, pageSize);
+    Page<MoEquVo> voPage = new Page<MoEquVo>(pageNo, pageSize);
+    IPage<DryEquipment> pageList = dryEquipmentService.page(page, queryWrapper);
+
+
+    comp(pageList, voPage);
+
+
+    return Result.OK(voPage);
+  }
+
+  private void comp(IPage<DryEquipment> pageList, Page<MoEquVo> page) {
+
+
+    //褰撳墠绉熸埛id
+    int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
+
+
+    List<MoEquVo> collect = pageList.getRecords().stream().map(item -> {
+      MoEquVo vo = new MoEquVo();
+      BeanUtils.copyProperties(item, vo);
+      String clientid = "client-" + tenantId + "-" + item.getCode();
+      JSONObject client = (JSONObject) redisUtil.get(MqttConstant.MQTT_ONLINE_CLIENT + clientid);
+      //缁勮鐘舵�佹暟鎹�
+      if (client != null) {
+        vo.setOnline(true);
+        //杩炴帴鏃堕棿
+        String st = client.getString("connectedAt");
+        vo.setUpTime(st);
+        vo.setClientId(clientid);
+      }
+      return vo;
+    }).collect(Collectors.toList());
+    //鎺掑簭
+    collect.sort(Comparator.comparing(obj -> obj.getCode(), Comparator.nullsLast(Comparator.naturalOrder())));
+    collect.sort(Comparator.comparing(obj -> obj.getOnline(), Comparator.nullsLast(Comparator.naturalOrder())));
+    BeanUtils.copyProperties(pageList, page);
+    page.setRecords(collect);
+  }
+
+
+}
diff --git a/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttConfig.java b/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttConfig.java
new file mode 100644
index 0000000..395d41d
--- /dev/null
+++ b/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttConfig.java
@@ -0,0 +1,182 @@
+package org.jeecg.modules.dry.mqtt;
+
+import cn.hutool.core.thread.ThreadUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.paho.client.mqttv3.*;
+import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
+import org.jeecg.common.constant.MqttConstant;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.common.util.RedisUtil;
+import org.jeecg.modules.dry.api.EmqxApi;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.*;
+
+/**
+ * mqtt
+ */
+@Slf4j
+@Configuration
+public class MqttConfig {
+  @Value(value = "${jeecg.mqtt.broker}")
+  private String broker;
+  @Value(value = "${jeecg.mqtt.mqtt_name}")
+  private String mqttName;
+  @Value(value = "${jeecg.mqtt.mqtt_pass}")
+  private String mqttPass;
+  @Value(value = "${jeecg.mqtt.mqtt_client_id}")
+  private String mqttClientId;
+  @Value(value = "${jeecg.mqtt.role}")
+  private String role;
+
+  @Autowired
+  private MqttSampleCallback mqttSampleCallback;
+  @Autowired
+  private MqttUtil mqttUtil;
+  @Autowired
+  private RedisUtil redisUtil;
+  @Autowired
+  private EmqxApi emqxApi;
+
+
+  @Bean
+  public void initMqtt() {
+    conn();
+    reconn();
+  }
+
+  /**
+   * mqtt杩炴帴閰嶇疆
+   */
+  private void conn() {
+    MemoryPersistence persistence = new MemoryPersistence();
+    MqttConnectOptions mqttConnOpt = new MqttConnectOptions();
+    mqttConnOpt.setUserName(mqttName);
+    mqttConnOpt.setPassword(mqttPass.toCharArray());
+    mqttConnOpt.setKeepAliveInterval(10);//璁剧疆蹇冭烦闂撮殧
+    mqttConnOpt.setConnectionTimeout(10);//璁剧疆杩炴帴瓒呮椂鏃堕棿
+    mqttConnOpt.setCleanSession(false);//璁剧疆鏄惁娓呴櫎浼氳瘽
+    mqttConnOpt.setAutomaticReconnect(false);//璁剧疆鏄惁鑷姩閲嶈繛
+
+    //閬楀槺娑堟伅 TODO qos2闇�瑕佸湪璁惧涓婄嚎鏃跺仛娓呴櫎娑堟伅鎿嶄綔
+    mqttConnOpt.setWill("downline", ("鎴戞槸" + mqttName + "_" + mqttClientId + "锛屾垜涓嬬嚎浜�").getBytes(), 2, false);
+    try {
+
+      MqttClient mqttClient = new MqttClient(broker, mqttClientId, persistence);
+      mqttClient.connect(mqttConnOpt);
+      if (mqttClient.isConnected()) {
+        System.err.println("杩炴帴鎴愬姛");
+        // 鍒涘缓娑堟伅骞惰缃� QoS
+        String content = "鎴戞槸" + mqttName + "_" + mqttClientId + "锛屾垜涓婄嚎浜�";
+        MqttMessage message = new MqttMessage(content.getBytes());
+        message.setQos(0);
+        // 娴嬭瘯鍙戝竷娑堟伅
+        mqttClient.publish("topline", message);
+        mqttClient.subscribe("message", 0);
+
+        mqttClient.setCallback(mqttSampleCallback);
+        mqttUtil.setMqttClient(mqttClient);
+        //涓嶅悓鐨勮鑹查渶瑕佷笉鍚岀殑璁㈤槄
+        switch (role) {
+          //绠$悊鍛�
+          case "admin":
+            //璁㈤槄绯荤粺绾ц澶囦笂涓嬬嚎閫氱煡
+            mqttClient.subscribe(MqttConstant.MQTT_TOPIC_ONLINE);
+            mqttClient.subscribe(MqttConstant.MQTT_TOPIC_OFFLINE);
+
+            //璁㈤槄绉诲姩绔笂琛屾寚浠�
+            mqttClient.subscribe(MqttConstant.MOBILE_UP);
+            System.err.println("admin璁㈤槄" + MqttConstant.MOBILE_UP);
+            initClients();
+
+            break;
+          //鏅�氱敤鎴�
+          case "user":
+            //鏅�氬鎴风鍙渶璁㈤槄鑷韩鐩稿叧娑堟伅
+            mqttClient.subscribe(MqttConstant.SERVICE_DOWN_PREFIX + "/" + mqttClientId + "/#");
+            System.err.println("user璁㈤槄" + MqttConstant.SERVICE_DOWN_PREFIX + "/" + mqttClientId + "/#");
+            break;
+
+        }
+
+      } else {
+        System.err.println("杩炴帴澶辫触");
+      }
+
+    } catch (MqttException e) {
+      e.printStackTrace();
+    }
+
+  }
+
+  //閲嶈繛
+  private void reconn() {
+    Timer timer = new Timer();
+
+    TimerTask task = new TimerTask() {
+      @Override
+      public void run() {
+        // 鍦ㄨ繖閲岀紪鍐欏畾鏃舵墽琛岀殑浠诲姟閫昏緫
+        System.out.println("瀹氭椂浠诲姟鎵ц锛�" + new java.util.Date());
+        if (mqttUtil.getMqttClient() == null || !mqttUtil.getMqttClient().isConnected()) {
+          try {
+            conn();
+          } catch (Exception e) {
+            e.printStackTrace();
+          }
+        }
+      }
+    };
+
+    // 璁惧畾瀹氭椂浠诲姟锛屽欢杩�0姣鍚庡紑濮嬫墽琛岋紝姣忛殧1000姣锛�1绉掞級鎵ц涓�娆�
+    timer.schedule(task, 0, 10000);
+
+  }
+
+  /**
+   * 鏈嶅姟绔紙admin瑙掕壊锛夊惎鍔ㄦ椂鏌ヨ鎵�鏈夎澶囧苟缂撳瓨鍒皉edis
+   */
+  private void initClients() {
+    redisUtil.del(MqttConstant.MQTT_ONLINE_CLIENT);
+
+    JSONObject clients = emqxApi.queryEmqx(EmqxApi.CMD_CLIENTS);
+    //TODO 鏍规嵁emqx杩斿洖缂栧啓瀹炰綋绫�
+    if (clients != null && clients.containsKey("data")) {
+      JSONArray data = clients.getJSONArray("data");
+      for (int i = 0; i < data.size(); i++) {
+        JSONObject obj = data.getJSONObject(i);
+        JSONObject item = new JSONObject();
+        //username
+        item.put("username", obj.get("username"));
+        //杩炴帴鏃堕棿
+        String st = obj.getString("connected_at");
+        String upTime = DateUtils.zone2Str(st);
+        item.put("connectedAt", upTime);
+        //clientid
+        String clientid = obj.getString("clientid");
+        item.put("clientid", clientid);
+        //鏄惁杩炴帴
+        Boolean connected = obj.getBoolean("connected");
+        item.put("connected", connected);
+        //
+        String[] info = clientid.split("-");
+        item.put("type", info[0]);
+        item.put("tenantId", info[1]);
+        item.put("code", info[2]);
+
+        if (connected) {
+          redisUtil.set(MqttConstant.MQTT_ONLINE_CLIENT + clientid, item);
+        }
+
+
+      }
+    }
+  }
+
+
+}
diff --git a/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttSampleCallback.java b/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttSampleCallback.java
new file mode 100644
index 0000000..55c571f
--- /dev/null
+++ b/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttSampleCallback.java
@@ -0,0 +1,199 @@
+package org.jeecg.modules.dry.mqtt;
+
+import cn.hutool.core.thread.ThreadUtil;
+import com.alibaba.fastjson.JSONObject;
+import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
+import org.eclipse.paho.client.mqttv3.MqttCallback;
+import org.eclipse.paho.client.mqttv3.MqttMessage;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.constant.MqttConstant;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.common.util.RedisUtil;
+import org.jeecg.modules.base.service.BaseCommonService;
+import org.jeecg.modules.dry.api.EmqxApi;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Component
+@Scope("prototype")
+public class MqttSampleCallback implements MqttCallback {
+  @Value(value = "${jeecg.mqtt.role}")
+  private String role;
+  @Autowired
+  private MqttUtil mqttUtil;
+  @Autowired
+  private EmqxApi emqxApi;
+  @Autowired
+  private BaseCommonService baseCommonService;
+  @Autowired
+  private RedisUtil redisUtil;
+
+
+  @Override
+  public void connectionLost(Throwable throwable) {
+    System.err.println("杩炴帴鏂紑锛氾細鎺夌嚎");
+  }
+
+  @Override
+  public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
+    System.out.println("鏀跺埌娑堟伅: \n  topic锛�" + topic + "\n  Qos锛�" + mqttMessage.getQos() + "\n  payload锛�"
+      + new String(mqttMessage.getPayload()));
+
+    switch (role) {
+      // 绠$悊鍛�
+      case "admin":
+        String message = new String(mqttMessage.getPayload());
+        JSONObject messageJson = JSONObject.parseObject(message);
+
+        if (topic.startsWith("$SYS/brokers/") && topic.endsWith("connected")) {
+          JSONObject client = (JSONObject) redisUtil.get(MqttConstant.MQTT_ONLINE_CLIENT + messageJson.get("clientid"));
+          if (client == null) {
+            JSONObject item = new JSONObject();
+            //username
+            item.put("username", messageJson.get("username"));
+            //杩炴帴鏃堕棿
+            Long st = messageJson.getLong("connected_at");
+            String upTime = DateUtils.timestamptoStr(st, DateUtils.datetimeFormat.get());
+            item.put("connectedAt", upTime);
+            //clientid
+            String clientid = messageJson.getString("clientid");
+            item.put("clientid", clientid);
+            //鏄惁杩炴帴
+            item.put("connected", true);
+            //
+            String[] info = clientid.split("-");
+            item.put("type", info[0]);
+            item.put("tenantId", info[1]);
+            item.put("code", info[2]);
+
+            redisUtil.set(MqttConstant.MQTT_ONLINE_CLIENT + clientid, item);
+            System.err.println(String.format("璁惧: %s涓婄嚎", clientid));
+          }
+
+        }
+        if (topic.startsWith("$SYS/brokers/") && topic.endsWith("disconnected")) {
+          String clientid = messageJson.getString("clientid");
+          redisUtil.del(MqttConstant.MQTT_ONLINE_CLIENT + clientid);
+          System.err.println(String.format("璁惧: %s涓嬬嚎", clientid));
+        }
+        parseAdminCommand(topic, mqttMessage);
+
+        break;
+      // 鏅�氱敤鎴�
+      case "user":
+        System.err.println("user");
+        parseUserCommand(topic, mqttMessage);
+        break;
+
+    }
+
+  }
+
+
+  @Override
+  public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
+    System.err.println("娑堟伅浼犻�掓垚鍔�");
+  }
+
+  // 瑙f瀽admin瑙掕壊鎸囦护
+  private void parseAdminCommand(String topic, MqttMessage mqttMessage) {
+    String message = new String(mqttMessage.getPayload());
+    JSONObject messageJson = JSONObject.parseObject(message);
+
+    //璇锋眰鐨勫鎴风(鏈嶅姟绔彧鎺ㄩ�佹暟鎹埌璇锋眰鐨勫鎴风)
+    StringBuilder req = new StringBuilder();
+    if (messageJson.containsKey("req")) {
+      req.append(messageJson.get("req"));
+    }
+    //鍓嶇浼犲弬鏃堕棿鎴宠浆鎹�
+    if (messageJson.containsKey("timestamp")) {
+      messageJson.put("timestamp", DateUtils.zone2Str(messageJson.get("timestamp").toString()));
+    }
+    baseCommonService.addLog(message, CommonConstant.LOG_TYPE_MQTT, CommonConstant.OPERATE_MQTT_1);
+    switch (topic) {
+      // 鏌ヨ璁惧鍦ㄧ嚎
+      case MqttConstant.MOBILE_QUERY_EQU_STATU:
+        System.err.println("admin鏀跺埌" + topic);
+        // 鏍规嵁璁惧id鏌ヨ璁惧mqtt鍦ㄧ嚎鐘舵��
+        String clientId = messageJson.getString("clientId");
+        JSONObject client = (JSONObject) redisUtil.get(MqttConstant.MQTT_ONLINE_CLIENT + clientId);
+
+        ThreadUtil.execute(() -> {
+
+          if (client == null || client.isEmpty()) {
+            JSONObject res = new JSONObject();
+            res.put("success", false);
+            res.put("msg", "鏌ヨ澶辫触");
+            try {
+              MqttMessage sendMessage = new MqttMessage(res.toJSONString().getBytes());
+              sendMessage.setQos(0);
+              mqttUtil.getMqttClient().publish(String.format(MqttConstant.SERVICE_RES_EQU_STATU, req), sendMessage);
+            } catch (Exception e) {
+              e.printStackTrace();
+            }
+            return;
+          }
+
+          client.put("success", true);
+          client.put("msg", "鏌ヨ鎴愬姛");
+          try {
+            MqttMessage sendMessage = new MqttMessage(client.toJSONString().getBytes());
+            sendMessage.setQos(0);
+            mqttUtil.getMqttClient().publish(String.format(MqttConstant.SERVICE_RES_EQU_STATU, req), sendMessage);
+            baseCommonService.addLog(client.toString(), CommonConstant.LOG_TYPE_MQTT, CommonConstant.OPERATE_MQTT_2);
+          } catch (Exception e) {
+            e.printStackTrace();
+          }
+        });
+        break;
+
+    }
+
+  }
+
+
+  // 瑙f瀽user瑙掕壊鎸囦护
+  private void parseUserCommand(String topic, MqttMessage mqttMessage) {
+
+    String message = new String(mqttMessage.getPayload());
+    JSONObject messageJson = JSONObject.parseObject(message);
+
+    //璇锋眰鐨勫鎴风(鏈嶅姟绔彧鎺ㄩ�佹暟鎹埌璇锋眰鐨勫鎴风)
+    StringBuilder req = new StringBuilder();
+    if (messageJson.containsKey("req")) {
+      req.append(messageJson.get("req"));
+    }
+    //鍓嶇浼犲弬鏃堕棿鎴宠浆鎹�
+    if (messageJson.containsKey("timestamp")) {
+      messageJson.put("timestamp", DateUtils.zone2Str(messageJson.get("timestamp").toString()));
+    }
+
+    switch (topic) {
+      case MqttConstant.MOBILE_REQ_EQU_CMD:
+        System.err.println("user鏀跺埌" + topic);
+        System.err.println(message);
+        ThreadUtil.execute(() -> {
+          //TODO 鍚慞LC鍙戦�佸紑鍏虫満鎿嶄綔锛屽苟杩斿洖淇℃伅
+          JSONObject res = new JSONObject();
+          res.put("success", true);
+          res.put("msg", "鎿嶄綔鎴愬姛");
+          try {
+            MqttMessage sendMessage = new MqttMessage(JSONObject.toJSONString(res).getBytes());
+            sendMessage.setQos(0);
+            mqttUtil.getMqttClient().publish(String.format(MqttConstant.SERVICE_RES_EQU_CMD, req), sendMessage);
+            baseCommonService.addLog(res.toString(), CommonConstant.LOG_TYPE_MQTT, CommonConstant.OPERATE_MQTT_2);
+          } catch (Exception e) {
+            e.printStackTrace();
+          }
+
+        });
+
+
+        break;
+    }
+
+  }
+
+}
diff --git a/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttUtil.java b/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttUtil.java
new file mode 100644
index 0000000..b744404
--- /dev/null
+++ b/jeecg-module-dry/jeecg-module-dry-biz/src/main/java/org/jeecg/modules/dry/mqtt/MqttUtil.java
@@ -0,0 +1,12 @@
+package org.jeecg.modules.dry.mqtt;
+
+import lombok.Data;
+import org.eclipse.paho.client.mqttv3.MqttClient;
+import org.springframework.stereotype.Component;
+
+@Component
+@Data
+public class MqttUtil {
+  public   MqttClient mqttClient;
+
+}

--
Gitblit v1.9.3