Apache Mina使用手記(三)

來源:互聯網
上載者:User

在上一篇中,通過一個簡單的例子,得以管中窺豹,瞭解了Mina的基本編寫方法。在MinaTimeServer示範程式中,我們添加了兩個過濾器,一個是日誌過濾器LoggingFilter,一個是文本編解碼過濾器。前者實現日誌資訊的自動處理,後者實現對按行讀寫的文本資料的編碼和解碼。

其中LoggingFilter預設的是slf4j,它是一個日誌Facade,實際並不實現真正的Tlog功能,它在程式運行時自動判斷classpath中載入的日誌組件,比如:log4j/Logback/JUL等,確定之後調用真正的日誌組件實現真正的Tlog操作。這一點對於組件式的程式,很明顯是非常靈活的,因為你並不知道使用者的實際環境中使用的是log4j還是JUL,或者是Logback等,但是為了實現自動識別,slf4j預設了log設定檔的載入位置,讓我覺得十分不便。

我自己的所有系統中,都使用是log4j(他的替代產品Logback已經出來了,據說效能更強),我一般喜歡把所有設定檔包括log4j.properties都放在conf目錄下,以便管理。因此,對於slf4j中需要把log4j.properties放在src檔案夾下非常不習慣,對於以後管理也容易引起混亂。所以,我希望能直接實現自己的log4j過濾器,按以前的方式使用。我們觀察一下LoggingFilter過濾器的原始碼,如下所示:

public class LoggingFilter extends IoFilterAdapter{...}

LoggingFilter繼承自IoFilterAdapter,它是java模型中的適配器模式,是對介面IoFilter的封裝。我們可以模仿LoggingFilter,實現自己的Log4jFilter類:

import org.apache.log4j.Level;<br />import org.apache.log4j.Logger;<br />import org.apache.mina.core.filterchain.IoFilterAdapter;<br />import org.apache.mina.core.session.IdleStatus;<br />import org.apache.mina.core.session.IoSession;<br />import org.apache.mina.core.write.WriteRequest;<br />import org.apache.mina.filter.logging.LogLevel;<br />import org.slf4j.helpers.MessageFormatter;<br />public class Log4jFilter extends IoFilterAdapter {<br /> /** The logger name */<br /> private final String name;</p><p> /** The logger */<br /> private final Logger logger;</p><p> /** The log level for the exceptionCaught event. Default to WARN. */<br /> private LogLevel exceptionCaughtLevel = LogLevel.WARN;</p><p> /** The log level for the messageSent event. Default to INFO. */<br /> private LogLevel messageSentLevel = LogLevel.INFO;</p><p> /** The log level for the messageReceived event. Default to INFO. */<br /> private LogLevel messageReceivedLevel = LogLevel.INFO;</p><p> /** The log level for the sessionCreated event. Default to INFO. */<br /> private LogLevel sessionCreatedLevel = LogLevel.INFO;</p><p> /** The log level for the sessionOpened event. Default to INFO. */<br /> private LogLevel sessionOpenedLevel = LogLevel.INFO;</p><p> /** The log level for the sessionIdle event. Default to INFO. */<br /> private LogLevel sessionIdleLevel = LogLevel.INFO;</p><p> /** The log level for the sessionClosed event. Default to INFO. */<br /> private LogLevel sessionClosedLevel = LogLevel.INFO;</p><p> /**<br /> * Default Constructor.<br /> */<br /> public Log4jFilter(Logger logger) {<br /> this.logger=logger;<br /> this.name=logger.getName();<br /> }</p><p> /**<br /> * @return The logger's name<br /> */<br /> public String getName() {<br /> return name;<br /> }</p><p> /**<br /> * Log if the logger and the current event log level are compatible. We log<br /> * a message and an exception.<br /> *<br /> * @param eventLevel the event log level as requested by the user<br /> * @param message the message to log<br /> * @param cause the exception cause to log<br /> */<br /> private void log(LogLevel eventLevel, String message, Throwable cause) {<br /> if (eventLevel == LogLevel.TRACE) {<br /> logger.trace(message, cause);<br /> } else if (eventLevel.getLevel() > LogLevel.INFO.getLevel()) {<br /> logger.info(message, cause);<br /> } else if (eventLevel.getLevel() > LogLevel.WARN.getLevel()) {<br /> logger.warn(message, cause);<br /> } else if (eventLevel.getLevel() > LogLevel.ERROR.getLevel()) {<br /> logger.error(message, cause);<br /> }<br /> }<br /> /**<br /> * Log if the logger and the current event log level are compatible. We log<br /> * a formated message and its parameters.<br /> *<br /> * @param eventLevel the event log level as requested by the user<br /> * @param message the formated message to log<br /> * @param param the parameter injected into the message<br /> */<br /> private void log(LogLevel eventLevel, String message, Object param) {<br /> String msgStr = MessageFormatter.format(message, param);<br /> if (eventLevel == LogLevel.TRACE) {<br /> logger.log(name, Level.TRACE, msgStr, null);</p><p> } else if (eventLevel.getLevel() > LogLevel.INFO.getLevel()) {<br /> logger.log(name, Level.INFO, msgStr, null);<br /> } else if (eventLevel.getLevel() > LogLevel.WARN.getLevel()) {<br /> logger.log(name, Level.WARN, msgStr, null);<br /> } else if (eventLevel.getLevel() > LogLevel.ERROR.getLevel()) {<br /> logger.log(name, Level.ERROR, msgStr, null);<br /> }<br /> }<br /> /**<br /> * Log if the logger and the current event log level are compatible. We log<br /> * a simple message.<br /> *<br /> * @param eventLevel the event log level as requested by the user<br /> * @param message the message to log<br /> */<br /> private void log(LogLevel eventLevel, String message) {<br /> if (eventLevel == LogLevel.TRACE) {<br /> logger.trace(message);<br /> } else if (eventLevel.getLevel() > LogLevel.INFO.getLevel()) {<br /> logger.info(message);<br /> } else if (eventLevel.getLevel() > LogLevel.WARN.getLevel()) {<br /> logger.warn(message);<br /> } else if (eventLevel.getLevel() > LogLevel.ERROR.getLevel()) {<br /> logger.error(message);<br /> }<br /> }<br /> @Override<br /> public void exceptionCaught(NextFilter nextFilter, IoSession session,<br /> Throwable cause) throws Exception {<br /> log(exceptionCaughtLevel, "EXCEPTION :", cause);<br /> nextFilter.exceptionCaught(session, cause);<br /> }<br /> @Override<br /> public void messageReceived(NextFilter nextFilter, IoSession session,<br /> Object message) throws Exception {<br /> log(messageReceivedLevel, "RECEIVED: {}", message );<br /> nextFilter.messageReceived(session, message);<br /> }<br /> @Override<br /> public void messageSent(NextFilter nextFilter, IoSession session,<br /> WriteRequest writeRequest) throws Exception {<br /> log(messageSentLevel, "SENT: {}", writeRequest.getMessage() );<br /> nextFilter.messageSent(session, writeRequest);<br /> }<br /> @Override<br /> public void sessionCreated(NextFilter nextFilter, IoSession session)<br /> throws Exception {<br /> log(sessionCreatedLevel, "CREATED");<br /> nextFilter.sessionCreated(session);<br /> }<br /> @Override<br /> public void sessionOpened(NextFilter nextFilter, IoSession session)<br /> throws Exception {<br /> log(sessionOpenedLevel, "OPENED");<br /> nextFilter.sessionOpened(session);<br /> }<br /> @Override<br /> public void sessionIdle(NextFilter nextFilter, IoSession session,<br /> IdleStatus status) throws Exception {<br /> log(sessionIdleLevel, "IDLE");<br /> nextFilter.sessionIdle(session, status);<br /> }<br /> @Override<br /> public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {<br /> log(sessionClosedLevel, "CLOSED");<br /> nextFilter.sessionClosed(session);<br /> }</p><p> /**<br /> * Set the LogLevel for the ExceptionCaught event.<br /> *<br /> * @param level The LogLevel to set<br /> */<br /> public void setExceptionCaughtLoglevel(LogLevel level) {<br /> exceptionCaughtLevel = level;<br /> }</p><p> /**<br /> * Get the LogLevel for the ExceptionCaught event.<br /> *<br /> * @return The LogLevel for the ExceptionCaught eventType<br /> */<br /> public LogLevel getExceptionCaughtLoglevel() {<br /> return exceptionCaughtLevel;<br /> }</p><p> /**<br /> * Set the LogLevel for the MessageReceived event.<br /> *<br /> * @param level The LogLevel to set<br /> */<br /> public void setMessageReceivedLoglevel(LogLevel level) {<br /> messageReceivedLevel = level;<br /> }</p><p> /**<br /> * Get the LogLevel for the MessageReceived event.<br /> *<br /> * @return The LogLevel for the MessageReceived eventType<br /> */<br /> public LogLevel getMessageReceivedLoglevel() {<br /> return messageReceivedLevel;<br /> }</p><p> /**<br /> * Set the LogLevel for the MessageSent event.<br /> *<br /> * @param level The LogLevel to set<br /> */<br /> public void setMessageSentLoglevel(LogLevel level) {<br /> messageSentLevel = level;<br /> }</p><p> /**<br /> * Get the LogLevel for the MessageSent event.<br /> *<br /> * @return The LogLevel for the MessageSent eventType<br /> */<br /> public LogLevel getMessageSentLoglevel() {<br /> return messageSentLevel;<br /> }</p><p> /**<br /> * Set the LogLevel for the SessionCreated event.<br /> *<br /> * @param level The LogLevel to set<br /> */<br /> public void setSessionCreatedLoglevel(LogLevel level) {<br /> sessionCreatedLevel = level;<br /> }</p><p> /**<br /> * Get the LogLevel for the SessionCreated event.<br /> *<br /> * @return The LogLevel for the SessionCreated eventType<br /> */<br /> public LogLevel getSessionCreatedLoglevel() {<br /> return sessionCreatedLevel;<br /> }</p><p> /**<br /> * Set the LogLevel for the SessionOpened event.<br /> *<br /> * @param level The LogLevel to set<br /> */<br /> public void setSessionOpenedLoglevel(LogLevel level) {<br /> sessionOpenedLevel = level;<br /> }</p><p> /**<br /> * Get the LogLevel for the SessionOpened event.<br /> *<br /> * @return The LogLevel for the SessionOpened eventType<br /> */<br /> public LogLevel getSessionOpenedLoglevel() {<br /> return sessionOpenedLevel;<br /> }</p><p> /**<br /> * Set the LogLevel for the SessionIdle event.<br /> *<br /> * @param level The LogLevel to set<br /> */<br /> public void setSessionIdleLoglevel(LogLevel level) {<br /> sessionIdleLevel = level;<br /> }</p><p> /**<br /> * Get the LogLevel for the SessionIdle event.<br /> *<br /> * @return The LogLevel for the SessionIdle eventType<br /> */<br /> public LogLevel getSessionIdleLoglevel() {<br /> return sessionIdleLevel;<br /> }</p><p> /**<br /> * Set the LogLevel for the SessionClosed event.<br /> *<br /> * @param level The LogLevel to set<br /> */<br /> public void setSessionClosedLoglevel(LogLevel level) {<br /> sessionClosedLevel = level;<br /> }<br /> /**<br /> * Get the LogLevel for the SessionClosed event.<br /> *<br /> * @return The LogLevel for the SessionClosed eventType<br /> */<br /> public LogLevel getSessionClosedLoglevel() {<br /> return sessionClosedLevel;<br /> }<br />}

其實代碼很類似,在MinaTimeServer中使用Log4jFilter使使看:

package com.gftech.mytool.mina;<br />import java.io.IOException;<br />import java.net.InetSocketAddress;<br />import java.nio.charset.Charset;<br />import java.util.Date;<br />import org.apache.log4j.Logger;<br />import org.apache.log4j.PropertyConfigurator;<br />import org.apache.mina.core.service.IoAcceptor;<br />import org.apache.mina.core.service.IoHandlerAdapter;<br />import org.apache.mina.core.session.IdleStatus;<br />import org.apache.mina.core.session.IoSession;<br />import org.apache.mina.filter.codec.ProtocolCodecFilter;<br />import org.apache.mina.filter.codec.textline.TextLineCodecFactory;<br />import org.apache.mina.transport.socket.nio.NioSocketAcceptor;<br />public class MinaTimeServer {<br /> private static final int PORT = 2500;<br /> // static Logger logger = LoggerFactory.getLogger(MinaTimeServer.class);<br /> static Logger logger = Logger.getLogger(MinaTimeServer.class);<br /> public static void main(String[] args) throws IOException {<br /> PropertyConfigurator.configure("conf//log4j.properties");<br /> IoAcceptor acceptor = new NioSocketAcceptor();<br /> // LoggingFilter lf = new LoggingFilter("testLog");<br /> Log4jFilter lf = new Log4jFilter(logger);<br /> acceptor.getFilterChain().addLast("logger", lf);<br /> acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("GBK"))));<br /> acceptor.setHandler(new TimeServerHandler());<br /> acceptor.getSessionConfig().setReadBufferSize(10);<br /> acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);<br /> acceptor.bind(new InetSocketAddress(PORT));<br /> System.out.println("start server ...");<br /> }<br />}<br />class TimeServerHandler extends IoHandlerAdapter {<br /> // static Logger logger = LoggerFactory.getLogger(TimeServerHandler.class);<br /> static Logger logger = Logger.getLogger(TimeServerHandler.class);<br /> @Override<br /> public void exceptionCaught(IoSession session, Throwable cause) throws Exception {<br /> cause.printStackTrace();<br /> }<br /> @Override<br /> public void messageReceived(IoSession session, Object message) throws Exception {<br /> String str = message.toString();<br /> if (str.trim().equalsIgnoreCase("quit")) {<br /> session.close(true);<br /> return;<br /> }<br /> logger.debug("Rec:" + str);<br /> Date date = new Date();<br /> session.write(date.toString());<br /> logger.debug("Message written...");<br /> }<br /> @Override<br /> public void sessionIdle(IoSession session, IdleStatus status) throws Exception {<br /> logger.debug("IDLE " + session.getIdleCount(status));<br /> }<br />}

把設定檔按照自己的習慣放到conf目錄下,就可以正常使用了。

需要注意的是,增加了自己的Log4jFilter之後,只能在您自己的代碼中實現logger.debug()之類的調用時產生的日誌記錄才是正常的,即按設定檔中的要求老老實實進行日誌記錄。對於Mina代碼中用到的logger調用,因為還是用的預設的slf4j,找不到src目錄下的log4j.properties,所以產生的日誌將無法正確顯示和記錄。除非您自己的將mina原始碼中的logger全部改成log4j的logger,這是個小小的遺憾,魚和熊掌不能兼得呀。

下一篇中,我們將介紹,如何編寫自己的編解碼過濾器。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.