如何在Apache Mina中记录日志?基于log4j.properties实现连接及数据收发日志
没问题,我来帮你搞定这个需求!其实结合Log4j和Apache Mina来记录连接状态与收发数据并不复杂,分两步走:先配置Log4j的日志输出,再在Mina的代码里埋点或用自带过滤器打日志,下面给你详细说明:
第一步:配置log4j.properties
首先要让Log4j把日志输出到指定文件,同时控制日志级别和格式。这里给你一个典型的配置示例:
# 根日志级别 log4j.rootLogger=INFO, file # 配置文件输出Appender(滚动文件,避免单个文件过大) log4j.appender.file=org.apache.log4j.RollingFileAppender # 日志文件路径,根据自己的项目路径修改 log4j.appender.file.File=/opt/mina-server/mina-connection.log # 单个日志文件最大容量,超过后自动生成新文件 log4j.appender.file.MaxFileSize=10MB # 最多保留的历史日志文件数量 log4j.appender.file.MaxBackupIndex=5 # 日志格式:包含时间、级别、类名、日志内容 log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %c{1} - %m%n # 可选:单独控制Apache Mina框架的日志级别,避免过多框架冗余日志 log4j.logger.org.apache.mina=INFO # 配置你的业务Handler类的日志级别,开发时可以设为DEBUG方便调试 log4j.logger.com.yourcompany.mina.handler.CustomHandler=DEBUG
第二步:在Apache Mina代码中实现日志记录
有两种常用方式,你可以根据需求选择:
方式一:手动在IoHandler中记录日志(推荐,定制化程度高)
Mina的核心业务逻辑都在IoHandler实现类里,你可以在这里注入Log4j的Logger,针对每个关键事件打日志:
import org.apache.log4j.Logger; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; public class CustomHandler extends IoHandlerAdapter { // 绑定当前类的Logger实例 private static final Logger logger = Logger.getLogger(CustomHandler.class); // 连接创建时触发 @Override public void sessionCreated(IoSession session) throws Exception { logger.info("新连接创建:远程地址=" + session.getRemoteAddress()); super.sessionCreated(session); } // 连接正式打开时触发 @Override public void sessionOpened(IoSession session) throws Exception { logger.info("连接已建立:远程地址=" + session.getRemoteAddress()); super.sessionOpened(session); } // 连接关闭时触发 @Override public void sessionClosed(IoSession session) throws Exception { logger.info("连接已断开:远程地址=" + session.getRemoteAddress()); super.sessionClosed(session); } // 收到客户端消息时触发 @Override public void messageReceived(IoSession session, Object message) throws Exception { // 根据消息类型转换为可读格式(如果是字节数组转字符串,解码后的对象直接toString) String receivedContent = message instanceof byte[] ? new String((byte[]) message, "UTF-8") : message.toString(); logger.debug("收到消息来自[" + session.getRemoteAddress() + "]:" + receivedContent); // 这里写你的业务处理逻辑,比如回复消息 String response = "已接收:" + receivedContent; session.write(response); } // 消息发送完成时触发 @Override public void messageSent(IoSession session, Object message) throws Exception { String sentContent = message instanceof byte[] ? new String((byte[]) message, "UTF-8") : message.toString(); logger.debug("发送消息到[" + session.getRemoteAddress() + "]:" + sentContent); super.messageSent(session, message); } // 捕获连接异常时触发 @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { logger.error("连接[" + session.getRemoteAddress() + "]发生异常", cause); // 异常处理:比如强制关闭连接 session.closeNow(); } }
这种方式可以完全控制日志的内容和格式,适合需要自定义日志细节的场景。
方式二:使用Mina自带的LoggingFilter(快速实现,适合简单场景)
Mina提供了LoggingFilter,可以自动帮你记录连接事件和消息收发,不用手动写日志代码,只需把它添加到过滤器链中:
import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import java.net.InetSocketAddress; public class MinaServer { public static void main(String[] args) throws Exception { NioSocketAcceptor acceptor = new NioSocketAcceptor(); // 创建LoggingFilter,默认记录INFO级别的连接事件、DEBUG级别的消息 LoggingFilter loggingFilter = new LoggingFilter(); // 可选:调整日志级别,比如把消息日志改成INFO // loggingFilter.setMessageLogLevel(Level.INFO); // 将过滤器添加到链中(注意顺序:建议放在编解码过滤器之后) acceptor.getFilterChain().addLast("logger", loggingFilter); // 设置业务Handler acceptor.setHandler(new CustomHandler()); // 绑定端口启动服务 acceptor.bind(new InetSocketAddress(8080)); System.out.println("Mina服务已启动,监听端口8080"); } }
这种方式优点是快速集成,无需编写大量日志代码,但日志内容比较固定,定制化程度低,适合简单的日志记录需求。
注意事项
- 确保项目中已引入Log4j 1.x的依赖包(比如
log4j-1.2.17.jar),如果用Log4j2的话配置格式会不同,这里针对你提到的log4j.properties默认是Log4j 1.x。 - 如果处理的是二进制消息,直接转字符串可能会乱码,建议先通过Mina的Codec过滤器解码为业务对象后再记录。
- 生产环境建议把日志级别设为
INFO或WARN,避免过多DEBUG日志影响性能;开发调试时可以用DEBUG级别。
内容的提问来源于stack exchange,提问作者Nexus
相关产品推荐
相关产品推荐

