Swing應用開發實戰系列之五:后台日志信息前台監控器


 

作為一個程序設計人員,我們深知日志的重要性,對於日志的監控,我們通常不外乎采用以下兩種方式:日志文件方式和后台打印方式,常規情況下,這兩種日志監控方式完全可以滿足我們對日志監控的需要。但是,當我們用Swing進行前台開發時,常常想能不能把后台服務運行日志實時地顯示在前台窗口中,或者只是將某類我們比較關心的日志信息(譬如異常日志等)實時動態地顯示在前台窗口中,這樣方便我們及時監控和處理。這個設想我們稱之為“后台日志信息前台監控器”。

設計這樣一個“后台日志信息前台監控器”,有兩個難點,第一個是,當我們捕捉到后台日志信息時,如何將日志信息傳遞給前台監控器,實現實時傳遞。第二個是,當前台監控器收到日志信息后,如何實時顯示。總結起來,就是一個“實時”的問題:實時傳遞和顯示日志信息。

對於如何將后台日志信息實時傳遞到前台進行監控顯示,我們采用了自定義事件機制,通過事件觸發機制,監控日志內容的變更。思路是這樣的,在LogMonitor類中,用StringBuilder實例化一個變量logs,用來存儲日志信息,通過addLog和clearLogs方法來添加和刪除日志信息,並在這兩個方法體內監控日志信息的變更,當日志信息發生變更時,觸發事件變更事件,最后在此事件內實時刷新前台監控區域。

 

  • 日志信息變更事件類
/**
 * Description:日志信息事件<br>
 * Copyright: Copyright (c) 2015<br>
 * Company: 河南電力科學研究院智能電網所<br>
 * 
 * @author shangbingbing 2015-01-01編寫
 * @version 1.0
 */
public class LogChangedEvent extends java.util.EventObject {
    private static final long serialVersionUID = 7573194493258326711L;
    public LogChangedEvent(Object source) {
        super(source);
    }
}

 

  • 日志信息變更監聽器類
/**
 * Description:日志信息變更監聽器<br>
 * Copyright: Copyright (c) 2015<br>
 * Company: 河南電力科學研究院智能電網所<br>
 * 
 * @author shangbingbing 2015-01-01編寫
 * @version 1.0
 */
public class LogChangedListener implements java.util.EventListener {
    public void EventActivated(LogChangedEvent me) {
        
    }
}

 

  • 日志信息監聽器類
/**
 * Description:日志信息監聽器類<br>
 * Copyright: Copyright (c) 2015<br>
 * Company: 河南電力科學研究院智能電網所<br>
 * @author shangbingbing 2015-01-01編寫
 * @version 1.0
 */
public class LogMonitor implements Serializable {
    private static final long serialVersionUID = 1L;
    private static StringBuilder logs = new StringBuilder();
    /**
     * 獲取日志信息
     * @return
     */
    public static StringBuilder getLogs() {
        return logs;
    }
    /**
     * 新增日志信息
     * @param log
     */
    public static void addLog(String log) {
        if(StringUtils.isBlank(log)) {
            logs.append("\r\n");
        } else {
            log = String.format("%s    %s\r\n", new Date().toString(), log);
            logs.append(log);
        }
        activateLogChangedEvent();
    }
    /**
     * 清除日志信息
     */
    public static void clearLogs() {
        logs = new StringBuilder();
        activateLogChangedEvent();
    }
    private static Vector<LogChangedListener> vectorListeners = new Vector<LogChangedListener>();
    public static synchronized void addLogChangedListener(LogChangedListener listener) {
        vectorListeners.addElement(listener);
    }
    public static synchronized void removeLogChangedListener(LogChangedListener listener) {
        vectorListeners.removeElement(listener);
    }
    public static void activateLogChangedEvent() {
        Vector<LogChangedListener> tempVector = null;
        LogChangedEvent e = new LogChangedEvent(LogMonitor.class);
        synchronized(LogMonitor.class) {
            tempVector = (Vector<LogChangedListener>)vectorListeners.clone();
            for(int i=0;i<tempVector.size();i++) {
                LogChangedListener listener = tempVector.elementAt(i);
                listener.EventActivated(e);
            }
        }
    }
}

 

  • 日志信息前台監控窗口
import javax.swing.JDialog;
import javax.swing.UIManager;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
/**
 * Description:日志信息監聽窗口<br>
 * Copyright: Copyright (c) 2015<br>
 * Company: 河南電力科學研究院智能電網所<br>
 * @author shangbingbing 2015-01-01編寫
 * @version 1.0
 */
public class DialogLogMonitor extends JDialog {
    private static final long serialVersionUID = 1L;
    private JTextArea txtLogInfo;
    public static void main(String[] args) {
        try {
            //設置系統觀感器
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            DialogLogMonitor dialog = new DialogLogMonitor();
            dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            dialog.setVisible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 日志信息變更監聽處理(關鍵點)
     */
    private void init() {
        LogMonitor.addLogChangedListener(new LogChangedListener() {
            @Override
            public void EventActivated(LogChangedEvent me) {
                txtLogInfo.setText(LogMonitor.getLogs().toString());
                txtLogInfo.setCaretPosition(txtLogInfo.getText().length());
                txtLogInfo.paintImmediately(txtLogInfo.getBounds());
            }
        });
    }
    public DialogLogMonitor() {
        setResizable(false);
        setTitle("\u540E\u53F0\u65E5\u5FD7\u76D1\u63A7\u5668");
        setBounds(100, 100, 439, 274);
        JScrollPane scrollPane = new JScrollPane();
        GroupLayout groupLayout = new GroupLayout(getContentPane());
        groupLayout.setHorizontalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(scrollPane)
                    .addContainerGap())
        );
        groupLayout.setVerticalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 230, Short.MAX_VALUE)
                    .addContainerGap())
        );
        txtLogInfo = new JTextArea();
        txtLogInfo.setEditable(false);
        txtLogInfo.setLineWrap(true);
        scrollPane.setViewportView(txtLogInfo);
        getContentPane().setLayout(groupLayout);
        this.init();
    }
}

 

  • 后台日志模擬生成窗口

我們設計了一個后台日志模擬生成窗口,來測試日志信息的監控效果。窗口源代碼如下:

import javax.swing.JDialog;
import javax.swing.UIManager;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JLabel;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
/**
 * Description:后台日志信息模擬生成窗口<br>
 * Copyright: Copyright (c) 2015<br>
 * Company: 河南電力科學研究院智能電網所<br>
 * @author shangbingbing 2015-01-01編寫
 * @version 1.0
 */
public class DialogLogGenerator extends JDialog {
    private static final long serialVersionUID = 1L;
    private JTextArea txtLogInfo;
    public static void main(String[] args) {
        try {
            //設置系統觀感器
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            DialogLogGenerator dialog = new DialogLogGenerator();
            dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            dialog.setVisible(true);
         
            DialogLogMonitor dialogLogMonitor = new DialogLogMonitor();
            dialogLogMonitor.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            dialogLogMonitor.setVisible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void generatorLog() {
        LogMonitor.addLog(this.txtLogInfo.getText());
        this.txtLogInfo.setText("");
    }
    public DialogLogGenerator() {
        setResizable(false);
    setTitle("\u540E\u53F0\u65E5\u5FD7\u6A21\u62DF\u751F\u6210\u6D4B\u8BD5\u7A97\u53E3");
        setBounds(100, 100, 439, 278);
        JLabel lblNewLabel = new JLabel("\u8BF7\u8F93\u5165\u6A21\u62DF\u65E5\u5FD7\u4FE1\u606F\uFF1A");
        JScrollPane scrollPane = new JScrollPane();
        JButton btnCreateLog = new JButton("\u4F20\u9012\u6A21\u62DF\u65E5\u5FD7");
        btnCreateLog.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                generatorLog();
            }
        });
        GroupLayout groupLayout = new GroupLayout(getContentPane());
        groupLayout.setHorizontalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
                        .addGroup(groupLayout.createSequentialGroup()
                            .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 413, Short.MAX_VALUE)
                            .addContainerGap())
                        .addGroup(groupLayout.createSequentialGroup()
                            .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
                                .addComponent(btnCreateLog, GroupLayout.PREFERRED_SIZE, 131, GroupLayout.PREFERRED_SIZE)
                                .addComponent(lblNewLabel, GroupLayout.PREFERRED_SIZE, 170, GroupLayout.PREFERRED_SIZE))
                            .addGap(253))))
        );
        groupLayout.setVerticalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addGap(18)
                    .addComponent(lblNewLabel)
                    .addPreferredGap(ComponentPlacement.UNRELATED)
                    .addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, 131, GroupLayout.PREFERRED_SIZE)
                    .addGap(18)
                    .addComponent(btnCreateLog, GroupLayout.PREFERRED_SIZE, 41, GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(17, Short.MAX_VALUE))
        );
        txtLogInfo = new JTextArea();
        scrollPane.setViewportView(txtLogInfo);
        getContentPane().setLayout(groupLayout);
    }
}

 

  • 運行測試

啟動運行DialogLogGenerator窗口,會同時顯示DialogLogMonitor窗口,在日志模擬窗口輸入一些日志信息,然后點擊“傳遞模擬日志”按鈕,你將可以在DialogLogMonitor監控區域看到模擬的日志信息。運行效果圖如下所示:

dailog_log_generator

dialog_log_monitor

 

運行程序打包下載 hnepri-log-monitor.jar

 


作者:商兵兵

單位:河南省電力科學研究院智能電網所

QQ:52190634

主頁:http://www.cnblogs.com/shangbingbing

空間:http://shangbingbing.qzone.qq.com

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM