`
fw2003
  • 浏览: 79369 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

java web聊天室

阅读更多

  对于基于web层的聊天室已经不是新鲜事了,但是用Java开发的还是比较少。原因可能是没有一套好的实现机制,我现在就分享一下个人几个月前的一点心得,也算是抛砖引玉了.

  基本功能如下:分频道聊天对话,分频道分屏显示,表情符号处理,扩展性还是比较强的

 

  众所周知,实现聊天无非2种方式,1种是保持长连接,1种是使用AJAX定时发送请求即客户端将数据从服务器拉过来.由于对SCOKET的一些异常错误处理自己还不是很熟悉,因此采取的是第2种自己熟悉的方式.

  设计思路如下:

   1.在WEB层提供一个类似VO的JAVABEAN(也可作为JSON BEAN),提供一些属性封装数据,一个对象代表1条消息

   2.利用一个工具类计算聊天索引号例如一个单例类,每个用户进入聊天室后会取得当前最大的索引号放入SESSION作为自己的索引号,当发送消息时索引号会增加并且更新当前用户的聊天索引号

   3.实现一个MAP结构来保存聊天记录并放入APPLICATION,我使用的是TREEMAP,键为聊天索引号,值为聊天对象

   4.通过聊天对象的属性判断来按频道以及按用户的信息区分显示,通过用户当前的聊天索引号和当前最大的聊天索引号的比较来控制给用户显示N条之前的信息(即进入聊天室后可以看到多少条以前的信息)以及在聊天信息栏里保持显示的N条信息(也可手动清屏).

   5.开启一个线程定时清除集合里的聊天对象,也可同时持久化形成聊天记录

   6.客户端利用定时器每隔几秒向服务器端发送刷新聊天信息的请求,根据配置由服务器端将N条信息以构造好的HTML格式的字符串的形式发送给客户端显示在一个DIV中

 

   基本思路就是以上,经过实际测试,目前是单台TOMCAT至少能支持350人在线聊天,再多的因为没实际环境,即使使用LoadRunner也得不到太准确的结果.可以扩展的功能有客户端实现字体的改变以及聊天记录查看.

 

   做这个的过程中我的感觉如下:对于多从事企业级开发的JAVA程序员来说,已经自然地会在实现过程中按照J2EE的分层体系进行划分:WEB层 业务层 持久层,或者通过对DDD的学习以及SSH等FRAMEWORK的使用,已经形成了VIEW-ACTION-SERVICE-DOMAIN OBJECT-DAO的定式(实际上SPRING并不是一个支持DDD的FRAMEWORK).但是如果不注重CACHE的使用以及真正在分析和设计时使用DDD(例如采用聚合根控制对整个聚合对象的访问实现针对聚合对象CACHE的FLUSH)的方式,很容易陷入以DB为中心的思考方式,即"80%的业务都是CRUD 90%的业务都必须和DB交互",这是第1点.第2点,比如在做WEB2.0,甚至游戏这种对数据的即时性要求很高,大部分操作在内存的系统的时候,没有了DAO或者不需要频繁调用DAO,应该怎样分层.比如在做这个聊天程序的时候,第1版完成时我发现由于没有DAO,因此没有第1时间就将业务逻辑从控制器中分离,即SERVLET里有很多和业务相关的代码,最后通过不断地重构分离了,不过还是看得出自己的OO思维还不够成熟.

 

  • 大小: 27.2 KB
分享到:
评论
8 楼 islong 2014-06-19  
兄弟,能发份源码吗?有个还没毕业的亲戚做设计需要  求帮助,,谢谢。997952321@qq.com
7 楼 leadingman123 2014-02-18  
求源码分享,谢谢哦!邮箱cctvlive5@163.com
6 楼 tanshen 2013-01-25  
求源码....
5 楼 day6 2011-04-03  
谢谢分享。用web 时,nio 怎么保持长连接?。
4 楼 fw2003 2010-05-08  
lison5566 写道
你好,你的单例类 主要应用在哪里呢

主要是对索引号的递增操作
PS:最近工作需要用到NIO 发现NIO实现异步长连接做聊天服务器性能要好得多
3 楼 lison5566 2010-05-07  
你好,你的单例类 主要应用在哪里呢
2 楼 fw2003 2009-09-07  
phenom 写道
开始我也是用数据库操作,容易多了,直接取得用户ID相关的聊天记录(未读的).但操作数据库相当频繁,可以保存聊天记录.
后来看到大多数是不操作DB的,一直也没想到如何实现.看到你的2,3两点,我是样理解的,用户的索引号比如从0开始,存入session后再修改的话如何取得最大的索引号,再比较其中最大的,想到这里,再看前面的单例,单例是只有一个实例,那里面记录的索引号是不是单个的?比如像在线人数统计.如果是多个人的索引号如何计算?
application是放所有人的聊天记录吧.每次用户用索引号取得和自己相关的未读信息都是从里面查找,查到了,读出来,再删除此次消息.
每次取得的是用索引号取,那就是不可能取出两条消息了,一次取一条消息,因为前面没有提到用list这样的结构,来存储相应的消息,那一个VO就是一条消息了,存入applicatioin中.
博主既然发了文章也不会吝啬赐教吧.谢谢


不好意思最近太忙今天才看到回复
1.索引号是作为key存入TreeMap的,所以取得最大的很简单,value是聊天信息的对象
2.我是额外写了几个单例的类,在实例化的方法上做了同步,只是为了处理并发时索引号的计算.索引号是不需要区分用户来保存的,每次发送消息时是向TreeMap中put,而接收消息是每几秒隔自动触发,只需要将当前用户的索引号和TreeMap中最大的索引号做比较就能知道在2次接收消息之间是否有新的消息产生.

谢谢你的关注和讨论,具体这个聊天程序的效果可以去www.pk250.com参看,有什么新的问题欢迎再次交流
1 楼 phenom 2009-06-23  
开始我也是用数据库操作,容易多了,直接取得用户ID相关的聊天记录(未读的).但操作数据库相当频繁,可以保存聊天记录.
后来看到大多数是不操作DB的,一直也没想到如何实现.看到你的2,3两点,我是样理解的,用户的索引号比如从0开始,存入session后再修改的话如何取得最大的索引号,再比较其中最大的,想到这里,再看前面的单例,单例是只有一个实例,那里面记录的索引号是不是单个的?比如像在线人数统计.如果是多个人的索引号如何计算?
application是放所有人的聊天记录吧.每次用户用索引号取得和自己相关的未读信息都是从里面查找,查到了,读出来,再删除此次消息.
每次取得的是用索引号取,那就是不可能取出两条消息了,一次取一条消息,因为前面没有提到用list这样的结构,来存储相应的消息,那一个VO就是一条消息了,存入applicatioin中.
博主既然发了文章也不会吝啬赐教吧.谢谢

相关推荐

Global site tag (gtag.js) - Google Analytics