Problem
我替老婆做了某個遊戲外掛,然後我希望能把log內容顯示在畫面上,例如:
我想透過log4j去通知畫面更新而不是再另開一個api;本篇文章主要告訴大家extend log4j appender的方法去達到這個目的。
How to?
原先我的Subject是目前工作的狀態,負責通知的是執行工作的controller;而Observer則是UI,實作以下介面,Subject有變動會通知它:
public interface IStateChangedListener { void update(Object[] messages); } public class MessageTable extends JTable implements IStateChangedListener { // skip }
接著新增一個名為NotificationAppender的Log4j Appender,要做以下事情:
- Extend AppenderSkeleton。
- 負責Observer的註冊與通知。
public class NotificationAppender extends AppenderSkeleton { protected static List<IStateChangedListener> mStateChangedListenerList = new ArrayList<>(); @Override protected void append(LoggingEvent arg0) { notify(arg0.getLevel().toString(), arg0.getMessage().toString()); } public static void addListener(IStateChangedListener aListener){ mStateChangedListenerList.add(aListener); } private static String getTimeString(Date aDate){ DateFormat df = new SimpleDateFormat("HH:mm:ss"); return df.format(aDate); } protected static void notify(String aState, String aMessage){ Date now = new Date(); for( IStateChangedListener listener : mStateChangedListenerList){ listener.update(new Object[]{ getTimeString(now), aState, aMessage }); } } @Override public void close() { } @Override public boolean requiresLayout() { return false; } }
在config的部分如下,我針對某兩個類別將訊息送至MessageTable UI:
log4j.additivity.org.tonylin.bot.fantasycity.RunBotJob=false log4j.logger.org.tonylin.bot.fantasycity.RunBotJob=DEBUG, CONSOLE, LOGFILE, MESSAGETABBLE log4j.additivity.org.tonylin.bot.fantasycity.BotUtils=false log4j.logger.org.tonylin.bot.fantasycity.BotUtils=DEBUG, CONSOLE, LOGFILE, MESSAGETABBLE # MessageTable Logger log4j.appender.MESSAGETABBLE=org.tonylin.bot.common.NotificationAppender log4j.appender.MESSAGETABBLE.Threshold=DEBUG
Additional Properties
extend的appender如果需要特別的設定,例如:
log4j.appender.MESSAGETABBLE.DumpConsole=true
在appender中,可以加入set code去達到此需求:
public void setDumpConsole(boolean value){ System.out.println(value); }
留言
張貼留言