欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

HTML5 WebSocket+Tomcat实现真●Web版即时聊天室(单人+多人)

程序员文章站 2022-05-21 16:08:35
心累,下班回到宿舍,花了一个多小时的时间打开网页。。。真实醉了,对于干IT的人来说,没有网络或者网络卡到爆,真实比割了JJ还难受。首先是LZ的电脑被别人中了木马,是mysql的漏洞...

心累,下班回到宿舍,花了一个多小时的时间打开网页。。。真实醉了,对于干IT的人来说,没有网络或者网络卡到爆,真实比割了JJ还难受。首先是LZ的电脑被别人中了木马,是mysql漏洞,在图书馆连了公共WiFi之后,被别人利用mysql 的漏洞,就中奖了,结果就是电脑多出了一个名为piress的账户具体的原因看这,最简单的办法就是把密码设置的复杂一点,不要是'root'或者'123456'!然后重新装了个系统,宿舍十几个设备同时用一个wifi,网络的情况大家自己脑补!

以上是题外话,上次实现了单人聊天之后,今天把单人聊天(点对点)和多人聊天合并在一起,并优化了一番,用起来像是一个web聊天室,效果图如下

HTML5 WebSocket+Tomcat实现真●Web版即时聊天室(单人+多人)

先进入login.jsp页面,填写你的昵称,登录进入chat.jsp页面,我打开了四个页面模拟四个用户,用户姓名放在session里,方便后台的操作,当然了根据系统需要你可以放用户ID

<%@ page language=java contentType=text/html; charset=UTF-8 pageEncoding=UTF-8%>
<script type=text/javascript src=js/jquery-1.7.2.min.js></script><% String name = request.getParameter(username); session.setAttribute(user, name); %> <script type=text/javascript>
var self = <%=name%>;
var ws = null;
function startWebSocket() {
    if ('WebSocket' in window)
        ws = new WebSocket(ws://localhost:8080/WebSocketUser/websocket.do);
    else if ('MozWebSocket' in window)
        ws = new MozWebSocket(ws://localhost:8080/WebSocketUser/websocket.do);
    else
        alert(not support);
    ws.onmessage = function(evt){
        var data = evt.data;
        var obj = eval ('(' + data + ')');//将字符串转换成JSON
        if(obj.type == 'message'){
            setMessageInnerHTML(obj.data);
        }else if(obj.type == 'user'){
            var userArry = obj.data.split(',');
            $(#userlist).empty();
            $(#userlist).append(

WebIM

登录状态: 正在登录
昵称:

To: *请选择聊天对象
发送内容:
聊天框:

 


样式比较粗糙,没有在界面上花时间,和之前的点对点通信并没有多大的区别,主要就是onMessage那里,根据后台推送的消息,判断消息类型,如果为‘user’,意思是有新用户登录,这个时候要将select里的option更新,效果就是,当前有多少人在线,就有多少个用户选项,当然了不包括自己!如果类型为'message',就是普通的消息类型了。

后台的代码主要改动的是MyMessageInbound文件,代码如下

package socket;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.WsOutbound;

import util.MessageUtil;

public class MyMessageInbound extends MessageInbound {

	private String name;
	public MyMessageInbound() {
		super();
	}

	public MyMessageInbound(String name) {
		super();
		this.name = name;
	}

	@Override  
	protected void onBinaryMessage(ByteBuffer arg0) throws IOException {  

	}  

	@Override  
	protected void onTextMessage(CharBuffer msg) {

		
		HashMap messageMap = MessageUtil.getMessage(msg);    //处理消息类
		String fromName = messageMap.get(fromName);    //消息来自人 的userId
		String toName = messageMap.get(toName);       //消息发往人的 userId
		String mapContent = messageMap.get(content);
		
		if(all.equals(toName)){
			String msgContentString = fromName + 对所有人说:  + mapContent;   //构造发送的消息
			String content = MessageUtil.sendContent(MessageUtil.MESSAGE,msgContentString);
			broadcastAll(content);
		}else{
			try {
				singleChat(fromName,toName,mapContent);
			} catch (IOException e) {
				e.printStackTrace();
			}		
		}
	}  

	private void singleChat(String fromName, String toName, String mapContent) throws IOException {
		HashMap userMsgMap = InitServlet.getSocketList();
		MessageInbound messageInbound = userMsgMap.get(toName);    //在仓库中取出发往人的MessageInbound
		MessageInbound messageFromInbound = userMsgMap.get(fromName);
		if(messageInbound!=null && messageFromInbound!=null){     //如果发往人 存在进行操作
			WsOutbound outbound = messageInbound.getWsOutbound(); 
			WsOutbound outFromBound = messageFromInbound.getWsOutbound();
			
			String msgContentString = fromName + 对 + toName + 说:  + mapContent;   //构造发送的消息
			String contentTemp = MessageUtil.sendContent(MessageUtil.MESSAGE,msgContentString);
			
			outFromBound.writeTextMessage(CharBuffer.wrap(contentTemp.toCharArray()));
			outbound.writeTextMessage(CharBuffer.wrap(contentTemp.toCharArray()));  //
			
			outFromBound.flush();
			outbound.flush();
		}else{
			String content = MessageUtil.sendContent(MessageUtil.MESSAGE,客服不在线请留言...);
			broadcastAll(content);
		}
	}

	@Override  
	protected void onClose(int status) { 
		if(name!=null){
			InitServlet.getSocketList().remove(name);//删除客服ID与用户
			System.out.println(用户 + name + 退出);
		}
		String names = getNames();
		String content = MessageUtil.sendContent(MessageUtil.USER,names);
		broadcastAll(content);
		super.onClose(status);
	}  

	@Override
	protected void onOpen(WsOutbound outbound) { 
		super.onOpen(outbound);
		if(name!=null){
			InitServlet.getSocketList().put(name, this);//存放客服ID与用户
		}
		String names = getNames();
		String content = MessageUtil.sendContent(MessageUtil.USER,names);
		broadcastAll(content);
	}
	
	private String getNames() {
		Map exitUser = InitServlet.getSocketList();
		Iterator it=exitUser.keySet().iterator();
		String names = ;
		while(it.hasNext()){
			String key=it.next();
			names += key + ,;
		}
		String namesTemp = names.substring(0,names.length()-1);
		return namesTemp;
	}

	
	
	public static void broadcastAll(String message){
		Set> set = InitServlet.getSocketList().entrySet();
		WsOutbound outbound = null;
		for(Map.Entry messageInbound: set){
			try {
				outbound = messageInbound.getValue().getWsOutbound();
				outbound.writeTextMessage(CharBuffer.wrap(message));
				outbound.flush();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public int getReadTimeout() {
		return 0;
	}  


}

改动也比较大,主要在onOpen那里,用户成功登录,要添加map里,同时将用户的列表以消息的方式推送给前台,消息的类型为“user”,前台会自动将用户姓名更新到每个用户聊天页面的select里。

用户的成功登录之后会将姓名(id)和对应的MyMessageInbound对象存在map里,只要找对fromName和toName,就能完成(聊天)推送的功能。

对了,这里要注意CharBuffer.wrap(message)的用法作为一个缓冲信息的用法, 用一次就清空了!

这里使用的是不是基于注解的方式,好处也在上一个博客中指出,但是现在tomcat8是用注解的方式,我们的系统是在tomcat8下运行的额,所以,还要把tomcat8版的做出来,呵呵

代码已将上传了源码下载,其实我这些功能是按照交流群里一位网友用socket.io做出的一个系统里的功能,问他要资料和源码,人家很傲娇,什么都不给,于是我就自己做喽,还好,做出来了,效果和他一模一样!

做技术的就是要交流嘛,给点提示也是极好的!

好了,就到这了!