diff --git a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java index cec7b921da..f7bff1f5b5 100644 --- a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java +++ b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java @@ -6,6 +6,7 @@ package com.fr.design; import com.fr.base.BaseXMLUtils; import com.fr.base.Utils; import com.fr.design.actions.help.alphafine.AlphaFineConfigManager; +import com.fr.design.carton.SwitchForSwingChecker; import com.fr.design.constants.UIConstants; import com.fr.design.data.DesignTableDataManager; import com.fr.design.dialog.ErrorDialog; @@ -192,6 +193,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { private VcsConfigManager vcsConfigManager = VcsConfigManager.getInstance(); private DesignerStartupConfig designerStartupConfig = DesignerStartupConfig.getInstance(); + + private SwitchForSwingChecker switchForSwingChecker = SwitchForSwingChecker.getInstance(); public static final String CAS_CERTIFICATE_PATH = "certificatePath"; @@ -1872,6 +1875,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { readDesignerLoginAttr(reader); } else if (name.equals(fvsDesignerConfig.getName())) { readFvsDesignerConfig(reader); + } else if (name.equals(SwitchForSwingChecker.XML_TAG)) { + readSwitchForSwingCheckerAttr(reader); } else { readLayout(reader, name); } @@ -2091,6 +2096,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { reader.readXMLObject(DesignerPort.getInstance()); } + private void readSwitchForSwingCheckerAttr(XMLableReader reader) { + reader.readXMLObject(switchForSwingChecker); + } + /** * Write XML.
* The method will be invoked when save data to XML file.
@@ -2123,6 +2132,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { writeComponentReuseNotificationInfo(writer); writeDesignerLoginAttr(writer); writeFvsDesignerConfig(writer); + writeSwitchForSwingChecker(writer); writer.end(); } @@ -2437,6 +2447,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.fvsDesignerConfig.writeXML(writer); } + private void writeSwitchForSwingChecker(XMLPrintWriter writer) { + this.switchForSwingChecker.writeXML(writer); + } + enum XmlHandler { Self; diff --git a/designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java b/designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java index 31964355a3..83c3f670e6 100644 --- a/designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java +++ b/designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java @@ -1,5 +1,6 @@ package com.fr.design.carton; +import com.fr.concurrent.FineExecutors; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; import com.fr.stable.ArrayUtils; @@ -9,6 +10,7 @@ import com.fr.stable.StringUtils; import com.fr.third.ibm.icu.text.SimpleDateFormat; import org.jetbrains.annotations.NotNull; +import javax.swing.SwingUtilities; import java.awt.EventQueue; import java.awt.Toolkit; import java.awt.AWTEvent; @@ -23,6 +25,8 @@ import java.lang.management.ThreadMXBean; import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; /** * 参考自git swinghelper @@ -46,12 +50,10 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { * 开启间隔检测后两次检测的相隔时间ms */ private static final long CHECK_INTERVAL_MS = 100; - /** * 最大的事件允许执行时间,超过该时间则打印堆栈等相关信息 */ private static final long UNREASONABLE_DISPATCH_DURATION_MS = 1500; - /** * 事件唯一编码,用于方便日志的查看 */ @@ -60,21 +62,19 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { * 输出日志所在地址 */ private static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log"); - /** * 类似于一个开关,当该值为默认的false启动时,定时任务在窗口开启前都不会对执行的事件进行检查 */ private boolean haveShownSomeComponent = false; - /** * 该链表为主要的实现定时任务的容器,在重写的dispatchEvent中由pre方法将DispatchInfo加入到链表,由post方法remove */ private final LinkedList dispatches = new LinkedList(); - /** * 一个变量,用于控制easy监测模式的开关 */ private boolean easyWitch = false; + private static ScheduledExecutorService scheduledExecutorService; public boolean isEasyWitch() { return easyWitch; @@ -194,12 +194,12 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { } //事件处理完后的时间判断 public void dispose() { - if (totalTime() > UNREASONABLE_DISPATCH_DURATION_MS) { + if (timeSoFar() > UNREASONABLE_DISPATCH_DURATION_MS) { JSONObject jsonObject = new JSONObject(); jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormat.format(System.currentTimeMillis())); jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "eventQueue_" + hangNumber); jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Start_Time"), simpleDateFormat.format(startDispatchTimeMillis)); - jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), totalTime() + "ms"); + jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), timeSoFar() + "ms"); outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG); } } @@ -234,6 +234,32 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { } + /** + * 参考SwingExplorer,在处理模态框时没有做特殊处理,也不会输出卡顿堆栈 + * 原因是SwingExplorer窗口一直有一个监听事件,不断的add,remove。 + * 由于卡顿日志输出的是事件连续执行的时间,所以一个长时间存在的模态框被不断重复的监听事件刷新时间,就不会输出了。 + * 当检测开关打开后,在这里模拟一下监听事件,给个不耗时的任务就可以。 + */ + public void startFilterModalWindow() { + scheduledExecutorService = FineExecutors.newSingleThreadScheduledExecutor(); + scheduledExecutorService.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + //不用干事,切个片就可以 + } + }); + } + }, 0, 500, TimeUnit.MILLISECONDS); + } + + public void stopFilterModalWindow() { + if (scheduledExecutorService != null) { + scheduledExecutorService.shutdown(); + } + } /** * Sets up a timer to check for hangs frequently. * 初始化一个Timer @@ -363,4 +389,5 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { } return result.toString(); } + } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java b/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java index 5ed1dee310..e05d3626a1 100644 --- a/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java +++ b/designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java @@ -280,7 +280,13 @@ public class FeedbackToolboxDialog extends JDialog { } else { SwitchForSwingChecker.stopTimerChecker(); } - FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Basic_Common_Save_Successfully")); + createBodyPanel(); + remove(generalSettingPanel); + add(body); + setPreferredSize(body.getPreferredSize()); + setSwitches(!StringUtils.isEmpty(GeneralUtils.objectToString(uiDatePicker.getSelectedItem()))); + repaint(); + setVisible(true); }); actionsPanel.add(confirmButton, BorderLayout.WEST); diff --git a/designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java b/designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java index e8cd53d551..ec1b427dd0 100644 --- a/designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java +++ b/designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java @@ -10,13 +10,17 @@ import com.fr.log.FineLoggerFactory; import com.fr.stable.ProductConstantsBase; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; +import com.fr.stable.xml.XMLPrintWriter; +import com.fr.stable.xml.XMLReadable; +import com.fr.stable.xml.XMLWriter; +import com.fr.stable.xml.XMLableReader; import sun.awt.AppContext; import javax.swing.SwingWorker; +import java.io.IOException; import java.io.File; import java.io.BufferedReader; import java.io.FileReader; -import java.io.IOException; import java.text.SimpleDateFormat; import java.util.List; import java.util.ArrayList; @@ -25,13 +29,21 @@ import java.util.Map; import java.util.Date; import java.util.Calendar; -public class SwitchForSwingChecker { +public class SwitchForSwingChecker implements XMLReadable, XMLWriter { /** - * /定时任务的开关 + * Designer4Debug类名 + */ + private static final String DEBUG_MAIN_CLASS_NAME = "com.fr.start.Designer4Debug"; + /** + * XML标签 + */ + public static final String XML_TAG = "SwitchForSwingChecker"; + /** + * 定时任务的开关 */ private static boolean checkerTimerSwitch = false; /** - * /简单记录事件执行时间的开关 + * 简单记录事件执行时间的开关 */ private static boolean easyChecker = false; /** @@ -41,7 +53,7 @@ public class SwitchForSwingChecker { public static final int EASY_CHECK_FLAG = 1; /** - * /日志存储地址 + * 日志存储地址 */ public static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log"); public static final String EASY_CHECKER_FILE_NAME = "easy_check_log.csv"; @@ -54,12 +66,21 @@ public class SwitchForSwingChecker { return easyChecker; } + public static volatile SwitchForSwingChecker switchForSwingChecker = new SwitchForSwingChecker(); + + public static SwitchForSwingChecker getInstance() { + return switchForSwingChecker; + } + public static void startTimerChecker() { if (!checkerTimerSwitch) { EventDispatchThreadHangMonitor.INSTANCE.initTimer(); CartonThreadExecutorPool.getTimerThreadExecutorPool().initTimer(); EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(true); checkerTimerSwitch = true; + if (!easyChecker) { + EventDispatchThreadHangMonitor.INSTANCE.startFilterModalWindow(); + } } } @@ -69,6 +90,9 @@ public class SwitchForSwingChecker { CartonThreadExecutorPool.getTimerThreadExecutorPool().stopTimer(); EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(false); checkerTimerSwitch = false; + if (!easyChecker) { + EventDispatchThreadHangMonitor.INSTANCE.stopFilterModalWindow(); + } } } @@ -77,6 +101,9 @@ public class SwitchForSwingChecker { EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(true); CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(true); easyChecker = true; + if (!checkerTimerSwitch) { + EventDispatchThreadHangMonitor.INSTANCE.startFilterModalWindow(); + } } } @@ -85,6 +112,9 @@ public class SwitchForSwingChecker { EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(false); CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(false); easyChecker = false; + if (!checkerTimerSwitch) { + EventDispatchThreadHangMonitor.INSTANCE.stopFilterModalWindow(); + } } } @@ -215,10 +245,15 @@ public class SwitchForSwingChecker { /** * 初始化监控任务,主要是替换EventQueue以及SwingWorker执行任务的线程池 + * */ public static void initThreadMonitoring () { - EventDispatchThreadHangMonitor.initMonitoring(); - AppContext.getAppContext().put(SwingWorker.class, CartonThreadExecutorPool.getTimerThreadExecutorPool()); + String mainClass = System.getProperty("sun.java.command"); + //判断一下,如果是以Designer4Debug启动,就不注册代码,不然会覆盖掉SwingExplorer,导致其无法使用 + if (!StringUtils.equals(mainClass, DEBUG_MAIN_CLASS_NAME)) { + EventDispatchThreadHangMonitor.initMonitoring(); + AppContext.getAppContext().put(SwingWorker.class, CartonThreadExecutorPool.getTimerThreadExecutorPool()); + } } /** @@ -237,4 +272,40 @@ public class SwitchForSwingChecker { public static boolean isCartonExists() { return isCartonExists(new Date()); } + + private void initSwitchChecker() { + if (easyChecker) { + EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(true); + CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(true); + } + if (checkerTimerSwitch) { + EventDispatchThreadHangMonitor.INSTANCE.initTimer(); + CartonThreadExecutorPool.getTimerThreadExecutorPool().initTimer(); + EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(true); + } + if (easyChecker || checkerTimerSwitch) { + EventDispatchThreadHangMonitor.INSTANCE.startFilterModalWindow(); + } + } + + @Override + public void readXML(XMLableReader reader) { + if (reader.isAttr()) { + checkerTimerSwitch = reader.getAttrAsBoolean("checkerTimerSwitch", false); + easyChecker = reader.getAttrAsBoolean("easyChecker", false); + } + try { + initSwitchChecker(); + } catch (Throwable t) { + FineLoggerFactory.getLogger().error("read checker attr fail", t); + } + } + + @Override + public void writeXML(XMLPrintWriter writer) { + writer.startTAG(XML_TAG); + writer.attr("checkerTimerSwitch", checkerTimerSwitch); + writer.attr("easyChecker", easyChecker); + writer.end(); + } }