差異處
這裏顯示兩個版本的差異處。
Both sides previous revision 前次修改 下次修改 | 前次修改 | ||
java:log4j:extend_appender [2017/01/22 00:14] tony |
java:log4j:extend_appender [2017/01/22 17:09] tony [How to?] |
||
---|---|---|---|
行 1: | 行 1: | ||
{{tag>java log4j}} | {{tag>java log4j}} | ||
- | ====== Extend the appender (Working) ====== | + | ====== Extend the appender ====== |
===== Problem ===== | ===== Problem ===== | ||
我替老婆做了某個遊戲外掛,然後我希望能把log內容顯示在畫面上,例如:\\ | 我替老婆做了某個遊戲外掛,然後我希望能把log內容顯示在畫面上,例如:\\ | ||
{{:java:log4j:log4j_extend_appender_result.png|}}\\ | {{:java:log4j:log4j_extend_appender_result.png|}}\\ | ||
- | 本篇文章主要告訴大家extend log4j appender的方法。 | + | 我想透過log4j去通知畫面更新而不是再另開一個api;本篇文章主要告訴大家extend log4j appender的方法去達到這個目的。 |
===== How to? ===== | ===== How to? ===== | ||
- | ===== Reference ===== | + | 原先我的Subject是目前工作的狀態,負責通知的是執行工作的controller;而Observer則是UI,實作以下介面,Subject有變動會通知它: |
- | * [[https://gist.github.com/kengelke/4664612|GitHub - CachingSingletonAppender]] | + | <code java> |
+ | public interface IStateChangedListener { | ||
+ | void update(Object[] messages); | ||
+ | } | ||
+ | public class MessageTable extends JTable implements IStateChangedListener { | ||
+ | // skip | ||
+ | } | ||
+ | </code> | ||
+ | 接著新增一個名為NotificationAppender的Log4j Appender,要做以下事情: | ||
+ | - Extend AppenderSkeleton。 | ||
+ | - 負責Observer的註冊與通知。 | ||
+ | <code java> | ||
+ | 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; | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | 在config的部分如下,我針對某兩個類別將訊息送至MessageTable UI: | ||
+ | <code java> | ||
+ | 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 | ||
+ | </code> | ||
+ | ===== Additional Properties ===== | ||
+ | extend的appender如果需要特別的設定,例如: | ||
+ | <code java> | ||
+ | log4j.appender.MESSAGETABBLE.DumpConsole=true | ||
+ | </code> | ||
+ | 在appender中,可以加入set code去達到此需求: | ||
+ | <code java> | ||
+ | public void setDumpConsole(boolean value){ | ||
+ | System.out.println(value); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ===== Reference ===== | ||
+ | * [[https://gist.github.com/kengelke/4664612|GitHub - CachingSingletonAppender]] | ||
+ | * [[http://stackoverflow.com/questions/6072389/how-to-create-a-own-appender-in-log4j|how-to-create-a-own-appender-in-log4j]] | ||
+ | ===== ===== | ||
+ | ---- | ||
+ | \\ | ||
+ | ~~DISQUS~~ | ||