diff --git a/designer-base/src/main/java/com/fr/design/carton/DocumentType.java b/designer-base/src/main/java/com/fr/design/carton/CartonFiles.java similarity index 90% rename from designer-base/src/main/java/com/fr/design/carton/DocumentType.java rename to designer-base/src/main/java/com/fr/design/carton/CartonFiles.java index 57646a4b1b..c2e39def91 100644 --- a/designer-base/src/main/java/com/fr/design/carton/DocumentType.java +++ b/designer-base/src/main/java/com/fr/design/carton/CartonFiles.java @@ -2,10 +2,11 @@ package com.fr.design.carton; import java.io.File; -public class DocumentType { +public class CartonFiles { private File easyCheckerFile; private File timerCheckerFile; - public DocumentType() { + + public CartonFiles() { } diff --git a/designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java b/designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java index 3e99445491..624bb2bb69 100644 --- a/designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java +++ b/designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java @@ -12,11 +12,6 @@ import java.util.concurrent.atomic.AtomicLong; public class CartonThreadExecutorPool extends ThreadPoolExecutor { - /** - * 一个标识位用于区分耗时任务时长检测(简单检测)和timer检测 - */ - private static final int TIMER_CHECK_FLAG = 0; - private static final int EASY_CHECK_FLAG = 1; private static final int MAX_LIVE_TIME = 3000; private static final int MAX_WORKER_THREADS = 10; /** @@ -72,7 +67,7 @@ public class CartonThreadExecutorPool extends ThreadPoolExecutor { jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "swingWorker_" + hangNumber); jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Duration_Task_Execute"), timeSoFar()); jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info"), stackTrace); - EventDispatchThreadHangMonitor.outPutJournalLog(jsonObject.toString(), TIMER_CHECK_FLAG); + EventDispatchThreadHangMonitor.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG); EventDispatchThreadHangMonitor.checkForDeadlock(); } } @@ -94,6 +89,7 @@ public class CartonThreadExecutorPool extends ThreadPoolExecutor { return thread; } }; + public static CartonThreadExecutorPool getTimerThreadExecutorPool () { if (cartonThreadExecutorPool == null) { synchronized (CartonThreadExecutorPool.class) { @@ -108,6 +104,7 @@ public class CartonThreadExecutorPool extends ThreadPoolExecutor { } return cartonThreadExecutorPool; } + private CartonThreadExecutorPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); simpleDateFormatThreadSafe.applyPattern("yyyy-MM-dd HH:mm:ss"); @@ -119,6 +116,7 @@ public class CartonThreadExecutorPool extends ThreadPoolExecutor { startReportedStack.set(t.getStackTrace()); concurrentHashMap.put(t.getId(), new ThreadInfo()); } + @Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); @@ -131,11 +129,12 @@ public class CartonThreadExecutorPool extends ThreadPoolExecutor { jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "swingWorker_" + concurrentHashMap.get(currentThreadId).hangNumber); jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Start_Time"), simpleDateFormatThreadSafe.format(concurrentHashMap.get(currentThreadId).startTime)); jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), runTime); - EventDispatchThreadHangMonitor.outPutJournalLog(jsonObject.toString(), EASY_CHECK_FLAG); + EventDispatchThreadHangMonitor.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG); } concurrentHashMap.remove(currentThreadId); } + public class Checker extends TimerTask { @Override public void run() { @@ -147,6 +146,7 @@ public class CartonThreadExecutorPool extends ThreadPoolExecutor { } } } + public void initTimer() { timer = new Timer("CheckerSwingWorker",true); timer.schedule(new Checker(), 0, CHECK_INTERVAL_MS); diff --git a/designer-base/src/main/java/com/fr/design/carton/CartonUploadMessage.java b/designer-base/src/main/java/com/fr/design/carton/CartonUploadMessage.java index 01a2cf5565..2c9c2bacae 100644 --- a/designer-base/src/main/java/com/fr/design/carton/CartonUploadMessage.java +++ b/designer-base/src/main/java/com/fr/design/carton/CartonUploadMessage.java @@ -6,6 +6,7 @@ public class CartonUploadMessage { private String slowTime; private String threadTime; private String info; + public CartonUploadMessage() { } 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 f7f6d68f75..31964355a3 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 @@ -2,13 +2,16 @@ package com.fr.design.carton; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; +import com.fr.stable.ArrayUtils; import com.fr.stable.ProductConstantsBase; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; import com.fr.third.ibm.icu.text.SimpleDateFormat; -import org.gradle.internal.impldep.com.google.gson.JsonObject; +import org.jetbrains.annotations.NotNull; -import java.awt.*; +import java.awt.EventQueue; +import java.awt.Toolkit; +import java.awt.AWTEvent; import java.awt.event.WindowEvent; import java.io.BufferedWriter; import java.io.File; @@ -30,11 +33,6 @@ import java.util.TimerTask; */ public final class EventDispatchThreadHangMonitor extends EventQueue { - /** - * 一个标识位用于区分耗时任务时长检测(简单检测)和timer检测 - */ - private static final int TIMER_CHECK_FLAG = 0; - private static final int EASY_CHECK_FLAG = 1; /** * 日期事件格式 */ @@ -52,29 +50,29 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { /** * 最大的事件允许执行时间,超过该时间则打印堆栈等相关信息 */ - private static final long UNREASONABLE_DISPATCH_DURATION_MS = 2000; + private static final long UNREASONABLE_DISPATCH_DURATION_MS = 1500; /** - * /事件唯一编码,用于方便日志的查看 + * 事件唯一编码,用于方便日志的查看 */ private static long hangCount = 0; /** - * /输出日志所在地址 + * 输出日志所在地址 */ private static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log"); /** - * /类似于一个开关,当该值为默认的false启动时,定时任务在窗口开启前都不会对执行的事件进行检查 + * 类似于一个开关,当该值为默认的false启动时,定时任务在窗口开启前都不会对执行的事件进行检查 */ private boolean haveShownSomeComponent = false; /** - * /该链表为主要的实现定时任务的容器,在重写的dispatchEvent中由pre方法将DispatchInfo加入到链表,由post方法remove + * 该链表为主要的实现定时任务的容器,在重写的dispatchEvent中由pre方法将DispatchInfo加入到链表,由post方法remove */ private final LinkedList dispatches = new LinkedList(); /** - * /一个变量,用于控制easy监测模式的开关 + * 一个变量,用于控制easy监测模式的开关 */ private boolean easyWitch = false; @@ -87,8 +85,7 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { } /** - * /一个变量,用于记录Timer的开关。 - * + * 一个变量,用于记录Timer的开关。 */ public boolean isTimerWitch() { @@ -104,9 +101,15 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { private synchronized static long getHangCount() { return hangCount++; } - public static boolean stacksEqual(StackTraceElement[] a, StackTraceElement[] b) { - if (a.length != b.length) { + /** + * @param a can not be null + * @param b can not be null + * @return + */ + public static boolean stacksEqual(@NotNull StackTraceElement[] a, @NotNull StackTraceElement[] b) { + + if (!ArrayUtils.isSameLength(a, b)) { return false; } for (int i = 0; i < a.length; ++i) { @@ -118,24 +121,29 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { } /** - * / 用于堆栈的比较 + * 用于判断是不是特定的堆栈 */ public static boolean stackTraceElementIs(StackTraceElement e, String className, String methodName, boolean isNative) { return e.getClassName().equals(className) && e.getMethodName().equals(methodName) && e.isNativeMethod() == isNative; } /** - * /用于判断某个堆栈是否在等待另一个事件 + * 用于判断某个堆栈是否在等待另一个事件 + * 取当前堆栈前三层判断是是不是匹配等待堆栈的格式 */ public static boolean isWaitingForNextEvent(StackTraceElement[] currentStack) { - return stackTraceElementIs(currentStack[0], "java.lang.Object", "wait", true) && stackTraceElementIs(currentStack[1], "java.lang.Object", "wait", false) && stackTraceElementIs(currentStack[2], "java.awt.EventQueue", "getNextEvent", false); + + return currentStack != null && currentStack.length >= 3 && + stackTraceElementIs(currentStack[0], "java.lang.Object", "wait", true) + && stackTraceElementIs(currentStack[1], "java.lang.Object", "wait", false) + && stackTraceElementIs(currentStack[2], "java.awt.EventQueue", "getNextEvent", false); } /** - * /event事件的包装类 + * event事件的包装类 */ public static class DispatchInfo { - // 上一次被打印的堆栈 + // 上一次被打印的堆栈ou private StackTraceElement[] lastReportedStack; //获取执行该事件的线程 private final Thread eventDispatchThread = Thread.currentThread(); @@ -162,7 +170,7 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { if (isWaitingForNextEvent(currentStack)) { return; } -// 某个事件执行时间很长,定时处理时可能会连续打很多个堆栈,对同一个事件的相同堆栈只打一次 + //某个事件执行时间很长,定时处理时可能会连续打很多个堆栈,对同一个事件的相同堆栈只打一次 if (lastReportedStack !=null && stacksEqual(lastReportedStack, currentStack)) { return; } @@ -173,7 +181,7 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { 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_Duration_Task_Execute"), timeSoFar()); jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info"), stackTrace); - outPutJournalLog(jsonObject.toString(), TIMER_CHECK_FLAG); + outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG); checkForDeadlock(); } //记录连续运行了多长时间 @@ -192,14 +200,15 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { 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"); - outPutJournalLog(jsonObject.toString(), EASY_CHECK_FLAG); + outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG); } } } + public static void outPutJournalLog(String message, int flag) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); String date = simpleDateFormat.format(System.currentTimeMillis()); - String filename = flag == EASY_CHECK_FLAG ? "easy_check_log.csv": "timer_check_log.csv"; + String filename = flag == SwitchForSwingChecker.EASY_CHECK_FLAG ? SwitchForSwingChecker.EASY_CHECKER_FILE_NAME: SwitchForSwingChecker.TIMER_CHECKER_FILE_NAME; String[] split = date.split("-"); int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]); String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date); @@ -262,7 +271,6 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { } /** - * Sets up hang detection for the event dispatch thread. * 将swing中默认的EventQueue换成自己的 */ public static void initMonitoring() { @@ -292,6 +300,7 @@ public final class EventDispatchThreadHangMonitor extends EventQueue { } } } + /** * Starts tracking a dispatch. */ 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 74fa03f645..5ed1dee310 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 @@ -19,7 +19,6 @@ import com.fr.file.FILEChooserPane; import com.fr.file.filter.ChooseFileFilter; import com.fr.general.GeneralUtils; import com.fr.log.FineLoggerFactory; -import com.fr.stable.ProductConstantsBase; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; @@ -30,17 +29,11 @@ import java.awt.event.MouseEvent; import java.awt.event.WindowEvent; import java.io.File; import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.List; public class FeedbackToolboxDialog extends JDialog { - /** - * 定时执行的任务 - */ - private static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log"); private UIDatePicker uiDatePicker; private JPanel generalSettingPanel = null; private UICheckBox easyCheckerButton = null; @@ -86,18 +79,13 @@ public class FeedbackToolboxDialog extends JDialog { //空格布局会好看一点 title.setText(" " + Toolkit.i18nText("Fine-Design_Basic_Carton_Record_Lag_Time") + ": "); //判断一下当天是否有卡顿日志记录,如果有将日期设置为当天,如果没有设置为空 - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - String date = simpleDateFormat.format(new Date()); - String[] split = date.split("-"); - int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]); - String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date); - File file = new File(dirPath); - if (file.exists()) { + boolean cartonExists = SwitchForSwingChecker.isCartonExists(); + if (cartonExists) { this.uiDatePicker = new UIDatePicker(UIDatePicker.STYLE_CN_DATE1, this); } else { this.uiDatePicker = new UIDatePicker(UIDatePicker.STYLE_CN_DATE1, null, this); } - Dimension dimension = new Dimension(150, 100); + Dimension dimension = new Dimension(160, 100); uiDatePicker.setPreferredSize(dimension); northPane.add(GUICoreUtils.createFlowPane(new Component[]{title, uiDatePicker}, FlowLayout.LEFT)); exportLogLabel = new UILabel(); @@ -123,6 +111,7 @@ public class FeedbackToolboxDialog extends JDialog { northPane.add(GUICoreUtils.createFlowPane(exportLogLabel, FlowLayout.RIGHT)); return northPane; } + private void exportLogFile() { String selectDate = GeneralUtils.objectToString(uiDatePicker.getSelectedItem()); FILEChooserPane fileChooserPane = FILEChooserPane.getInstance(); @@ -138,7 +127,7 @@ public class FeedbackToolboxDialog extends JDialog { //selectDate 2002-03-09例子 String[] split = selectDate.split("-"); int month = Integer.parseInt(split[1]); - File sourceFile = new File(StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, selectDate)); + File sourceFile = new File(StableUtils.pathJoin(SwitchForSwingChecker.JOURNAL_FILE_PATH, split[0], "month-" + month, selectDate)); if (sourceFile.exists()) { File[] files = sourceFile.listFiles(); if (files != null) { @@ -160,6 +149,7 @@ public class FeedbackToolboxDialog extends JDialog { fileChooserPane.removeAllFilter(); } } + private JPanel createTailPane() { JPanel tailPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); tailPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, lineColor)); 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 b16d779cd2..e8cd53d551 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,10 +10,20 @@ import com.fr.log.FineLoggerFactory; import com.fr.stable.ProductConstantsBase; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; +import sun.awt.AppContext; -import java.io.*; +import javax.swing.SwingWorker; +import java.io.File; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.List; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Date; +import java.util.Calendar; public class SwitchForSwingChecker { /** @@ -25,12 +35,17 @@ public class SwitchForSwingChecker { */ private static boolean easyChecker = false; /** - * /日志存储地址 + * 一个标识位用于区分耗时任务时长检测(简单检测)和timer检测 */ - private static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log"); - private static final String EASY_CHECKER_FILE_NAME = "easy_check_log.csv"; - private static final String TIMER_CHECKER_FILE_NAME = "timer_check_log.csv"; + public static final int TIMER_CHECK_FLAG = 0; + 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"; + public static final String TIMER_CHECKER_FILE_NAME = "timer_check_log.csv"; public static boolean isCheckerTimerSwitch() { return checkerTimerSwitch; } @@ -76,7 +91,7 @@ public class SwitchForSwingChecker { /** * 获取文件名字以及判断文件是否存在 */ - private static DocumentType getFiles(String date) { + private static CartonFiles getFiles(String date) { String[] split = date.split("-"); int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]); String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date); @@ -85,10 +100,10 @@ public class SwitchForSwingChecker { File[] files = new File[2]; files[0] = file1; files[1] = file2; - DocumentType documentType = new DocumentType(); - documentType.setEasyCheckerFile(file1); - documentType.setTimerCheckerFile(file2); - return documentType; + CartonFiles cartonFiles = new CartonFiles(); + cartonFiles.setEasyCheckerFile(file1); + cartonFiles.setTimerCheckerFile(file2); + return cartonFiles; } /** @@ -148,6 +163,7 @@ public class SwitchForSwingChecker { } return res; } + private static List getEasyFileCartonLog(File file) { List res = new ArrayList<>(); try { @@ -176,17 +192,14 @@ public class SwitchForSwingChecker { return res; } - - - /** * /埋点方法上传卡顿信息入口 date为 2022-09-08的格式 */ public static List uploadJournalLog(Date dateTime) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); List res = new ArrayList<>(); - DocumentType files = getFiles(simpleDateFormat.format(dateTime)); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + CartonFiles files = getFiles(simpleDateFormat.format(dateTime)); File easyCheckerFile = files.getEasyCheckerFile(); File timerCheckerFile = files.getTimerCheckerFile(); if (easyCheckerFile.exists() && timerCheckerFile.exists()) { @@ -199,4 +212,29 @@ public class SwitchForSwingChecker { return res; } } + + /** + * 初始化监控任务,主要是替换EventQueue以及SwingWorker执行任务的线程池 + */ + public static void initThreadMonitoring () { + EventDispatchThreadHangMonitor.initMonitoring(); + AppContext.getAppContext().put(SwingWorker.class, CartonThreadExecutorPool.getTimerThreadExecutorPool()); + } + + /** + * 判断是否有指定日期的卡顿日志,没有就返回false + */ + public static boolean isCartonExists(Date date) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String format = simpleDateFormat.format(date); + Calendar calendar = Calendar.getInstance(); + int month = calendar.get(Calendar.MONTH) + 1; + int year = calendar.get(Calendar.YEAR); + File file = new File(StableUtils.pathJoin(JOURNAL_FILE_PATH, String.valueOf(year), "month-" + month, format)); + return file.exists(); + } + + public static boolean isCartonExists() { + return isCartonExists(new Date()); + } } diff --git a/designer-base/src/main/java/com/fr/design/gui/date/JDateDocument.java b/designer-base/src/main/java/com/fr/design/gui/date/JDateDocument.java index 1ef24a83bc..4fa06ef7a2 100644 --- a/designer-base/src/main/java/com/fr/design/gui/date/JDateDocument.java +++ b/designer-base/src/main/java/com/fr/design/gui/date/JDateDocument.java @@ -10,8 +10,9 @@ import javax.swing.text.JTextComponent; import javax.swing.text.PlainDocument; /** + * */ -public class JDateDocument extends PlainDocument{ +public class JDateDocument extends PlainDocument { private JTextComponent textComponent; //日期输入文本框 private SimpleDateFormat dateFormat; @@ -26,7 +27,7 @@ public class JDateDocument extends PlainDocument{ ** 调用者:类JDateDocument *******************************************************************/ public JDateDocument(JTextComponent tc, SimpleDateFormat dateFormat) throws - UnsupportedOperationException{ + UnsupportedOperationException { //当前日期构造 this(tc, dateFormat, getCurrentDate(dateFormat)); } @@ -34,50 +35,61 @@ public class JDateDocument extends PlainDocument{ public JDateDocument(JTextComponent tc, SimpleDateFormat dateFormat, String initDateTime) throws - UnsupportedOperationException{ - //设置当前日期格式 - setDateFormat(dateFormat); - //保存操作的文本框 - textComponent = tc; - //设置显示为当前日期,同时完成显示的格式化 - try{ - insertString(0, initDateTime, null); - } catch(BadLocationException ex){ - throw new UnsupportedOperationException(ex.getMessage()); - } + UnsupportedOperationException { + this(tc, dateFormat, initDateTime, false); } + + /** + * + * @param tc + * @param dateFormat + * @param initDateTime + * @param initTime 判断是不是要通过insertString设置默认值 + * @throws UnsupportedOperationException + */ public JDateDocument(JTextComponent tc, SimpleDateFormat dateFormat, - int emptyDateTime) throws - UnsupportedOperationException{ + String initDateTime, + boolean initTime) throws + UnsupportedOperationException { //设置当前日期格式 setDateFormat(dateFormat); //保存操作的文本框 textComponent = tc; - //给了第三个int类型的参数说明不要一个默认的日期作为初始值 + //设置显示为当前日期,同时完成显示的格式化,如果emptyDateTime为true就设时间为空 + if (!initTime) { + try { + insertString(0, initDateTime, null); + } catch (BadLocationException ex) { + throw new UnsupportedOperationException(ex.getMessage()); + } + } } /** * 设置当前日期格式 + * * @param dateFormat SimpleDateFormat */ - public void setDateFormat(SimpleDateFormat dateFormat){ + public void setDateFormat(SimpleDateFormat dateFormat) { this.dateFormat = dateFormat; } /** * 取得当前日期格式 + * * @return SimpleDateFormat */ - public SimpleDateFormat getDateFormat(){ + public SimpleDateFormat getDateFormat() { return dateFormat; } /** * 取得当前系统日时 + * * @return String */ - public static String getCurrentDate(SimpleDateFormat smFormat){ + public static String getCurrentDate(SimpleDateFormat smFormat) { return smFormat.format(new Date()); } @@ -92,15 +104,15 @@ public class JDateDocument extends PlainDocument{ ** 调用者:类JDateDocument *******************************************************************/ public void insertString(int offset, String s, - AttributeSet attributeSet) throws BadLocationException{ + AttributeSet attributeSet) throws BadLocationException { String toTest; //用于测试输入合法性的字符串 //判断插入字符串长度 - if(s.length() == 1){ + if (s.length() == 1) { //长度为1 - try{ + try { //限制输入为整数 Integer.parseInt(s); - } catch(Exception ex){ + } catch (Exception ex) { //错误则提示并返回 Toolkit.getDefaultToolkit().beep(); return; @@ -108,14 +120,14 @@ public class JDateDocument extends PlainDocument{ //取得原始插入位置 int newOffset = offset; //如果插入位置为"/"," ","-"符号的前面,则移动到其后面插入(改变newOffset的值) - if(offset == 4 || offset == 7 || + if (offset == 4 || offset == 7 || offset == 10 || offset == 13 || - offset == 16){ + offset == 16) { newOffset++; textComponent.setCaretPosition(newOffset); } //如果插入位置为最后,则不插入 - if(offset == dateFormat.toPattern().length()){ + if (offset == dateFormat.toPattern().length()) { return; } //取得显示的时间,处理后得到要显示的字符串 @@ -124,7 +136,7 @@ public class JDateDocument extends PlainDocument{ toTest.substring(newOffset + 1); //如果要显示的字符串合法,则显示,否则给出提示并退出 boolean isValid = isValidDate(toTest); - if(!isValid){ + if (!isValid) { Toolkit.getDefaultToolkit().beep(); return; } @@ -133,9 +145,9 @@ public class JDateDocument extends PlainDocument{ super.insertString(newOffset, s, attributeSet); } //如果插入长度10 - else if(s.length() == 10 || s.length() == 19){ + else if (s.length() == 10 || s.length() == 19) { //合法则显示,否则给出提示退出 - if(!isValidDate(s)){ + if (!isValidDate(s)) { Toolkit.getDefaultToolkit().beep(); return; } @@ -153,10 +165,10 @@ public class JDateDocument extends PlainDocument{ ** 返回值:无 ** 调用者:insertString(int, String,AttributeSet) ***********************************************************************************/ - public void remove(int offset, int length) throws BadLocationException{ + public void remove(int offset, int length) throws BadLocationException { //如果插入位置在"-"前,则回退一个光标位置 //yyyy-MM-dd HH:mm:ss - if(offset == 4 || offset == 7 || + if (offset == 4 || offset == 7 || offset == 10 || offset == 13 || offset == 16) textComponent.setCaretPosition(offset - 1); @@ -173,32 +185,32 @@ public class JDateDocument extends PlainDocument{ ** 返回值:boolean型,真,表示是合法的,假,表示不合法 ** 调用者:insertString(int, String,AttributeSet) ***********************************************************************************/ - private boolean isValidDate(String strDate){ + private boolean isValidDate(String strDate) { int intY, intM, intD; //年,月,日,时,分,秒的值 int intH = 0, intMi = 0, intS = 0; int iCaretPosition; //光标位置 int iPatternLen = getDateFormat().toPattern().length(); //获取字符串 - if(strDate == null){ + if (strDate == null) { return false; } strDate = strDate.trim(); //如果为空,长度不对,则为非法,返回false - if(strDate.length() != iPatternLen){ + if (strDate.length() != iPatternLen) { return false; } //如果是全角字符,则返回false - for(int i = 0; i < 10; i++){ - if(((int)strDate.charAt(i)) > 255){ + for (int i = 0; i < 10; i++) { + if (((int) strDate.charAt(i)) > 255) { return false; } } //取年,月,日的值 - try{ + try { intY = Integer.parseInt(strDate.substring(0, 4)); intM = Integer.parseInt(strDate.substring(5, 7)); intD = Integer.parseInt(strDate.substring(8, 10)); - } catch(Exception e){ + } catch (Exception e) { //失败则返回false return false; } @@ -207,23 +219,23 @@ public class JDateDocument extends PlainDocument{ boolean isValid = true; //月越界 - if(intM > 12 || intM < 1){ + if (intM > 12 || intM < 1) { intM = Math.min(12, Math.max(1, intM)); isValid = false; } //根据月份,判断日期输入,如越界,则修改 - if(intD < 1){ + if (intD < 1) { intD = 1; isValid = false; } - switch(intM){ + switch (intM) { case 4: case 6: case 9: case 11: //最大天数为30天 //如果输入大于30,则修改为30 - if(intD > 30){ + if (intD > 30) { intD = 30; isValid = false; } @@ -231,15 +243,15 @@ public class JDateDocument extends PlainDocument{ case 2: //2月份 //区别闰年 - if((intY % 4 == 0 && intY % 100 != 0) || intY % 400 == 0){ + if ((intY % 4 == 0 && intY % 100 != 0) || intY % 400 == 0) { //如果输入大于29,则修改为29 - if(intD > 29){ + if (intD > 29) { intD = 29; isValid = false; } - } else{ + } else { //如果输入大于28,则修改为28 - if(intD > 28){ + if (intD > 28) { intD = 28; isValid = false; } @@ -248,7 +260,7 @@ public class JDateDocument extends PlainDocument{ default: //最大天数为31天 //如果输入大于31,则修改为31 - if(intD > 31){ + if (intD > 31) { intD = 31; isValid = false; } @@ -256,31 +268,31 @@ public class JDateDocument extends PlainDocument{ // System.err.println("out:intY="+intY+",intM="+intM+",intD="+intD); //yyyy-MM-dd HH:mm:ss - if(iPatternLen > 10){ - try{ + if (iPatternLen > 10) { + try { intH = Integer.parseInt(strDate.substring(11, 13)); intMi = Integer.parseInt(strDate.substring(14, 16)); intS = Integer.parseInt(strDate.substring(17)); - } catch(Exception e){ + } catch (Exception e) { return false; } //时越界 - if(intH > 23 || intH < 0){ + if (intH > 23 || intH < 0) { intH = Math.min(23, Math.max(0, intH)); isValid = false; } //分越界 - if(intMi > 59 || intMi < 0){ + if (intMi > 59 || intMi < 0) { intMi = Math.min(59, Math.max(0, intMi)); isValid = false; } //秒越界 - if(intS > 59 || intS < 0){ + if (intS > 59 || intS < 0) { intS = Math.min(59, Math.max(0, intS)); isValid = false; } } - if(!isValid){ + if (!isValid) { textComponent.setText(toDateString(intY, intM, intD, intH, intMi, intS)); textComponent.setCaretPosition(iCaretPosition + 1); @@ -288,11 +300,11 @@ public class JDateDocument extends PlainDocument{ return isValid; } - private String toDateString(int y, int m, int d, int h, int mi, int s){ + private String toDateString(int y, int m, int d, int h, int mi, int s) { m = Math.max(1, Math.min(12, m)); //最大天数为31天 d = Math.max(1, Math.min(31, d)); - switch(m){ + switch (m) { case 4: case 6: case 9: @@ -302,9 +314,9 @@ public class JDateDocument extends PlainDocument{ case 2: //润年 - if((y % 4 == 0 && y % 100 != 0) || y % 400 == 0){ + if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) { d = Math.min(29, d); //最大天数为29天 - } else{ + } else { d = Math.min(28, d); //最大天数为28天 } break; @@ -321,7 +333,7 @@ public class JDateDocument extends PlainDocument{ String strDate; strDate = strY + strPattern.substring(4, 5) + strM + strPattern.substring(7, 8) + strD; - if(strPattern.length() == 19){ + if (strPattern.length() == 19) { strDate += strPattern.substring(10, 11) + rPad0(2, "" + h) + strPattern.substring(13, 14) + rPad0(2, "" + mi) + strPattern.substring(16, 17) @@ -330,8 +342,8 @@ public class JDateDocument extends PlainDocument{ return strDate; } - private String rPad0(int maxLen, String str){ - if(str.length() < maxLen){ + private String rPad0(int maxLen, String str) { + if (str.length() < maxLen) { str = "0" + str; } return str; diff --git a/designer-base/src/main/java/com/fr/design/gui/date/UICalendarPanel.java b/designer-base/src/main/java/com/fr/design/gui/date/UICalendarPanel.java index acf60d1be4..fb21021179 100644 --- a/designer-base/src/main/java/com/fr/design/gui/date/UICalendarPanel.java +++ b/designer-base/src/main/java/com/fr/design/gui/date/UICalendarPanel.java @@ -1,9 +1,9 @@ package com.fr.design.gui.date; import com.fr.base.BaseUtils; -import com.fr.base.SimpleDateFormatThreadSafe; import com.fr.base.background.GradientBackground; import com.fr.design.carton.MonthlyCartonFile; +import com.fr.design.carton.SwitchForSwingChecker; import com.fr.design.constants.UIConstants; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ilable.UILabel; @@ -139,7 +139,7 @@ public class UICalendarPanel extends JPanel { } } private void initTodayListener() { - if (speciallyForCarton && !isTodayCartonExists()) { + if (speciallyForCarton && !SwitchForSwingChecker.isCartonExists()) { lbToday.setEnabled(false); lbToday.removeMouseListener(todayListener); } @@ -234,18 +234,6 @@ public class UICalendarPanel extends JPanel { return pCenter; } - /** - * 判断是否有当天的卡顿日志,没有就返回false - */ - private boolean isTodayCartonExists() { - String format = dayFormat.format(new Date()); - Calendar calendar = Calendar.getInstance(); - int month = calendar.get(Calendar.MONTH) + 1; - int year = calendar.get(Calendar.YEAR); - File file = new File(StableUtils.pathJoin(JOURNAL_FILE_PATH, String.valueOf(year), "month-" + month, format)); - return file.exists(); - } - private JPanel createSouthPane() { JPanel sPane = new JPanel(); sPane.setPreferredSize(new Dimension(216, 30)); diff --git a/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java b/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java index 6e01d5d9af..0344960e1b 100644 --- a/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java +++ b/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java @@ -34,7 +34,9 @@ import java.util.Date; */ public class UIDatePicker extends UIComboBox implements Serializable { - //用于记录本datePicker是否是由设计器卡顿优化箱上打开(后续要去调用方法) + /** + * 用于记录本datePicker是否是由设计器卡顿优化箱上打开(后续要去调用方法) + */ private FeedbackToolboxDialog feedbackToolboxDialog = null; /** * 日期格式类型 @@ -70,9 +72,18 @@ public class UIDatePicker extends UIComboBox implements Serializable { public UIDatePicker(int formatStyle) throws UnsupportedOperationException { this(formatStyle, new Date()); } + public UIDatePicker(int formatStyle, FeedbackToolboxDialog feedbackToolboxDialog) throws UnsupportedOperationException { this(formatStyle, new Date(), feedbackToolboxDialog); } + + /** + * + * @param formatStyle + * @param initialDatetime + * @param feedbackToolboxDialog 判断该日历是否由设计器反馈工具箱打开 + * @throws UnsupportedOperationException + */ public UIDatePicker(int formatStyle, Date initialDatetime, FeedbackToolboxDialog feedbackToolboxDialog) throws UnsupportedOperationException { this.setStyle(formatStyle); //设置可编辑 @@ -80,33 +91,25 @@ public class UIDatePicker extends UIComboBox implements Serializable { this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); //设置编辑器属性(只能输入正确日期) JTextField textField = ((JTextField) getEditor().getEditorComponent()); - textField.setHorizontalAlignment(SwingConstants.CENTER); - dateDocument = new JDateDocument(textField, this.dateFormat,0); + if (feedbackToolboxDialog != null) { + dateDocument = new JDateDocument(textField, this.dateFormat, StringUtils.EMPTY, false); + this.feedbackToolboxDialog = feedbackToolboxDialog; + textField.setHorizontalAlignment(SwingConstants.LEFT); + //设置当前选择日期 + this.setSelectedItem(initialDatetime); + } else { + dateDocument = new JDateDocument(textField, this.dateFormat); + this.setSelectedItem(initialDatetime == null ? new Date() : initialDatetime); + textField.setHorizontalAlignment(SwingConstants.CENTER); + } textField.setDocument(dateDocument); //设置Model为单值Model this.setModel(model); - //设置当前选择日期 - this.setSelectedItem(initialDatetime); - this.feedbackToolboxDialog = feedbackToolboxDialog; updateUI(); } - public UIDatePicker(int formatStyle, Date initialDatetime) throws UnsupportedOperationException { - this.setStyle(formatStyle); - //设置可编辑 - this.setEditable(true); - - this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - //设置编辑器属性(只能输入正确日期) - JTextField textField = ((JTextField) getEditor().getEditorComponent()); - textField.setHorizontalAlignment(SwingConstants.CENTER); - dateDocument = new JDateDocument(textField, this.dateFormat); - textField.setDocument(dateDocument); - //设置Model为单值Model - this.setModel(model); - //设置当前选择日期 - this.setSelectedItem(initialDatetime == null ? new Date() : initialDatetime); - updateUI(); + public UIDatePicker(int formatStyle, Date initialDatetime) throws UnsupportedOperationException { + this(formatStyle, initialDatetime, null); } /** diff --git a/designer-realize/src/main/java/com/fr/start/MainDesigner.java b/designer-realize/src/main/java/com/fr/start/MainDesigner.java index 01e62cccbb..8b5a38ea1c 100644 --- a/designer-realize/src/main/java/com/fr/start/MainDesigner.java +++ b/designer-realize/src/main/java/com/fr/start/MainDesigner.java @@ -11,8 +11,7 @@ import com.fr.design.actions.server.ServerConfigManagerAction; import com.fr.design.actions.server.TemplateThemeManagerAction; import com.fr.design.actions.server.WidgetManagerAction; import com.fr.design.base.mode.DesignModeContext; -import com.fr.design.carton.CartonThreadExecutorPool; -import com.fr.design.carton.EventDispatchThreadHangMonitor; +import com.fr.design.carton.SwitchForSwingChecker; import com.fr.design.constants.UIConstants; import com.fr.design.deeplink.DeepLinkManager; import com.fr.design.file.HistoryTemplateListCache; @@ -160,8 +159,8 @@ public class MainDesigner extends BaseDesigner { } FineLoggerFactory.getLogger().info("Designer started.Time used {} ms", watch.getTime()); watch.stop(); - EventDispatchThreadHangMonitor.initMonitoring(); - AppContext.getAppContext().put(SwingWorker.class, CartonThreadExecutorPool.getTimerThreadExecutorPool()); + + SwitchForSwingChecker.initThreadMonitoring(); } /**