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监控区域看到模拟的日志信息。运行效果图如下所示:

Swing应用开发实战系列之五:后台日志信息前台监控器_第1张图片

Swing应用开发实战系列之五:后台日志信息前台监控器_第2张图片

 

运行程序打包下载 hnepri-log-monitor.jar

 

作者:商兵兵

单位:河南省电力科学研究院智能电网所

QQ:52190634

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

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

 

你可能感兴趣的:(Swing应用开发实战系列之五:后台日志信息前台监控器)