1. 程式人生 > >websocket實現簡單聊天

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是要傳送的訊息。好了這樣就可以實現簡單的兩個使用者間的對話了。