Andrewtao00 2013-06-03
在MINA 1.X的版本里,你可以在Acceptor级别定义线程模型。这是Acceptor设定的一部分。但是这种做法带来了复杂性,所以MINA的开发团队决定废弃这种方式,取而代之的是个更加灵活的方式,基于Filter:ExecutorFilter
这个类实现了IoFilter接口,它里面包含一个Executor,并且把进来的事件转交给线程池来处理。这种方式可以让应用程序更加有效的利用处理器,特别是处理CPU敏感的任务。
如果绝大部分处理都是在你的应用中完成,这个Filter可以被放置在IoHandler之前。或者放在某些CPU敏感的Filter之前(如CodecFilter)。
Apache MINA的日志系统允许开发者在MINA的应用程序中使用自己喜欢的日志系统。
MINA使用了Simple Logging Facade for Java (SLF4J)。SLF4J的详细信息可以看这里:http://www.slf4j.org/。 这个日志工具允许你使用很多种日志系统的实现。你可以使用log4j, java.util.logging 或其他的日志系统。 使用这个工具的好处是你可以在不改变代码的情况下切换日志系统。
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)
SLF4J提供一种方式可以在不更改代码的情况下把Jakarta Commons Logging 替换为SLF4J。 只需要吧classpath下的commons-logging的jar文件删除,并把jcl104-over-slf4j.jar添加到classpath。
下面的例子使用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级别 |