Spring4 集成Mina

http://www.tuicool.com/articles/JRzmqi

在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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值