`
zhaohaolin
  • 浏览: 985074 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Mina2和Spring(2.5)在web项目中的结合使用

    博客分类:
  • JAVA
 
阅读更多

项目结构图如下:

Mina2和Spring(2.5)在web项目中的结合使用 - abjuration - abjuration  

说明: com.test.server包下是mina的服务端程序, MinaServer_Unuse.java 类就是一般的mina服务端主类, 但这里不用它来启动, 而是通过applicationContext-minaServer.xml 来启动. 
但这个spring配置文件不会自己启动,所以用到 com.test.action包下的 InitListener.java来调用这个spring配置文件, 达到启动的目的.
com.test.client包是个普通的mina客户端类, 这里主要用来检查与spring结合后的mina服务端运行是否正常.
项目会发布到tomcat进行测试.
注: 本文基本不会讲解mina如何使用, 这种文章很多. 所有代码复制过去即可观察效果


 InitListener.java:
package com.test.action;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class InitListener implements ServletContextListener {

 public void contextDestroyed(ServletContextEvent arg0) {
  // TODO Auto-generated method stub
 }

 public void contextInitialized(ServletContextEvent sce) {
  new ClassPathXmlApplicationContext("applicationContext-minaServer.xml");
  //在tomcat的启动过程中,会看到控制台打印此语句.
  System.out.println("********mina server 启动完毕*********");
 }
}

 

SomeServer:
package com.test.action;

/** 这个类主要是通过spring注入给MinaServerHandler用的,表示: mina在接收到信息后,该由主要业务类来处理了. 仅作演示用 */
public class SomeServer {
 public void doSome(){
  System.out.println("someServer todo something!");
 }
}

 

MinaClient:
package com.test.client;

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

import org.apache.mina.core.future.ConnectFuture;
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.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

/**
 * 客户端
 * @author yan
 */
public class MinaClient {
 public void start() throws IOException{
  NioSocketConnector connector = new NioSocketConnector();
//  connector.getFilterChain().addLast( "logger", new LoggingFilter() );
  //设置编码过滤器
  connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
  connector.setConnectTimeoutMillis(10000);
  connector.setHandler(new MinaClientHandler());
  ConnectFuture cf = connector.connect(new InetSocketAddress("192.168.1.83",10000));
  //等待连接创建完成
  cf.awaitUninterruptibly();
  IoSession session = cf.getSession();

  System.out.println("客户端准备完毕");
  //以下是等待控制台的输入
  while(true){
   BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
   String line = in.readLine();
   try {
    if(!"".equals(line)){
     session.write(line);
    } else if("quit".equals(line)){
     break;
    }
   } catch (Exception e) {
    e.printStackTrace();
    System.out.println("服务端关闭了连接");
   }
  }
  session.getCloseFuture().awaitUninterruptibly();
  connector.dispose();
 }
 
 public static void main(String[] args) {
  try {
   new MinaClient().start();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}


MinaClientHandler:
package com.test.client;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
/**
 * 客户端事件处理类
 * @author yan
 */
public class MinaClientHandler extends IoHandlerAdapter {

 @Override
 public void exceptionCaught(IoSession session, Throwable cause)
   throws Exception {
  System.out.println("服务端关闭了连接");
 }

 @Override
 public void messageReceived(IoSession session, Object message)throws Exception {
  System.out.println("客户端接收到的消息: "+message);
 }

 @Override
 public void sessionCreated(IoSession session) throws Exception {
  System.out.println("客户端连接上服务器");
 }
}

MinaServerHandler:
package com.test.server;

import java.net.InetSocketAddress;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;

import com.test.action.SomeServer;

/**
 * mina服务端的的事件处理类
 * @author yan
 */
public class MinaServerHandler extends IoHandlerAdapter {
 private SomeServer someServer;
 
 public void setSomeServer(SomeServer someServer) {
  this.someServer = someServer;
 }

 @Override
 public void exceptionCaught(IoSession session, Throwable cause){
  try {
   System.out.println("客户端 "+session.getRemoteAddress()+" 关闭了连接");
  } catch (Exception e) {
   // TODO: handle exception
  }
 }

 /**
  * 服务端接收消息
  */
 @Override
 public void messageReceived(IoSession session, Object message)
   throws Exception {
  someServer.doSome();
  String msg = message.toString();
  if("quit".equals(msg)){
   session.close(false);
   return;
  }
  //对客户端做出的响应
  for (Iterator<String> it = sessions.keySet().iterator(); it.hasNext();) {
   IoSession ss = sessions.get(it.next());
   ss.write( "message from server:: "+session.getRemoteAddress()+" 说: " + msg );//返回客户端发送过来的消息
  }
 }

 /**
  * 客户端连接的会话创建
  */
 @Override
 public void sessionCreated(IoSession session) throws Exception {
  InetSocketAddress isa = (InetSocketAddress)session.getRemoteAddress();
  System.out.println("客户端:"+isa.getAddress().getHostAddress()+":"+isa.getPort()+" 连接进来了");
  sessions.put(session.getRemoteAddress().toString(), session);
 }
 
 private ConcurrentMap<String, IoSession> sessions=new ConcurrentHashMap<String, IoSession>();
}

MiniServer_Unuse:
package com.test.server;

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

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.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * mina服务端. 这个类不会用,除非你要手动来启动.
 * @author yan
 *
 */
public class MiniServer_Unuse {
 private static final int port = 10000;

 public void start() throws IOException {
  // 用于创建服务端的监听
  IoAcceptor acceptor = new NioSocketAcceptor();
  // acceptor.getFilterChain().addLast("logger", new LoggingFilter() );
  // 编码过滤器
  // acceptor.getFilterChain().addLast("encode", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
  acceptor.getFilterChain().addLast("encode",new ProtocolCodecFilter(new MyCodecFactory()));
  // 设置事件处理类
  acceptor.setHandler(new MinaServerHandler());
  // 设置地址和端口
  acceptor.setDefaultLocalAddress(new InetSocketAddress("192.168.1.100",port));
  acceptor.bind();
  System.out.println("服务端准备完毕");
 }
 
  public static void main(String[] args) {
  new ClassPathXmlApplicationContext("applicationContext.xml");
  try {
   new MiniServer_Unuse().start();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

 

MyCodecFactory:
package com.test.server;

import java.nio.charset.Charset;

import org.apache.mina.filter.codec.textline.TextLineCodecFactory;

package com.test.server;

import java.nio.charset.Charset;

import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
/**
 * <style type="text/css">body{background:#C7EDCC;}</style>
 * 这个类集成自TextLineCodecFactory, 表示对mina的数据的解析方式.
 * 本来可以直接用TextLineCodecFactory的, 但这个类的目的是表示我们可以有自己的方式来解析.
 * MyCodecFactory.java
 * @author yan
 */
public class MyCodecFactory extends TextLineCodecFactory {
 public MyCodecFactory(){
  super(Charset.forName("UTF-8"));
 }
}

public class MyCodecFactory extends TextLineCodecFactory {
 public MyCodecFactory(){
  super(Charset.forName("UTF-8"));
 }
}

applicationContext-minaServer.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=" "
 xmlns:xsi=" "
 xsi:schemaLocation=" ">
 
<!-- 这里是那个自定义的类 -->
 <bean id="someServer" class="com.test.action.SomeServer"></bean>
 
 <!-- 自定义的serverHandler -->
 <bean id="serverHandler" class="com.test.server.MinaServerHandler">
  <property name="someServer" ref="someServer"></property>
 </bean>
 <!-- 自定义的编码过滤器 -->
 <bean id="myCodecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
  <constructor-arg>
   <bean class="com.test.server.MyCodecFactory" />
  </constructor-arg>
 </bean>
 <!-- 指定服务端地址和端口 -->
 <bean id="address" class="java.net.InetSocketAddress">
  <constructor-arg index="0" value="192.168.1.100"/>
  <constructor-arg index="1" value="10000"/>
 </bean>
 <!-- 日志filter -->
 <bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter" />
 <!--
 <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="com.test.server.MyCodecFactory"></bean>
  </constructor-arg>
 </bean>
 <!-- 过滤器链 -->
 <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>
  
 <!-- 开始运行socket服务 -->
 <bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor"
  init-method="bind" destroy-method="unbind">
  <property name="defaultLocalAddress" ref="address" />
  <property name="handler" ref="serverHandler" />
  <property name="filterChainBuilder" ref="filterChainBuilder" />
  <property name="reuseAddress" value="true" />
 </bean>
</beans>

 

web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
 xmlns=" "
 xmlns:xsi=" "
 xsi:schemaLocation="
  ">

  <listener>
  <listener-class>com.test.action.InitListener</listener-class>
 </listener>


  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>


部署, 启动(如下图):

Mina和Spring(2.5)在web项目中的结合使用 - abjuration - abjuration
看到了打印的信息. 说明启动成功了.


F11运行MinaClient.java, 并在控制台输入一些话, 会看到服务端的返回信息(如下图).

Mina和Spring(2.5)在web项目中的结合使用 - abjuration - abjuration
 

 在切换回tomcat的控制台视图, 观察服务端部分的打印(如下图):

Mina和Spring(2.5)在web项目中的结合使用 - abjuration - abjuration
 
OK, that"s all.


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics