spring+hibernate+mina

来源:互联网 发布:计算机编程学校 编辑:程序博客网 时间:2024/06/06 09:59

经过一个星期的研究,终于写好了聊天的服务端,不得不感叹的是网上有些帖子实在copy太多,我还是希望兄弟们能总结自己的经验,弄些原创,免得不懂的兄弟们走弯路,也算为这个行业的发展做点点推动. 不罗嗦了,说正事:

 开始我用了serverScoket直接监听来做聊天,后来发现有阻塞问题,于是采用了nio 但是  也不是很满意,于是采用了mina框架和我之前的框架整合起来,其实这个服务端主要是为了android做聊天整合的。O了,直接说代码:

  首先说下mina部分:

  mina 服务端启动类:

  public class ServerMain extends Thread {


private static final int PORT = 9420;
/** Set this to true if you want to make the server SSL */
private static final boolean USE_SSL = false;


@Override
public void run() {
try {
//启动监听服务
//用Nio方式创建一个非阻塞的serever端socket
IoAcceptor acceptor = new NioSocketAcceptor(); 
// 添加接收数据的过滤器
acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); 
//过滤编码
acceptor.getFilterChain().addLast( "filter", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));//指定编码过滤器 
//指定业务逻辑处理器 
acceptor.setHandler( new ChatProtocolHandler() );
//设置端口号 
acceptor.setDefaultLocalAddress( new InetSocketAddress(PORT) );
acceptor.bind();//启动监听 
System.out.println("开始监听端口:" + PORT); 
} catch (Exception e) {
e.printStackTrace();
}
}
}

消息处理类:

public class ChatProtocolHandler extends IoHandlerAdapter {

//注入数据层接口,必须是static类型 因为ChatProtocolHandler 这个是继承mina框架内IoHandlerAdapter的 每次都会被重新实例,

//如果不static那么那怕 spring启动时set了值也是没有用的
private static IOffLineMessageDao impl;


public void setImpl(IOffLineMessageDao impl) {
this.impl = impl;
}


private final Map<Long, IoSession> userLinks = new LinkedHashMap<Long, IoSession>();
private final Map<IoSession, Long> userLinks_back = new LinkedHashMap<IoSession, Long>();


@Override
public void exceptionCaught(IoSession session, Throwable cause) {
// System.out.println("Unexpected exception." + cause);
// 出现异常时,关闭连接对象
session.close(true);
}


/**
* 有消息进入的时候 处理方法 message 是一个IoBuffer 类
*/
@Override
public void messageReceived(IoSession session, Object message) {
try {
String theMessage = (String) message;
String[] result = theMessage.split(" ", 2);
// 获得的消息
String theCommand = result[0];
System.out.println(" 收到消息:" + theCommand);

//下面是消息处理,看的朋友们可以不管,只要知道这里面用接口对象处理自己的业务就可以了。


Map<String, String> map = JsonOpt.jsonOpt(theCommand);
long fid = Long.parseLong(map.get("fid"));
long uid = Long.parseLong(map.get("id"));


// 保存用户的连接对象
userLinks.put(uid, session);
userLinks_back.put(session, uid);


// 消息处理
// 判断是否为保持长连接的消息
if (fid == -11) {
System.out.println(uid + ":连接信号..读取离线消息..");
// 获取离线消息
List<Offlinemessage> list = impl.getOffLineMessage(uid);
if (list != null && list.size() > 0) {
List<Map<String, String>> listMap = new ArrayList<Map<String, String>>();
for (int i = 0; i < list.size(); i++) {
Offlinemessage offlinemessage = list.get(i);
Map<String, String> map1 = new LinkedHashMap<String, String>();
map1.put("uid", offlinemessage.getUsersByUid()
.getUserid()
+ "");
map1.put("fid", offlinemessage.getUsersByFid()
.getUserid()
+ "");
map1.put("info", offlinemessage.getInfo());
String date = new SimpleDateFormat("MM-dd-HH-mm-ss")
.format(offlinemessage.getSendtime());
map1.put("time", date);
listMap.add(map1);
}
String infos = JsonOpt.getJsonArray(listMap);
session.write(infos);
}
return;
}
// 判断是否转发消息
if (userLinks.containsKey(fid)) {
IoSession ioSession = userLinks.get(fid);
if (ioSession.isConnected()) {
ioSession.write(theMessage);
return;
}
}
// 保存为离线消息
impl.addInfo(uid, fid, map.get("info").toString());
} catch (Exception e) {
e.printStackTrace();
}
}


@Override
public void sessionOpened(IoSession session) throws Exception {
// TODO Auto-generated method stub
super.sessionOpened(session);
System.out.println("打开连接..");
}


@Override
public void sessionClosed(IoSession session) throws Exception {
// 移除连接
if (userLinks_back.containsKey(session)) {
Long id = userLinks_back.get(session);
// 删除连接
userLinks.remove(id);
userLinks_back.remove(session);
}
System.out.println("关闭连接..");
}
}

下面监听类,就是在tomcat启动的时候就启动第一个线程类,服务端线程 也可以不用线程启动

public class ServletListener implements ServletContextListener {


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


}


public void contextInitialized(ServletContextEvent arg0) {
// TODO Auto-generated method stub
// 启动mina
new ServerMain().start();
}


}

下面是web.xml里面需要加的一句监听:

          <listener>

 <listener-class>lbaca.mina.ServletListener</listener-class>
</listener>

下面是spring配置文件需要加的配置:

      <!-- ===数据层=== -->

   <bean id="offLineMessageDaoImpl" class="lbaca.dao.daoImpl.OffLineMessageDaoImpl" >
        <property name="sessionFactory"  ref="sessionFactory"></property>
   </bean>


<!-- ====mina数据处理==== -->
<bean  id="chatProtocolHandler"  class="lbaca.mina.ChatProtocolHandler">
 <property name="impl" ref="offLineMessageDaoImpl"></property>
</bean>

到次为止已经搞定了,其实就是将数据层的接口注入到消息处理的类里面。一个星期的工作到此总结收工,继续android端的开发。


原创粉丝点击