Apache MINA 2.0 簡單應用示例及與Spring的集成

我頂 字號:
Apache MINA 2.0 簡單應用示例及與Spring的集成

基於Apache MINA 的網絡應用有三個層次,分別是 I/O 服務、I/O 過濾器和 I/O 處理器:
1. I/O 服務:I/O 服務用來執行實際的 I/O 操作。Apache MINA 2.0 已經提供了一系列支持不同協議的 I/O 服務,如 TCP/IP、UDP/IP、串口和虛擬機內部的管道等。我們也可以實現自己的 I/O 服務。
2. I/O 過濾器:I/O 服務能夠傳輸的是字節流,而上層應用需要的是特定的對象與數據結構。I/O 過濾器用來完成這兩者之間的轉換。I/O 過濾器的另外一個重要作用是對輸入輸出的數據進行處理,滿足橫切的需求。多個 I/O 過濾器串聯起來,形成 I/O 過濾器鏈。
3. I/O 處理器:I/O 處理器用來執行具體的業務邏輯, 對接收到的消息執行特定的處理。

應用示例中要實現I/O 處理器及I/O 服務。

開發環境: Windows 7, Apache MINA 2.0.4, eclipse

A. 實現I/O 處理器
I/O 處理器需要實現 org.apache.mina.core.service.IoHandler接口或者繼承自org.apache.mina.core.service.IoHandlerAdapter。我們這裏選擇後者,代碼如下:

package mina204.ioBusinessHandler;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CalculatorHandler extends IoHandlerAdapter {
private static final Logger LOG = LoggerFactory.getLogger(CalculatorHandler.class);

private ScriptEngine jsEngine = null;

public CalculatorHandler()
{
ScriptEngineManager seManager = new ScriptEngineManager();
jsEngine = seManager.getEngineByName("JavaScript");

if (jsEngine == null)
{
throw new RuntimeException("Can not find out the javascript engine.");
}
}

public void exceptionCaught(IoSession session, Throwable cause) throws Exception
{
LOG.warn(cause.getMessage(), cause);
}

public void messageReceived(IoSession session, Object message) throws Exception
{
String expression = message.toString();
if ("exit".equalsIgnoreCase(expression.trim()) || "quit".equalsIgnoreCase(expression.trim()))
{
session.close(true);
return;
}
try
{
Object result = jsEngine.eval(expression);
session.write(result.toString());
}
catch (ScriptException e)
{
LOG.error(e.getMessage(), e);
session.write("Error script expression! Please check it again.");
}
}
}


B. 實現I/O 服務:在示例中使用 TCP/IP 協議,需要在指定端口(端口號9876)監聽,接受客戶端的連接。代碼如下:

package mina204.ioServer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import mina204.ioBusinessHandler.CalculatorHandler;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CalculatorServer {
private static final int PORT = 9876;

private static Logger log = LoggerFactory.getLogger(CalculatorServer.class);

public static void main(String args[]) throws IOException {
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast("codec2012", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));

acceptor.setHandler(new CalculatorHandler());
acceptor.bind(new InetSocketAddress(PORT));

log.info("Calculator server has started up.... port: " + PORT);
}
}

說明:
過濾器只有在添加到過濾器鏈中的時候才起作用。過濾器鏈是過濾器的容器。過濾器鏈與 I/O 會話是一一對應的關係。org.apache.mina.core.filterchain.IoFilterChain是 Apache MINA 中過濾器鏈的接口,其中提供了一系列方法對其中包含的過濾器進行操作,包括查詢、添加、刪除和替換等。

I/O 事件通過過濾器鏈之後會到達 I/O 處理器。I/O 處理器中與 I/O 事件對應的方法會被調用。Apache MINA 中 org.apache.mina.core.service.IoHandler是 I/O 處理器要實現的接口,一般情況下,只需要繼承自 org.apache.mina.core.service.IoHandlerAdapter並覆寫所需方法即可。

運行步驟:
1. 啓動 CalculatorServer.
Calculator server has started up.... port: 9876
2. Window 7系統中: 控制面板-->程序-->打開或關閉Windows功能-->勾上"Telnet客戶端".
3. 開始-->輸入 cmd 打開 system32\cmd.exe -->輸入 "telnet localhost 9876"即可測試.

Apache MINA與Spring的集成
配置文件spring-mina.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
">
<bean id="calculatorHandler" class="mina204.ioBusinessHandler.CalculatorHandler" />
<bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter" />
<bean id="calculatorCodecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
<constructor-arg>
<bean class="org.apache.mina.filter.codec.textline.TextLineCodecFactory" />
</constructor-arg>
</bean>
<bean id="filterChainBuilder"
class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
<property name="filters">
<map>
<entry key="loggingFilter" value-ref="loggingFilter" />
<entry key="codecFilter" value-ref="calculatorCodecFilter" />
</map>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.net.SocketAddress">
<bean class="org.apache.mina.integration.beans.InetSocketAddressEditor"/>
</entry>
</map>
</property>
</bean>
<bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor"
init-method="bind" destroy-method="unbind">
<property name="defaultLocalAddress" value="127.0.0.1:9876" />
<property name="handler" ref="calculatorHandler" />
<property name="filterChainBuilder" ref="filterChainBuilder" />
</bean>
</beans>

新建I/O Server類: CalculatorServerWithSpringMINA.java 內容如下:

package mina204.ioServer;

import org.apache.mina.core.service.IoAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class CalculatorServerWithSpringMINA {
private static Logger log = LoggerFactory.getLogger(CalculatorServerWithSpringMINA.class);

public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"spring-mina.xml");
IoAcceptor acceptor = (IoAcceptor) ctx.getBean("ioAcceptor");
log.info("Calculator server has started up.... Local Address: "
+ acceptor.getLocalAddress().toString()
+ " Default Local Address: "
+ acceptor.getDefaultLocalAddress().toString());
}

}

同樣的測試步驟可以得到預期的結果。
發佈了94 篇原創文章 · 獲贊 310 · 訪問量 171萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章