Mina入门教程(二)----Spring4 集成Mina
在spring和mina集成的时候,要十分注意一个问题:版本。
这是一个非常严重的问题,mina官网的demo没错,网上很多网友总结的代码也是对的,但是很多人将mina集成到spring中的时候,总是会发现有个问题:
java.lang.IllegalArgumentException: Cannot convert value of type [org.apache.mina.integration.beans.InetSocketAddressEditor] to required
type [java.lang.Class] for property 'customEditors[java.net.SocketAddress]': PropertyEditor .....
类型不匹配。估计很多人按照网上的demo来做的话,都会遇到这个错误(除非spring是用的2.5或者之前的版本)。这是因为新版的spring有改动:
将一个PropertyEditor 实例传入CustomEditorConfigurer 已经被废除了
所以很多人会遇到这个错误。笔者也是查了N久资料,发现某位学php的牛人解决了该问题。是对spring的配置文件做一点修改:
将原来的:
<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
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<!-- 修改这里 -->
<entry key="java.net.SocketAddress" value="org.apache.mina.integration.beans.InetSocketAddressEditor" >
</entry>
</map>
</property>
</bean>
这样,这个问题就解决了。想想原本的项目中,用的spring+mina没出现问题,真是个侥幸。。。
好了,下面把整合的写一下。
首先是用到的包,这里使用maven,pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>mymina</groupId>
<artifactId>MyMina</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>MyMina</name>
<url>http://maven.apache.org</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
</plugin>
</plugins>
</build> <dependencies> <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-beans</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.0.4</version>
<type>bundle</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-spring</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.3.0</version>
</dependency>
</dependencies>
</project>
这里面有几个配置是比较讲究的,包括那个plugin和mina-core中的配置,配置有点差别,会报一个bundle的错误。
因为用maven,会方便很多,找包的时候,知道依赖就可以了。这里有个网站,可以查找自己需要的依赖包:http://mvnrepository.com/ ,这个网站很不错,类似以前的findjar.com。
然后是spring整合的配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.net.SocketAddress" value="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=":8888" />
<property name="handler" ref="SampleHandler" />
<property name="filterChainBuilder" ref="filterChainBuilder" />
<property name="reuseAddress" value="true" /> </bean>
<bean id="executorFilter"
class="org.apache.mina.filter.executor.ExecutorFilter" />
<bean id="mdcInjectionFilter"
class="org.apache.mina.filter.logging.MdcInjectionFilter">
<constructor-arg value="remoteAddress" />
</bean>
<bean id="codecFilter"
class="org.apache.mina.filter.codec.ProtocolCodecFilter">
<constructor-arg>
<!--
<bean
class="org.apache.mina.filter.codec.textline.TextLineCodecFactory" />
-->
<bean class="cn.org.handler.MyCodeFactory"></bean>
</constructor-arg>
</bean>
<bean id="loggingFilter"
class="org.apache.mina.filter.logging.LoggingFilter" />
<bean id="SampleHandler" class="cn.org.handler.HandlerTwo" />
<!--boss server -->
<bean id="bossSampleHandler" class="cn.org.handler.HandlerOne" /> <bean id="filterChainBuilder"
class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
<property name="filters">
<map>
<entry key="executor" value-ref="executorFilter" />
<entry key="mdcInjectionFilter"
value-ref="mdcInjectionFilter" />
<entry key="codecFilter" value-ref="codecFilter" />
<entry key="loggingFilter" value-ref="loggingFilter" />
</map>
</property>
</bean>
</beans>
这里需要注意的问题,前面已经有写。
再者就是服务端和客户端的代码编写,服务端已经和spring整合了,里面配置了服务端的handler,所以这里主要是服务端的handler:
package cn.org.handler; import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession; public class HandlerTwo extends IoHandlerAdapter { @Override
public void messageReceived(IoSession session, Object message)
throws Exception {
// TODO Auto-generated method stub
// super.messageReceived(session, message);
System.out.println("received message :"+message);
} @Override
public void sessionClosed(IoSession session) throws Exception {
// TODO Auto-generated method stub
super.sessionClosed(session);
} @Override
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
// TODO Auto-generated method stub
super.sessionIdle(session, status);
} }
写一个启动入口:
package cn.org.test; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test {
/**
* @param args
*/
public static void main(String[] args) {
ClassPathXmlApplicationContext ct = new ClassPathXmlApplicationContext("applicationContext-mina.xml");
} }
还缺少一个服务端的编码过滤器:
package cn.org.handler; import java.nio.charset.Charset; import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineDecoder;
import org.apache.mina.filter.codec.textline.TextLineEncoder; public class MyCodeFactory implements ProtocolCodecFactory { private final TextLineEncoder encoder;
private final TextLineDecoder decoder;
/*final static char endchar = 0x1a;*/
final static char endchar = 0x0d;
public MyCodeFactory() {
this(Charset.forName("gb2312"));
}
public MyCodeFactory(Charset charset) {
encoder = new TextLineEncoder(charset, LineDelimiter.UNIX);
decoder = new TextLineDecoder(charset, LineDelimiter.AUTO);
} public ProtocolDecoder getDecoder(IoSession session) throws Exception {
// TODO Auto-generated method stub
return decoder;
}
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
// TODO Auto-generated method stub
return encoder;
}
public int getEncoderMaxLineLength() {
return encoder.getMaxLineLength();
}
public void setEncoderMaxLineLength(int maxLineLength) {
encoder.setMaxLineLength(maxLineLength);
}
public int getDecoderMaxLineLength() {
return decoder.getMaxLineLength();
}
public void setDecoderMaxLineLength(int maxLineLength) {
decoder.setMaxLineLength(maxLineLength);
} }
这样,运行入口程序,服务端就启动了。除了入口,在spring中都有配置,包括端口这些。
然后写一个客户端:
客户端的handler:
package cn.org.handler; import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession; public class HandlerOne extends IoHandlerAdapter {
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
// TODO Auto-generated method stub
//super.messageReceived(session, message);
System.out.println("message :"+message);
} @Override
public void sessionClosed(IoSession session) throws Exception {
// TODO Auto-generated method stub
super.sessionClosed(session);
} @Override
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
// TODO Auto-generated method stub
super.sessionIdle(session, status);
} @Override
public void messageSent(IoSession session, Object message) throws Exception { System.out.println("发送的消息是:"+message.toString());
//super.messageSent(session, message);
} @Override
public void sessionCreated(IoSession session) throws Exception { super.sessionCreated(session);
} @Override
public void sessionOpened(IoSession session) throws Exception {
super.sessionOpened(session);
} }
客户端的入口:
package cn.org.test; import java.net.InetSocketAddress;
import java.nio.charset.Charset; import org.apache.mina.core.future.ConnectFuture;
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.NioSocketConnector; import cn.org.handler.HandlerOne; public class ClintTest { /**
* @param args
*/
public static void main(String[] args) {
// 创建客户端连接器.
NioSocketConnector connector = new NioSocketConnector();
connector.getFilterChain().addLast( "logger", new LoggingFilter() );
connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "GBK" )))); //设置编码过滤器
connector.setHandler(new HandlerOne());//设置事件处理器
ConnectFuture cf = connector.connect(
new InetSocketAddress("127.0.0.1", 8888));//建立连接
cf.awaitUninterruptibly();//等待连接创建完成
cf.getSession().write("知识");//发送消息
cf.getSession().close(true);
cf.getSession().getCloseFuture().awaitUninterruptibly();//等待连接断开
connector.dispose(); } }
这样,当服务端启动的时候,客户端发送一个信息,服务端就会收到,并作相应的处理。
运行结果
客户端控制台输出:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/wanglei/.m2/repository/org/slf4j/slf4j-jdk14/1.7.7/slf4j-jdk14-1.7.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/wanglei/.m2/repository/org/slf4j/slf4j-log4j12/1.3.0/slf4j-log4j12-1.3.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.JDK14LoggerFactory]
八月 27, 2014 8:50:10 下午 org.apache.mina.filter.logging.LoggingFilter log
信息: CREATED
八月 27, 2014 8:50:10 下午 org.apache.mina.filter.logging.LoggingFilter log
信息: OPENED
八月 27, 2014 8:50:10 下午 org.apache.mina.filter.logging.LoggingFilter log
信息: SENT: HeapBuffer[pos=0 lim=0 cap=0: empty]
发送的消息是:知识
八月 27, 2014 8:50:10 下午 org.apache.mina.filter.logging.LoggingFilter log
信息: CLOSED
服务端输出:
SLF4J: Found binding in [jar:file:/C:/Users/wanglei/.m2/repository/org/slf4j/slf4j-log4j12/1.3.0/slf4j-log4j12-1.3.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.JDK14LoggerFactory]
八月 27, 2014 8:50:10 下午 org.apache.mina.filter.logging.LoggingFilter log
信息: CREATED
八月 27, 2014 8:50:10 下午 org.apache.mina.filter.logging.LoggingFilter log
信息: OPENED
八月 27, 2014 8:50:10 下午 org.apache.mina.filter.logging.LoggingFilter log
信息: RECEIVED: 知识
received message :知识
八月 27, 2014 8:50:10 下午 org.apache.mina.filter.logging.LoggingFilter log
信息: CLOSED
Mina入门教程(二)----Spring4 集成Mina的更多相关文章
- 无废话ExtJs 入门教程二十一[继承:Extend]
无废话ExtJs 入门教程二十一[继承:Extend] extjs技术交流,欢迎加群(201926085) 在开发中,我们在使用视图组件时,经常要设置宽度,高度,标题等属性.而这些属性可以通过“继承” ...
- 无废话ExtJs 入门教程二十[数据交互:AJAX]
无废话ExtJs 入门教程二十[数据交互:AJAX] extjs技术交流,欢迎加群(521711109) 1.代码如下: 1 <!DOCTYPE html PUBLIC "-//W3C ...
- 无废话ExtJs 入门教程二[Hello World]
无废话ExtJs 入门教程二[Hello World] extjs技术交流,欢迎加群(201926085) 我们在学校里学习任何一门语言都是从"Hello World"开始,这里我 ...
- mongodb入门教程二
title: mongodb入门教程二 date: 2016-04-07 10:33:02 tags: --- 上一篇文章说了mongodb最基本的东西,这边博文就在深入一点,说一下mongo的一些高 ...
- SpringBoot入门教程(二)CentOS部署SpringBoot项目从0到1
在之前的博文<详解intellij idea搭建SpringBoot>介绍了idea搭建SpringBoot的详细过程, 并在<CentOS安装Tomcat>中介绍了Tomca ...
- PySide——Python图形化界面入门教程(二)
PySide——Python图形化界面入门教程(二) ——交互Widget和布局容器 ——Interactive Widgets and Layout Containers 翻译自:http://py ...
- Elasticsearch入门教程(二):Elasticsearch核心概念
原文:Elasticsearch入门教程(二):Elasticsearch核心概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:ht ...
- RabbitMQ入门教程(二):简介和基本概念
原文:RabbitMQ入门教程(二):简介和基本概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn ...
- JasperReports入门教程(二):中文打印
JasperReports入门教程(二):中文打印 背景 在上一篇中我们介绍了JasperReport的基本入门,也展示了一个报表.但是我们的示例都是使用的英文,如果我们把需要打印的数据改为中文会怎么 ...
- WebGL入门教程(二)-webgl绘制三角形
前面已经介绍过了webgl,WebGL入门教程(一)-初识webgl(http://www.cnblogs.com/bsman/p/6128447.html),也知道了如何绘制一个点,接下来就用web ...
随机推荐
- Microsoft Visual Studio PDB文件相关事宜
Microsoft Visual Studio PDB:调试的符号文件,程序数据库 (PDB) 文件保存着调试和项目状态信息,使用这些信息可以对程序的调试配置: 当以 /ZI 或 /Zi(用于 C/C ...
- JS--该死的&&和||
近段时间搞前端js,零零星星的看了一些框架源码,发现大量存在&&和||,其语法看的我是头冒青烟,也不知道怎么回事,度娘搜吧,现在写下来,以防忘掉. 先来约束一下用词:有一表达式A : ...
- C#创建文件夹,往里追字符串。
/// <summary>写文本日志</summary> /// <param name="StrMessage">日志消息</param ...
- xamarin(3.9.236)里DATETIMENOW的错误。
[ERROR] FATAL UNHANDLED EXCEPTION: System.EntryPointNotFoundException: monodroid_get_system_property ...
- 主机ping不同虚拟机
前提:今天加班时,一不小时把网线踢掉了,然而虚拟机怎么都ping不通了,试过很多办法; 最后.... 简单粗暴的重启了我的主机,对,是主机,不是虚拟机,ok,问题解决; over...
- 深入理解ConcurrentMap.putIfAbsent(key,value) 用法
转自:http://blog.csdn.net/exceptional_derek/article/details/40384659 先看一段代码: public class Locale { pri ...
- [转] 前后端分离开发模式的 mock 平台预研
引入 mock(模拟): 是在项目测试中,对项目外部或不容易获取的对象/接口,用一个虚拟的对象/接口来模拟,以便测试. 背景 前后端分离 前后端仅仅通过异步接口(AJAX/JSONP)来编程 前后端都 ...
- bzoj1503郁闷的出(cheng)纳(xu)员
好痛苦,,,WA了不知道多少遍 错的服了,,, 如果某员工的初始工资低于工资下界,他将立刻离开公司 我也不知道是我语文有问题还是题目有毒,反正这个东西好像不应该算在离开公司的总人数的答案里... 让我 ...
- jquery+bootstrap实现tab切换, 每次切换时都请求数据, 点击提交分别向不同的地址提交数据
今天一个朋友叫帮做一个tab切换, 每一个tab内容区域都是从后台取出的数据, 这些数据要用表格的形式显示处理, 并且表格的内容区域可以修改, 如下所示: 例子查看请演示查看. 截图如图所示: 实现步 ...
- 弹出popwindow 背景变暗
先看下效果图吧 代码如下 package com.example.administrator.popwindowdemo.view; import android.app.Activity; impo ...