websocket实现简单聊天

上个月公司开发APP中用到了实时聊天功能,一开始觉得不可思议,因为完全没有接触过,然后听安卓和ios的说之前的公司都是用第三方sdk的很少看到自己写聊天功能的(南京大公司不多,我想大点的公司自己写还是可以的,因为实现功能和商用还是有点区别的),老板对我们的要求也不高,鼓励我们说先实现功能即可,然后我们就开始入坑了。经过查找资料看教程等一番工作后终于把这个功能实现了。然后下面分享一下,也希望大家可以少踩点坑,大牛可也以指点一下我这个才工作了一年多的菜鸟。

一.首先是一个配置类

使用websocket不用引入外部依赖,因为从tomcat7开始内置了websocket的jar包

创建ChatServerConfigImpl继承ServerApplicationConfi。tomcat容器启动就会自动扫描带有@ServerEndpoint注解的类

import java.util.Set;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;

public class ChatServerConfigImpl implements ServerApplicationConfig   {
	@Override
    public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scan) {
        System.out.println("endPoint扫描到的数量:"+scan.size());
        //返回提供了过滤的作用
        return scan;
    }
	@Override
    public Set<ServerEndpointConfig> getEndpointConfigs(
            Set<Class<? extends Endpoint>> arg0) {
        return null;
    }

二.写Socket,这里包含了服务端对客户端所有的响应

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import net.sf.json.JSONObject;

@ServerEndpoint("/chatSocket")
public class ChatSocket {
	static Logger logger = LogManager.getLogger(ChatSocket.class.getName());
    private  static  List<ChatSocket>  sockets=new Vector<ChatSocket>();
    private  static  List<String>   nameList=new ArrayList<String>();
    private  Session  session;
    private String userId;
    //只要有人连接这个服务,就会打开,执行下面的方法。
    @OnOpen
    public void open(Session session) throws UnsupportedEncodingException{
        //一个session就代表一个通信会话
        System.out.println("sessionid:"+session.getId()+"通道开启了。。。。");
        //把session添加到容器中
        this.session=session;
        sockets.add(this);

        //getQueryString把url中?后面的所有的串儿都取出来
        String queryString = session.getQueryString();
        
        //获取用户名
        this.userId = URLDecoder.decode(queryString.substring(queryString.indexOf("=")+1), "UTF-8");
        logger.info("userId:"+userId);
        nameList.add(userId);

        JSONObject message = new JSONObject();
       
      /*  message.put("alert", userId+"进入聊天室!!");
        message.put("names", nameList);

        broadcast(sockets, message.toString());*/
        System.out.println(userId+"进入聊天室!!");
    }
    //退出
    @OnClose
    public void close(Session session){
        //1.清理退出的session
        sockets.remove(this);
        //2.清理列表用户名
        nameList.remove(this.userId);
        //3.更新消息信息
        JSONObject message = new JSONObject();
        message.put("alert", this.userId+"退出聊天室!!");
        message.put("names", nameList);
        //4.广播消息信息
       // broadcast(sockets, message.toString());
        System.out.println(this.userId+"退出聊天室!!");
    }

    //收
    @OnMessage
    /**
     * 
     * @param session
     * @param msg 从客户端接收的消息
     */
    public void message(Session session,String msg){
        //接收消息

     JSONObject message = new JSONObject();
     String[] split = msg.split("#");
     message.put("sendMsg", split[1]);
     message.put("from", this.userId);
     message.put("date", new Date().toString());
      
        broadcast(sockets, message.toString(),split[0]);

    }
    /**
     * 广播消息
     * @param ss 用户session
     * @param msg 广播消息
     */
    public void broadcast(List<ChatSocket>  ss ,String msg,String toId){
    	System.out.println("toId:"+toId);
    	int index = nameList.indexOf(toId);
    	ChatSocket chatSocket = ss.get(index);
    	try {
			chatSocket.session.getBasicRemote().sendText(msg);
		} catch (IOException e) {
			e.printStackTrace();
		}
    }
}

三.前端的页面也很简单,创建一个简单的chat.jsp测试一下

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<title>聊天室</title>
<script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
<script>
function getQueryVariable(variable)
{
       var query = window.location.search.substring(1);
       var vars = query.split("&");
       for (var i=0;i<vars.length;i++) {
               var pair = vars[i].split("=");
               if(pair[0] == variable){return pair[1];}
       }
       return(false);
}

        var ws; //一个ws对象就是一个通信管道!!,只要不关浏览器,不关闭服务器就一直开着 ${sessionScope.userId}
        var target="ws://localhost:8080/ChatTest/chatSocket?userId="+getQueryVariable("userId");
        alert(target);
        $().ready(function () {
        	     //alert("开始");
                 //页面加载判断是否已经开启了target这个通道,如果没有开启,就开启
                 if ('WebSocket' in window) {
                     ws = new WebSocket(target);
                     alert(ws);
                 } else if ('MozWebSocket' in window) {
                     ws = new MozWebSocket(target);
                     alert(ws);
                 } else {
                     alert('WebSocket is not supported by this browser.');
                     return;
                 } 
                 //接收消息 
                 ws.onmessage = function (event) {
                    eval("var result="+event.data);

                    if(result.alert!=undefined){
                        $("#content").append(result.alert+"<br/>");
                    }

                    if(result.names!=undefined){
                        $("#userList").html("");
                        $(result.names).each(function(){
                            $("#userList").append(this+"<br/>");
                        });
                    }

                    if(result.from!=undefined){
                        $("#content").append(result.from+" "+result.date+
                                " 说:<br/>"+result.sendMsg+"<br/>");
                    }

                 };
             });


        //点击发送消息触发事件
        function send(){
            var msg = $("#msg").val();
            ws.send(msg);
            $("#msg").val("");
        }
    </script>
</head>

<body>
    <h3>欢迎 ${sessionScope.userId} 使用本系统!!</h3>

    <div id="content"
        style="
        border: 1px solid black; width: 400px; height: 300px;
        float: left;
    "></div>
    <div id="userList"
        style="
        border: 1px solid black; width: 100px; height: 300px;
        float:left;
    "></div>

    <div style="clear: both;">
        <input id="msg" />
        <button onclick="send();">send</button>
    </div>

</body>
</html>

四.注意

访问这个jsp的时候应该在后面加上访问用户的id比如http://localhost:8080/ChatTest/chat.jsp?userId=10,这样js代码里面就会获取你传过来的userId然后发起一个ws://localhost:8080/ChatTest/chatSocket?userId=10的会话,/ChatTest/chatSocket接口就会将为一个以userId为标识建立一个长连接,断开连接时传入userId即可。向指定用户发消息时用toId#sendMsg的格式,toId即要对话的用户id,sendMsg是要发送的消息。好了这样就可以实现简单的两个用户间的对话了。

猜你喜欢

转载自blog.csdn.net/King__Jack/article/details/83651252