创建的maven工程,pom中导入下面两个
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-websocket-api</artifactId>
<version>8.0.24</version>
</dependency>
核心类,使用注解,提供访问的url,不需要到xml里配置,然后分别实现@OnOpen,@OnMessage,@OnClose, @OnError即可
@ServerEndpoint(value = "/websocket")
public class WebSocket {
public static Map<String, Session> conns = new HashMap<String, Session>();// session的map
/**
*
* @Title: OnOpen
* @Desc: 前端打开链接后,将执行此方法
*
* @param session
* @param config
* 参数
*
*/
@OnOpen
public void OnOpen(Session session, EndpointConfig config) {
// System.out.println("---------open---------" + session.getId());
Session s = null;
for (String conn : conns.keySet()) {// 遍历已有的session(即已有的连接)
s = conns.get(conn);
synchronized (s) {
try {
s.getBasicRemote().sendText(session.getId() + "进入了聊天室");// 根据session发送到对应页面
} catch (IOException e) {
e.printStackTrace();
}
}
}
conns.put(session.getId(), session);
}
/**
*
* @Title: message
* @Desc: 消息处理,接收前端的send,并将消息返回给各个前端连接的页面
*
* @param message
* @param session
* 参数
*
*/
@OnMessage
public void message(String message, Session session) {
// System.out.println("---------message---------" + session.getId());
Session s = null;
for (String conn : conns.keySet()) {
s = conns.get(conn);
synchronized (s) {
try {
s.getBasicRemote()
.sendText((session.getId() == s.getId() ? "我" : session.getId()) + " 说:" + message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
*
* @Title: close
* @Desc: 关闭连接,前端close方法时调用
*
* @param session
* 参数
*
*/
@OnClose
public void close(Session session) {
//System.out.println("---------close---------" + session.getId());
Session s = null;
for (String conn : conns.keySet()) {
s = conns.get(conn);
if (s != session)
synchronized (s) {
try {
s.getBasicRemote().sendText(session.getId() + "离开了聊天室");
} catch (IOException e) {
e.printStackTrace();
}
}
}
conns.remove(session.getId());
}
/**
*
* @Title: close
* @Desc: 系统出错时调用
*
* @param session
* 参数
*
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("error");
error.printStackTrace();
}
}
前端的jsp页面,没什么特别的。。简单弄个
js中的方法与后台的四个注解的方法对应
<%@ page contentType="text/html;charset=UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>聊天室</title>
<script type="text/javascript">
var ws;
var wsUri = "ws://localhost:8080/webChat/websocket";
ws = new WebSocket(wsUri);
//接收后台getBasicRemote().sendText()的内容
ws.onmessage = function(message) {
writeToScreen(message.data);
};
//发送按钮监听,点击按钮后,向后台发送信息,由后台OnMessage接收
function button() {
message = document.getElementById('in').value;
ws.send(message);
}
//发生错误时
ws.onerror = function(msg) {
writeToScreen('<span style="color:red;">系统出错啦</span>' + msg.data);
ws.close();
};
//聊天信息写入窗口中
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
//当关闭页面时执行,调用后台的OnClose方法
window.onbeforeunload = function() {
ws.close();
};
</script>
</head>
<body>
<h2>聊天室</h2>
<div
style="width: 400px; height: 260px; overflow: scroll; border: 1px solid;"
id="output"></div>
<br />
<div style="text-align: left;">
<form action="">
<input id="in" name="message" value="" type="text"
style="width: 400px; height: 60px; border: 1px solid;"> <br />
<br /> <input onclick="button()" value="发送" type="button" />
</form>
</div>
</body>
</html>
效果演示:
分别打开三个窗口,先打开的窗口收到后打开窗口的进入信息
窗口2,发送消息,三个窗口同时收到
关闭窗口1,窗口2和3,收到1离开的消息
一个简单的聊天室就这样实现了,至于样式那些,就懒得弄了。。。
ps:部分老的浏览器并不支持websocket,特别是某i系列