QuickServer開發指南(7)- 使用和定製日誌

    對任何一個項目來說,日誌都是一個重要的工具。日誌幫助我們去理解我們的項目內部發生了什麼,它也會提供審覈和調試信息。想要知道更多有關日誌的資料可查閱Sun公司的網站
    http://java.sun.com/j2se/1.4.0/docs/guide/util/logging/overview.html
    QuickServer目前只支持Java Logging API (java.util.logging)。1.4版的Java已加入logging。如果你還在使用舊的版本,你可以安裝Lumberjack庫提供的可選的實現(http://javalogging.sourceforge.net/)。
    讓我們給我們的EchoServer做一個日誌器。QuickServer默認已可以使用日誌器,但是除了ConsoleHandler和設置INFO的級別之外它什麼也沒有處理。因而無論何時我們在EchoServer關閉和客戶端的連接,我們都會在控制檯看見一些相似的信息
        Feb 16, 2000 10:11:25 PM ClientHandler sendSystemMsg
        INFO: Closing connection : /127.0.0.1
    上面的信息指明IP爲127.0.0.1的客戶端關閉了連接。這條消息的顯示使用了ClientHalder類的sendSystemMsg()方法.
    讓我們看看我們怎樣在我們的項目中控制日誌。使用java logging必須先在類中導入java.util.logging包。
    從上面的日誌,我們發現某些客戶端關閉了連接或掉線,但是它是怎樣顯示的,我們並沒有寫任何有關日誌的命令。它會顯示是因爲QuickServer使用了內部的日誌器ClientHandler類的sendSystemMsg()方法。
    查看QuickServer文檔可以找到sendSystemMsg(),如果沒有指定級別,它默認使用INFO。你可以在ClientCommandHandler或Authenticator或任何類中使用sendSystemMsg()來記錄一個事件。

1. 簡單的日誌
   現在我們來記錄每一個連接EchoServer的客戶端IP地址。編輯EchoCommandHandler.java文件。在gotConnected(ClientHandler handler)後添加
    handler.sendSystemMsg("New Client : " +
                          handler.getSocket().getInetAddress().getHostAddress(),
                          Level.INFO);
   還要導入包import java.util.logging.*;
   編譯並運行,連接到EchoServer,你將看到當客戶端連接時控制檯會顯示你的地址。
   讓QuickServer將日誌記錄到文件中(XML格式)。下面是修改的文件:

01 package echoserver;

02

03 import org.quickserver.net.*;

04 import org.quickserver.net.server.*;

05

06 import java.io.*;

07 import java.util.logging.*;

08

09 public class EchoServer {

10 public static void main(String s[]) {

11

12 String cmd = "echoserver.EchoCommandHandler";

13 String auth = "echoserver.EchoServerQuickAuthenticator";

14 String data = "echoserver.EchoServerPoolableData"; //Poolable

15

16 QuickServer myServer = new QuickServer();

17

18 //setup logger to log to file

19 Logger logger = null;

20 FileHandler xmlLog = null;

21 File log = new File("./log/");

22 if(!log.canRead())

23 log.mkdir();

24 try {

25 logger = Logger.getLogger(""); //get root logger

26 logger.setLevel(Level.INFO);

27 xmlLog = new FileHandler("log/EchoServer.xml");

28 logger.addHandler(xmlLog);

29 } catch(IOException e){

30 System.err.println("Could not create xmlLog FileHandler : "+e);

31 }

32 //set logging level to fine

33 myServer setConsoleLoggingLevel(Level INFO);

34

35

36 myServer.setClientCommandHandler(cmd);

37 myServer.setAuthenticator(auth);

38 myServer.setClientData(data);

39

40 myServer.setPort(4123);

41 myServer.setName("Echo Server v 1.0");

42

43 //store data needed to be changed by QSAdminServer

44 Object[] store = new Object[]{"12.00"};

45 myServer.setStoreObjects(store);

46

47 //config QSAdminServer

48 myServer.setQSAdminServerPort(4124);

49 myServer.getQSAdminServer().getServer().setName("EchoAdmin v 1.0");

50 try {

51 //add command plugin

52 myServer.getQSAdminServer().setCommandPlugin(

53 "echoserver.QSAdminCommandPlugin");

54 myServer.startQSAdminServer();

55 myServer.startServer();

56 } catch(AppException e){

57 System.out.println("Error in server : "+e);

58 } catch(Exception e){

59 System.out.println("Error : "+e);

60 }

61 }

62 }


    在上面的代碼中,我們首先檢查是否存在一個日誌文件夾(21、22行),如果沒有先創建它。
    在25行,我們嘗試獲得一個日誌器,28行,添加一個新的FileHandler,這裏我們沒有指定格式因爲默認的格式就是XML的。
    在33行,我們設置日誌的控制級別爲INFO。
    接下來修改EchoCommandHandler.java

01 // EchoCommandHandler.java

02 package echoserver;

03

04 import java.net.*;

05 import java.io.*;

06 import org.quickserver.net.server.ClientCommandHandler;

07 import org.quickserver.net.server.ClientHandler;

08 import java.util.logging.*;

09

10 public class EchoCommandHandler implements ClientCommandHandler {

11

12 public void gotConnected(ClientHandler handler)

13 throws SocketTimeoutException, IOException {

14 handler.sendSystemMsg("New Client : "+

15 handler.getSocket().getInetAddress().getHostAddress(),

16 Level.INFO);

17 handler.sendClientMsg("+++++++++++++++++++++++++++++++");

18 handler.sendClientMsg("| Welcome to EchoServer v 1.0 |");

19 handler.sendClientMsg("| Note: Password = Username |");

20 handler.sendClientMsg("| Send 'Quit' to exit |");

21 handler.sendClientMsg("+++++++++++++++++++++++++++++++");

22 }

23 public void lostConnection(ClientHandler handler)

24 throws IOException {

25 handler.sendSystemMsg("Connection lost : " +

26 handler.getSocket().getInetAddress());

27 }

28 public void closingConnection(ClientHandler handler)

29 throws IOException {

30 handler.sendSystemMsg("Closing connection : " +

31 handler.getSocket().getInetAddress());

32 }

33

34 public void handleCommand(ClientHandler handler, String command)

35 throws SocketTimeoutException, IOException {

36 if(command.equals("Quit")) {

37 handler.sendClientMsg("Bye ;-)");

38 handler.closeConnection();

39 return;

40 }

41 if(command.equals("What's interest?")) {

42 handler.sendClientMsg("Interest is : "+

43 (String)handler.getServer().getStoreObjects()[0]+

44 "%");

45 } else if(command.equalsIgnoreCase("hello")) {

46 EchoServerData data = (EchoServerData) handler.getClientData();

47 data.setHelloCount(data.getHelloCount()+1);

48 if(data.getHelloCount()==1) {

49 handler.sendClientMsg("Hello "+data.getUsername());

50 } else {

51 handler.sendClientMsg("You told Hello "+data.getHelloCount()+

52 " times. ");

53 }

54 } else {

55 handler.sendClientMsg("Echo : "+command);

56 }

57 }

58 }


    編譯並運行程序,現在嘗試連接,你將看到它會同時在控制檯和xml文件記錄你的IP地址。
    讓我們使用QSAdminGUI設置日誌級別爲FINEST,觀察日誌內容的變化。日誌記錄增加了。另外一個改變日誌級別的方法是修改代碼,可以使用logger.setLevel()或者QuickServer的方法setLoggingLevel()來設置所有句柄的日誌級別。

2. 日誌的高級應用
    當我們設置日誌級別爲FINEST時,會記錄很多信息。一個可能的需要是分離QuickServer和應用的日誌。下面的代碼允許你這麼做。

01 package echoserver;

02

03 import org.quickserver.net.*;

04 import org.quickserver.net.server.*;

05

06 import java.io.*;

07 import java.util.logging.*;

08

09 public class EchoServer {

10 public static void main(String s[]) {

11

12 String cmd = "echoserver.EchoCommandHandler";

13 String auth = "echoserver.EchoServerQuickAuthenticator";

14 String data = "echoserver.EchoServerPoolableData"; //Poolable

15

16 QuickServer myServer = new QuickServer();

17

18 //setup logger to log to file

19 Logger logger = null;

20 FileHandler xmlLog = null;

21 FileHandler txtLog = null;

22 File log = new File("./log/");

23 if(!log.canRead())

24 log.mkdir();

25 try {

26 logger = Logger.getLogger("org.quickserver.net"); //get QS logger

27 logger.setLevel(Level.FINEST);

28 xmlLog = new FileHandler("log/EchoServer.xml");

29 logger.addHandler(xmlLog);

30

31 logger = Logger.getLogger("echoserver"); //get App logger

32 logger.setLevel(Level.FINEST);

33 txtLog = new FileHandler("log/EchoServer.txt");

34 txtLog.setFormatter(new SimpleFormatter());

35 logger.addHandler(txtLog);

36 myServer.setAppLogger(logger); //img : Sets logger to be used for app.

37 } catch(IOException e){

38 System.err.println("Could not create xmlLog FileHandler : "+e);

39 }

40 //set logging level to fine

41 myServer.setConsoleLoggingLevel(Level.INFO);

42

43

44 myServer.setClientCommandHandler(cmd);

45 myServer.setAuthenticator(auth);

46 myServer.setClientData(data);

47

48 myServer.setPort(4123);

49 myServer.setName("Echo Server v 1.0");

50

51 //store data needed to be changed by QSAdminServer

52 Object[] store = new Object[]{"12.00"};

53 myServer.setStoreObjects(store);

54

55 //config QSAdminServer

56 myServer.setQSAdminServerPort(4124);

57 myServer.getQSAdminServer().getServer().setName("EchoAdmin v 1.0");

58 try {

59 //add command plugin

60 myServer.getQSAdminServer().setCommandPlugin(

61 "echoserver.QSAdminCommandPlugin");

62 myServer.startQSAdminServer();

63 myServer.startServer();

64 } catch(AppException e){

65 System.out.println("Error in server : "+e);

66 } catch(Exception e){

67 System.out.println("Error : "+e);

68 }

69 }

70 }


    代碼中的註釋說明的很清楚了。編譯並運行,連接後你將看見QuickServer內部的日誌記錄到了xml文件,應用級別的日誌記錄到了我們想要的txt文件。

注意:
    要儘量減少控制檯中的日誌數量,使用文件記錄詳細的日誌,並降低日誌的級別。這樣可以改善應用的性能。避免使用System.out.println(),用logging代替。ClientHandler中的sendSystemMsg()方法在記錄日誌方面很有用。
發佈了27 篇原創文章 · 獲贊 10 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章