在 Tomcat 裡實作 websocket 滿簡單的。
WebSocket可以在伺服器和瀏覽器之間建立雙向通訊,今天要來用WebSocket來實現一個簡單的聊天室做範例,Tomcat 伺服器的最小版本要求是 Tomcat 7, 目前我是使用 Tomcat 7.
附註1:如果你是走 ssl 需要把 ws:// 修改為 wss://
附註2:如果是 html 去存取別台伺服器的 wss, 如果是自簽的憑證會有問題。
附註3:不需要額外修改 tomcat 的 server.xml 或 web.xml
範例1:
==================
webSocketTest.html :
<!DOCTYPE html> <html> <head> <title>WebSocket Test</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="js/webSocket.js"></script> </head> <body> <div> <form id="chatRoomForm" onsubmit="return false;"> 聊天室 名字: <input type="text" id="userNameInput" /> <input type="button" id="loginBtn" value="登入" /> <span id="infoWindow"></span> <input type="text" id="userinput" /> <input type="submit" value="送出訊息" /> </form> </div> <div id="messageDisplay"></div> </body> </html>
webSocket.js :
window.onload = function () { //獲取DOM元件 var loginBtn = document.getElementById("loginBtn"); var userNameInput = document.getElementById("userNameInput"); var infoWindow = document.getElementById("infoWindow"); var userinput = document.getElementById("userinput"); var chatRoomForm = document.getElementById("chatRoomForm"); var messageDisplay = document.getElementById("messageDisplay"); var webSocket; var isConnectSuccess = false; //設置登入鈕的動作,沒有登出,登入才可發言 loginBtn.addEventListener("click", function () { //檢查有無輸入名稱 if (userNameInput.value && userNameInput.value !== "") { setWebSocket(); //設置WebSocket連接 } else { infoWindow.innerHTML = "請輸入名稱"; } }); //Submit Form時送出訊息 chatRoomForm.addEventListener("submit", function () { sendMessage(); return false; }); //使用webSocket擁有的function, send(), 送出訊息 function sendMessage() { //檢查WebSocket連接狀態 if (webSocket && isConnectSuccess) { var messageInfo = { userName: userNameInput.value, message: userinput.value } webSocket.send(JSON.stringify(messageInfo)); } else { infoWindow.innerHTML = "未登入"; } } //設置WebSocket function setWebSocket() { //開始WebSocket連線 webSocket = new WebSocket('ws://localhost:8080/WebSocketTest/websocket'); //以下開始偵測WebSocket的各種事件 //onerror , 連線錯誤時觸發 webSocket.onerror = function (event) { loginBtn.disabled = false; userNameInput.disabled = false; infoWindow.innerHTML = "登入失敗"; }; //onopen , 連線成功時觸發 webSocket.onopen = function (event) { isConnectSuccess = true; loginBtn.disabled = true; userNameInput.disabled = true; infoWindow.innerHTML = "登入成功"; //送一個登入聊天室的訊息 var firstLoginInfo = { userName : "系統", message : userNameInput.value + " 登入了聊天室" }; webSocket.send(JSON.stringify(firstLoginInfo)); }; //onmessage , 接收到來自Server的訊息時觸發 webSocket.onmessage = function (event) { var messageObject = JSON.parse(event.data); messageDisplay.innerHTML += " " + messageObject.userName + " 說 : " + messageObject.message; }; } };
WebSocketEndpointTest.java:
import java.io.IOException; import java.util.ArrayList; import javax.websocket.EncodeException; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint("/websocket") public class WebSocketEndpointTest { //用來存放WebSocket已連接的Socket static ArrayList<Session> sessions; @OnMessage public void onMessage(String message, Session session) throws IOException, InterruptedException, EncodeException { System.out.println("User input: " + message); //session.getBasicRemote().sendText("Hello world Mr. " + message); //for (Session s : session.getOpenSessions()) { for (Session s : sessions) { //對每個連接的Client傳送訊息 if (s.isOpen()) { s.getBasicRemote().sendText(message); } } } @OnOpen public void onOpen(Session session) { //紀錄連接到sessions中 System.out.println("Client connected"); if (sessions == null) { sessions = new ArrayList<Session>(); } sessions.add(session); System.out.println("Current sessions size: " + sessions.size()); } @OnClose public void onClose(Session session) { //將連接從sessions中移除 System.out.println("Connection closed"); if (sessions == null) { sessions = new ArrayList<Session>(); } sessions.remove(session); System.out.println("Current sessions size: " + sessions.size()); } }
範例 2號,我是用這組來修改。
我们需要2个jar包:
- tomcat7-websocket.jar
- websocket-api.jar
這两个jar包是在tomcat7及以上版本的lib目录下获得的。主要是封装了websocket的API方法类以及实现了其中的方法。
当跳转到chat.jsp页面的时候,会加载其中的js文件,js中会开启一个通信管道。页面加载判断是否已经开启了这个通道,如果没有开启,就开启。当管道开启的时候就会触发onopen事件。触发的方法在ChatSocket类中。
chat.jsp:
<body> <script src="../js/jquery-3.2.1.min.js"></script> <script src="../js/popper.min.js"></script> <script src="../js/bootstrap.min.js"></script> <script> var ws; //一个ws对象就是一个通信管道!!,只要不关浏览器,不关闭服务器就一直开着 var target="wss://192.168.1.215:8443/Core/WsPushServer?username=max32002"; $().ready(function connect() { //页面加载判断是否已经开启了target这个通道,如果没有开启,就开启 if ('WebSocket' in window) { ws = new WebSocket(target); } else if ('MozWebSocket' in window) { ws = new MozWebSocket(target); } else { alert('WebSocket is not supported by this browser.'); return; } //onerror , 連線錯誤時觸發 ws.onerror = function (event) { alert("登入失敗"); }; //接收消息 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> <h3>欢迎 max32002 使用本系统!!</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>
Java:
import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import com.google.gson.Gson; @ServerEndpoint("/WsPushServer") public class WsPushServer { private static Set<WsPushServer> sockets=new HashSet<WsPushServer>(); private static List<String> nameList=new ArrayList<String>(); private Session session; private String username; private Gson gson=new Gson(); //只要有人连接这个服务,就会打开,执行下面的方法。 @OnOpen public void open(Session session){ //一个session就代表一个通信会话 System.out.println("sessionid:"+session.getId()+"通道开启了。。。。"); //把session添加到容器中 this.session=session; sockets.add(this); //getQueryString把url中?后面的所有的串儿都取出来 String QueryString = session.getQueryString(); System.out.println(QueryString); //获取用户名 this.username = QueryString.substring(QueryString.indexOf("=")+1); nameList.add(username); String message = (username+"进入聊天室!!"); broadcast(sockets, gson.toJson(message) ); } //退出 @OnClose public void close(Session session){ //1.清理退出的session sockets.remove(this); //2.清理列表用户名 nameList.remove(this.username); //3.更新消息信息 String message=(this.username+"退出聊天室!!"); //4.广播消息信息 broadcast(sockets, gson.toJson(message)); } @OnError public void onError(Throwable e){ e.printStackTrace(); } //收 @OnMessage /** * * @param session * @param msg 从客户端接收的消息 */ public void message(Session session,String msg){ //接收消息 String message=(this.username + ":" + msg + ":" + new Date().toString()); broadcast(sockets, gson.toJson(message)); } /** * 广播消息 * @param ss 用户session * @param msg 广播消息 */ public void broadcast(Set<WsPushServer> ss ,String msg ){ for (Iterator<WsPushServer> iterator = ss.iterator(); iterator.hasNext();) { WsPushServer chatSocket = (WsPushServer) iterator.next(); try { chatSocket.session.getBasicRemote().sendText(msg); } catch (IOException e) { e.printStackTrace(); } } } }
相關文章:
- http://blog.csdn.net/kisscatforever/article/details/72417091
- http://hklifenote.blogspot.tw/2017/02/websocket-tomcat-v80.html
- https://github.com/yuechang/webSocket
- http://www.itread01.com/articles/1478584824.html
- https://examples.javacodegeeks.com/enterprise-java/tomcat/apache-tomcat-websocket-tutorial/
- http://www.jianshu.com/p/c57b0055dc20
- http://colobu.com/2015/02/27/WebSockets-tutorial-on-Wildfly-8/