第十章 - Executor Filter
在MINA 1.X的版本里,你可以在Acceptor級別定義線程模型。這是Acceptor設定的一部分。但是這種做法帶來了複雜性,所以MINA的開發團隊決定廢棄這種方式,取而代之的是個更加靈活的方式,基於Filter:ExecutorFilter
ExecutorFilter類
這個類實現了IoFilter接口,它裏面包含一個Executor,並且把進來的事件轉交給線程池來處理。這種方式可以讓應用程序更加有效的利用處理器,特別是處理CPU敏感的任務。
如果絕大部分處理都是在你的應用中完成,這個Filter可以被放置在IoHandler之前。或者放在某些CPU敏感的Filter之前(如CodecFilter)。
第十二章 - 日誌Filter
Apache MINA的日誌系統允許開發者在MINA的應用程序中使用自己喜歡的日誌系統。
SLF4J
MINA使用了Simple Logging Facade for Java (SLF4J)。SLF4J的詳細信息可以看這裏:http://www.slf4j.org/。 這個日誌工具允許你使用很多種日誌系統的實現。你可以使用log4j, java.util.logging 或其他的日誌系統。 使用這個工具的好處是你可以在不改變代碼的情況下切換日誌系統。
選擇正確的JAR文件
SLF4J使用靜態綁定,也就是說針對每一個日誌框架都有一個對應的SLF4J的實現類的JAR文件。你可以使用你喜歡的日誌框架,然後選擇一個調用這個日誌框架的JAR文件。下面的表格裏表示了各種日誌框架說需要的JAR文件。
日誌框架 | 需要的JAR |
Log4J 1.2.x | slf4j-api.jar, slf4j-log4j12.jar** |
Log4J 1.3.x | slf4j-api.jar, slf4j-log4j13.jar |
java.util.logging | slf4j-api.jar, slf4j-jdk14.jar** |
Commons Logging | slf4j-api.jar, slf4j-jcl.jar |
請注意下面幾點:
slf4j-api.jar在所有的實現JAR裏都是需要的
你不能把多個實現JAR放到classpath裏。(例如 slf4j-log4j12.jar 和 slf4j-jdk14.jar); 這會帶來一些意想不到的問題。
slf4j-api.jar的版本和slf4j-.jar的版本應該一致
上面的JAR文件配置好以後,接下來就是配置實際的日誌框架(例如:修改log4j.properties)
重寫Jakarta Commons Logging
SLF4J提供一種方式可以在不更改代碼的情況下把Jakarta Commons Logging 替換爲SLF4J。 只需要吧classpath下的commons-logging的jar文件刪除,並把jcl104-over-slf4j.jar添加到classpath。
log4j例子
下面的例子使用log4j作爲實際的日誌系統。我們設定了一些項目,把下面的代碼放到log4j.properties文件。
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c{1} %x - %m%n
這個文件放在項目的src目錄。如果你使用IDE,在測試的時候,記住要把這個文件配置到JVM的classpath下面。
儘管下面的例子是展示如何在IoAcceptor中設置日誌功能,瞭解SLF4J API本身的使用也是非常重要的。
這個例子是一個簡單的服務器的,可以產生一些日誌。在這裏我們使用EchoServer的例子。
public static void main(String[] args) throws Exception {
IoAcceptor acceptor = new SocketAcceptor();
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
LoggingFilter loggingFilter = new LoggingFilter();
chain.addLast("logging", loggingFilter);
acceptor.setLocalAddress(new InetSocketAddress(PORT));
acceptor.setHandler(new EchoProtocolHandler());
acceptor.bind();
System.out.println("Listening on port " + PORT);
}
我們在EchoServer的例子中刪除了addLogger方法,添加了兩行代碼。在LoggingFilter中你可以爲這個IoAcceptor關聯的IoHandler中的每一個事件類型設置日誌級別。在LoggingFilter裏有一個setLogLevel(IoEventType, LogLevel)方法。下面是可選的參數。
IoEventType | 描述 |
SESSION_CREATED | 當會話建立時調用 |
SESSION_OPENED | 當會話打開時調用 |
SESSION_CLOSED | 當會話關閉時調用 |
MESSAGE_RECEIVED | 當接收到數據時調用 |
MESSAGE_SENT | 當消息發送時調用 |
SESSION_IDLE | 當會話進入空閒狀態時調用 |
EXCEPTION_CAUGHT | 當異常產生時調用 |
下面是LogLevel的描述:
LogLevel | 描述 |
NONE | 無論怎麼配置都不產生日誌 |
TRACE | 日誌系統的TRACE級別 |
DEBUG | 日誌系統的DEBUG級別 |
INFO | 日誌系統的INFO級別 |
WARN | 日誌系統的WARN級別 |
ERROR | 日誌系統的ERROR級別 |