在 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/