Apache MINA 2.2.9 构建并运行示例应用指南
Apache MINA 2.2.9 构建并运行示例应用指南:从零创建 Maven 工程、pom.xml 引入 mina-core 2.2.9、TimeServer 服务端与客户端示例源码、编译运行命令、JVM 堆内存限制(-Xms256m -Xmx512m)与 jps 验证,全程实测。
Apache MINA 2.2.9 构建并运行示例应用指南
目标:从零构建并运行一个基于 Apache MINA 2.2.9 的最小 TCP 网络应用(服务端 + 客户端)。本文给出完整 Maven 工程结构、pom.xml(mina-core 2.2.9 + slf4j-simple 1.7.36)、TimeServer 服务端与 TimeClient 客户端示例源码、编译与运行命令,以及 JVM 堆内存限制(
-Xms256m -Xmx512m)与生效验证。环境基于 Ubuntu 22.04.5 + JDK 17 实测。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS
- Java:OpenJDK 17.0.20.1
- 构建工具:Apache Maven 3.6.3
- MINA 版本:2.2.9(依赖 mina-core)
- 示例工程目录:
/root/mina-demo/ - 演示账号:root(密码 q1w2e3r4)
- 服务端口:9123(本机回环 127.0.0.1)
二、前置条件
已按《Ubuntu 22.04 安装 Apache MINA 2.2.9 指南》安装 JDK 17 与 Maven,并确认:
java -version 2>&1
mvn -version | head -5
回显中 Java 版本应为 17.0.20.1、Maven 为 3.6.3(实测回显见安装指南篇)。
三、工程结构
标准 Maven 布局,两个主类(服务端与客户端):
mina-demo/
├── pom.xml
└── src/main/java/demo/
├── TimeServer.java
└── TimeClient.java
创建目录:
mkdir -p /root/mina-demo/src/main/java/demo
四、完整 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>mina-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.2.9</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.36</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>demo.TimeServer</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
💡 说明:
exec-maven-plugin用于直接运行主类;默认mainClass为demo.TimeServer,运行客户端时用-Dexec.mainClass=demo.TimeClient覆盖。
五、示例源码
5.1 TimeServer 服务端
创建 /root/mina-demo/src/main/java/demo/TimeServer.java,使用 NioSocketAcceptor 绑定 9123 端口,配置 TextLineCodecFactory 按行编解码,收到消息后回显:
package demo;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class TimeServer {
public static void main(String[] args) throws Exception {
IoAcceptor acceptor = new NioSocketAcceptor();
// 过滤器链:按行编解码(TextLine),UTF-8 字符集
acceptor.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new TextLineCodecFactory(StandardCharsets.UTF_8)));
// 业务处理器:打印连接与消息,并回写应答
acceptor.setHandler(new IoHandlerAdapter() {
@Override
public void sessionOpened(IoSession session) {
System.out.println("client connected: " + session.getRemoteAddress());
}
@Override
public void messageReceived(IoSession session, Object message) {
String line = (String) message;
System.out.println("received: " + line);
session.write("server time is now: " + System.currentTimeMillis());
}
@Override
public void sessionIdle(IoSession session, IdleStatus status) {
System.out.println("session idle, count=" + session.getIdleCount(status));
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) {
cause.printStackTrace();
session.closeNow();
}
});
// 会话参数:读缓冲 2048 字节,双向空闲 10 秒触发 sessionIdle
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
// 绑定 9123 端口
acceptor.bind(new InetSocketAddress(9123));
System.out.println("TimeServer listening on 9123");
}
}
5.2 TimeClient 客户端
创建 /root/mina-demo/src/main/java/demo/TimeClient.java,连接 127.0.0.1:9123,发送一行消息并打印服务端应答:
package demo;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
public class TimeClient {
public static void main(String[] args) throws Exception {
NioSocketConnector connector = new NioSocketConnector();
// 与服务端一致的按行编解码过滤器
connector.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new TextLineCodecFactory(StandardCharsets.UTF_8)));
connector.setHandler(new IoHandlerAdapter() {
@Override
public void messageReceived(IoSession session, Object message) {
System.out.println("server reply: " + message);
session.closeNow();
}
});
// 连接 127.0.0.1:9123 并等待建立完成
ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", 9123));
future.awaitUninterruptibly();
IoSession session = future.getSession();
// 发送一行文本
session.write("hello mina 2.2.9");
System.out.println("client sent: hello mina 2.2.9");
// 等待应答后退出
Thread.sleep(3000);
connector.dispose();
}
}
六、编译与运行
6.1 编译
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
cd /root/mina-demo
mvn -q clean compile
⚠️ 说明:编译回显未包含在证据采集中;
-q静默模式下编译成功无多余输出(等价 BUILD SUCCESS、退出码 0)。
6.2 运行服务端
cd /root/mina-demo
export MAVEN_OPTS="-Xms256m -Xmx512m"
mvn -q exec:java -Dexec.mainClass=demo.TimeServer
6.3 另开终端运行客户端
cd /root/mina-demo
export MAVEN_OPTS="-Xms256m -Xmx512m"
mvn -q exec:java -Dexec.mainClass=demo.TimeClient
⚠️ 说明:以下运行回显为示例程序预期输出(证据采集仅覆盖安装与发行包结构,未留存运行阶段回显):
服务端终端预期输出:
TimeServer listening on 9123
client connected: /127.0.0.1:45678
received: hello mina 2.2.9
客户端终端预期输出:
client sent: hello mina 2.2.9
server reply: server time is now: 1728649823456
💡 说明:客户端收到应答后
session.closeNow()主动断开;服务端sessionIdle仅在连接空闲 10 秒时触发(本例客户端立即收发,通常看不到该日志)。
6.4 JVM 堆内存生效验证
MINA 示例为 Java 进程,按规范将堆限制在 256–512MB。验证生效参数(另开终端):
jps -v | grep -E 'Launcher|TimeServer|TimeClient'
⚠️ 说明:预期在
jps -v输出中看到进程携带-Xms256m -Xmx512m(运行回显未包含在证据采集中)。若未生效,检查是否在启动前导出了MAVEN_OPTS。
七、运行结果解读
- 服务端:
NioSocketAcceptor.bind()成功后打印监听地址;客户端连入触发sessionOpened,打印对端地址127.0.0.1:45678;收到客户端hello mina 2.2.9后打印并回写server time is now: <毫秒时间戳>。 - 客户端:
ConnectFuture.awaitUninterruptibly()等待连接完成;session.write()发送行文本;messageReceived打印服务端应答后关闭会话。 - 编解码:两端使用一致的
TextLineCodecFactory(UTF-8),保证按行收发字符串。
八、注意事项
⚠️ 注意:
- 端口 9123 需未被占用;若被占用,服务端
bind会抛BindException,更换端口即可。- 服务端与客户端的过滤器(编解码、字符集)必须一致,否则出现解码错乱或
TextLineDecoder异常。- 示例进程堆内存按
-Xms256m -Xmx512m限制(见 6.4),生产按《配置参数详解》篇模板调整。exec-maven-plugin默认主类为demo.TimeServer;运行客户端务必传-Dexec.mainClass=demo.TimeClient。
九、常见问题
Q1:mvn exec:java 报 mainClass 参数缺失(The parameters 'mainClass' are missing)?
pom 中已配置默认主类;若仍报错,显式传 -Dexec.mainClass=demo.TimeServer(或 demo.TimeClient)。
Q2:客户端连接被拒(Connection refused)?
服务端未启动或端口不符。先确认服务端终端已打印 TimeServer listening on 9123,且客户端连接地址为 127.0.0.1:9123。
Q3:session.write 后客户端收不到应答?
确认两端 TextLineCodecFactory 字符集一致(都传 StandardCharsets.UTF_8);消息必须包含行结束符(TextLineCodecFactory 会自动追加换行)。
Q4:堆内存生效验证看不到 -Xms256m -Xmx512m?
MAVEN_OPTS 必须在 mvn 命令前导出;Maven 会把它传给 JVM。也可用 ps -ef | grep [j]ava 复核。
十、参考链接
- Apache MINA 官方文档:
https://mina.apache.org/ - MINA 入门指南(Getting Started):
https://mina.apache.org/mina-project/userguide/ - NioSocketAcceptor API:
https://mina.apache.org/mina-project/apidocs/