歡迎閱讀我的開(kāi)源項(xiàng)目《迷你微信》服務(wù)器與《迷你微信》客戶端
在《迷你微信》服務(wù)器中,我們用了Log4J來(lái)進(jìn)行輸出,這可以在我們程序出現(xiàn)異常的時(shí)候找到錯(cuò)誤發(fā)生時(shí)的上下文。然而嗎,在項(xiàng)目的組件迭代過(guò)程中,我們發(fā)現(xiàn),log出來(lái)的內(nèi)容越來(lái)越多,往往在儲(chǔ)蓄出現(xiàn)異常去查L(zhǎng)og的時(shí)候,會(huì)被一大堆不相干的Log給淹沒(méi),這時(shí),我們想:如果能夠只輸出我要的那部分豈不是很爽,這樣就能快速的找到我們要的Log了,所以博主自己別編寫了一個(gè)定制化輸出的方法。
Log4J的NameLog4J在創(chuàng)建時(shí)是需要設(shè)置名稱的,可以把它理解成一個(gè)索引,以此在其他地方拿到它。
public class MyLogTest {private Logger logger = Logger.getLogger(this.getClass().getSimpleName());ppublic void method_1(){logger.info("abcdefg");}}public class Test_2 {public Logger getMyLogger(String name){return Logger.getLogger(name);}}上述MyLogTest類中,我們用類名創(chuàng)建了一個(gè)Log4J的Logger對(duì)象,在第二個(gè)類Test_2中,我們有一個(gè)getMyLogger方法,如果我們調(diào)用時(shí)傳入的是MyLogTest的類名,則會(huì)返回MyLogTest中的那個(gè)Logger對(duì)象。
注:Logger.getLogger(name) 方法在以name命名對(duì)象不存在時(shí),會(huì)創(chuàng)建一個(gè)新的返回,當(dāng)已經(jīng)被創(chuàng)建后調(diào)用則會(huì)返回之前創(chuàng)建過(guò)的那個(gè)Logger對(duì)象。
定制化Log輸出配置xml想要做到定制化Log輸出,我們需要有一個(gè)配置文件來(lái)設(shè)置哪些Logger輸出,哪些不輸出。(詳細(xì)源碼請(qǐng)參考《迷你微信》服務(wù)器)
<?xml version=""1.0" encoding="UTF-8"?><LoggerRule><TypeContain>False</TypeContain><TypeList><ProtoHead logType="class">server.Server_User</ProtoHead></TypeList></LoggerRule>先來(lái)解釋一下上述代碼所代表的意義:
整體來(lái)說(shuō),就是在項(xiàng)目運(yùn)行時(shí),叫server.Server_User這個(gè)名字的Logger將被忽略輸出。
編寫讀取類private void readLogRule() { DocumentBuilderFactory domfac=DocumentBuilderFactory.newInstance();try { DocumentBuilder dombuilder=domfac.newDocumentBuilder(); InputStream is=new FileInputStream(LoggerXML); Document doc=dombuilder.parse(is); Element root = doc.getDocumentElement(); // 獲取根元素String typeContain = root.getElementsByTagName("TypeContain").item(0).getFirstChild().getNodeValue().toString();loggerRule = new LoggerRule(typeContain.equals("True") ? LoggerType.Contain: LoggerType.Ignore);NodeList nodeList = root.getElementsByTagName("ProtoHead");Node node1, node2;NamedNodeMap namedNodeMap;String nodeValue;for (int i=0; i<nodeList.getLength(); i++) {node1 = nodeList.item(i);namedNodeMap = node1.getAttributes();for (int j=0; j<namedNodeMap.getLength(); j++) {node2 = namedNodeMap.item(j);if (node2.getNodeName().equals("logType")) {nodeValue = node1.getFirstChild().getNodeValue().toString();if (node2.getNodeValue().equals("Network")) {// 顯示服務(wù)器發(fā)了什么包的LogloggerRule.loggerSet.add(ProtoHead.ENetworkMessage.valueOf(nodeValue));} else if (node2.getNodeValue().equals("class")) {loggerRule.logCalssList.add(nodeValue);}}}}} catch (Exception e) {logger.error("MyLogger : load " + LoggerXML + " file error!/n" + MyException.getStackStr(e.getStackTrace()));}}class LoggerRule {public static enum LoggerType {Contain, Ignore};public LoggerType loggerType;HashSet<ProtoHead.ENetworkMessage> loggerSet;public ArrayList<String> logCalssList;public LoggerRule(LoggerType loggerType) {this.loggerType = loggerType;loggerSet = new HashSet<ProtoHead.ENetworkMessage>();logCalssList = new ArrayList<String>();}}通過(guò)上面這個(gè)方法,我們從配置文件中讀出了我們制定的輸出規(guī)則,存儲(chǔ)在一個(gè)ArrayList中,接著,只要進(jìn)行以此遍歷,將指定的Logger關(guān)掉即可:
public void closeLoggerNotWant(){for (String className : loggerRule.logCalssList)Logger.getLogger(className).setAdditivity(false);}優(yōu)點(diǎn)通過(guò)這種方式,我們實(shí)現(xiàn)了配置編程,在不修改項(xiàng)目源碼的前提下,我們可以通過(guò)修改配置文件的方式來(lái)設(shè)置哪些Logger不驚醒輸出。甚至,在對(duì)上述程序做一些修改后,可以動(dòng)態(tài)的進(jìn)行變化(如:定時(shí)讀取XML),即可以在不重啟整個(gè)進(jìn)程的前提下修改輸出設(shè)置。
歡迎閱讀我的開(kāi)源項(xiàng)目《迷你微信》服務(wù)器與《迷你微信》客戶端
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注