websocket實現簡單聊天
阿新 • • 發佈:2018-12-19
上個月公司開發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是要傳送的訊息。好了這樣就可以實現簡單的兩個使用者間的對話了。