花了20分钟,给女朋友们写了一个web版群聊程序
WebSocket详解
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。可以说WebSocket的出现,使得浏览器具备了实时双向通信的能力
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
原来为了实现推送,很多公司用的是Ajax 轮询,即按照特定的时间间隔,由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。而websocket就可以解决这些问题。
在Spring Boot中使用WebSocket
1.pom文件增加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.增加配置
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
3.Java代码
@Component
@ServerEndpoint("/websocket")
public class WebSocketServerController {
// 收到消息调用的方法
@OnMessage
public void onMessage(String message) {
System.out.println("收到的消息为 " + message);
}
// 建立连接调用的方法
@OnOpen
public void onOpen() {
System.out.println("Client connected");
}
// 关闭连接调用的方法
@OnClose
public void onClose() {
System.out.println("Connection closed");
}
// 传输消息错误调用的方法
@OnError
public void OnError(Throwable error) {
System.out.println("Connection error");
}
}
4.前端代码
<!DOCTYPE html>
<html>
<head>
<title>Testing websockets</title>
</head>
<body>
<div>
<textarea rows="3" cols="20" id="content"></textarea>
<br>
<input type="submit" value="Start" onclick="start()" />
</div>
<div id="messages"></div>
<script type="text/javascript"> var webSocket =
new WebSocket('ws://localhost:8080/websocket');
webSocket.onerror = function(event) {
onError(event)
};
webSocket.onopen = function(event) {
onOpen(event)
};
webSocket.onmessage = function(event) {
onMessage(event)
};
webSocket.onclose = function(event) {
onClose(event)
};
function onMessage(event) {
document.getElementById('messages').innerHTML
+= '<br />' + event.data;
}
function onOpen(event) {
document.getElementById('messages').innerHTML
= 'Connection established';
}
function onError(event) {
alert(event);
}
function onClose(event) {
alert(event);
}
function start() {
var text = document.getElementById('content').value;
webSocket.send(text);
}
</script>
</body>
</html>
所以你看websocket其实很简单,前后端各写4个事件方法就行了(当然你也可以省略一些方法)
1.建立连接2.收到消息3.传输消息失败4.关闭连接
事件和具体会话关联
如果事件想和具体会话关联,方法上只要加Session参数就行(4种事件类型的方法上都可加)
举个例子,直接将用户发送给服务端的话再返回给客户端
// 收到消息调用的方法
@OnMessage
public void onMessage(Session session, String message) {
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
传递参数
方法上加@PathParam参数即可
@Component
@ServerEndpoint("/websocket/{sid}")
public class WebSocketServerController
@OnOpen
public void onOpen(@PathParam("sid") String sid) {
System.out.println("Client connected");
}
实现一个在线群聊
后端接口
@Slf4j
@Component
@ServerEndpoint("/groupChat/{sid}/{username}")
public class GroupChatController {
// 保存 组id->组成员 的映射关系
private static ConcurrentHashMap<String, List<Session>> groupMemberInfoMap = new ConcurrentHashMap<>();
// 收到消息调用的方法,群成员发送消息
@OnMessage
public void onMessage(@PathParam("sid") String sid,
@PathParam("username") String username, String message) {
List<Session> sessionList = groupMemberInfoMap.get(sid);
// 先一个群组内的成员发送消息
sessionList.forEach(item -> {
try {
String text = username + ": " + message;
item.getBasicRemote().sendText(text);
} catch (IOException e) {
e.printStackTrace();
}
});
}
// 建立连接调用的方法,群成员加入
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
List<Session> sessionList = groupMemberInfoMap.get(sid);
if (sessionList == null) {
sessionList = new ArrayList<>();
groupMemberInfoMap.put(sid,sessionList);
}
sessionList.add(session);
log.info("Connection connected");
log.info("sid: {}, sessionList size: {}", sid, sessionList.size());
}
// 关闭连接调用的方法,群成员退出
@OnClose
public void onClose(Session session, @PathParam("sid") String sid) {
List<Session> sessionList = groupMemberInfoMap.get(sid);
sessionList.remove(session);
log.info("Connection closed");
log.info("sid: {}, sessionList size: {}", sid, sessionList.size());
}
// 传输消息错误调用的方法
@OnError
public void OnError(Throwable error) {
log.info("Connection error");
}
}
前端代码很简单,放github了地址为:https://github.com/erlieStar/spring-boot-websocket
下面来看效果
注意先连接,后发送
在线聊天地址:
http://www.javashitang.com:8090/
文章转载自公众号:Java识堂