依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
创建服务器端点:
对于 WebSocket 的使用,可以先通过 Spring 创建 Java 配置文件。在这个文件 中, 先新建 Server
EndpointExporter 对象 , 通过它可以定义 WebSocket 服务器的端点 , 这样客户端就能请求服务器 的
端点,其内容如代码清单,有了这个 Bean ,就可以使用@ServerEndpoint 定义一个端点服务类。
在这个站点服务类中,还可以定义 WebSocket 的打开 、关闭 、错误和发送消息的方法。
package com.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
创建webSocket:
WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller
直接@ServerEndpoint("/websocket")@Component启用即可,然后在里面实现@OnOpen,@onClose,@onMessage, @OnError等方法
package com.demo.config;
import org.springframework.stereotype.Service;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
@ServerEndpoint("/ws/{sid}")
@Service
public class WebSocket {
/**
* 这里稍微解释一下这些主要注解的作用 。
* • @ServerEndpoint("/ws") :
* 表示让 Spring 创建 WebSocket 的服务端点 ,其中请求地址是“/ws”。
* • @OnOpen:
* 标注客户端打开 WebSocket 服务端点调用方法。
* • @OnClose :
* 标注客户端关 闭 WebSocket 服务端点调用方法。
* • @OnMessage :
* 标注客户端发送消息, WebSocket 服务端点调用方法。
* • @OnError:
* 标注客户 端请求 WebSocket 服务端点发生异常调用 方法。
* 因为每一个客户端打开时,都会为其创建一个 WebSocket 对象,所以这里的打开方
* 法中都会去计数并且将这个对象保存到 CopyOnWriteArraySet 中,这样就可以知道拥有多少连接。对
* 于关 闭方法则是清除这个对象,并且计数减一。对于消息发送方法 ,则是通过轮询对所有的客户端
* 连接都给予发送消息,所以所有的连接都可以收到这个消息。但是有时候可能只 是需要发送给特定13.4 WebSocket 应用 309
* 的用户,则需要得到用户的信息,然后再发送给特定的用户 。
*/
/**静态变量,用来记录当前在线连接数 。 应该把它设计成线程安全的*/
private static int onlineConunt = 0;
/**连接标识编号*/
private String sid="";
/**oncurrent 包的线程安全 Set ,用来存放每个客户端对应的 WebSocketServiceimpl 对象*/
private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();
/**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
private Session session;
/** 连接建立成功调用的方法 */
@OnOpen
public void onOpen(Session session, @PathParam("sid")String sid ){
this.sid=sid;
this.session = session;
//加入 set 中
webSocketSet.add(this);
//在线数加1
addOnlineCount();
System.out.println("有新连接加入!"+sid+"当前在线人数为:"+getOnlineConunt());
try {
sendMessage("有新的连接加入了!!");
} catch (IOException e) {
System.out.println("IO异常");
}
}
//连接关闭调用的方法
@OnClose
public void onClose(){
//从set中删除
webSocketSet.remove(this);
//在线数减1
subOnlineCount();
System.out.println("有一连接关闭!当前在线人数为:"+getOnlineConunt());
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
* @param session
*/
@OnMessage
public void onMessage(String message,Session session){
System.out.println("来自客户端的消息:"+message);
//群发消息
for(WebSocket item : webSocketSet){
//获取当前用户名称
try {
item.sendMessage(message);
} catch (IOException e) {
System.out.println("发送消息异常");
}
}
}
//发送错误时调用
@OnError
public void onError(Session session,Throwable error){
System.out.println("发送错误");
error.printStackTrace();
}
/**
* 根据编号给指定客户端发送消息
* @param message 客户端消息
* @throws IOException
*/
public static void appointMessage(String message,String sid) throws IOException {
for(WebSocket item : webSocketSet){
if(item.getSid().equals(sid)){
item.sendMessage(message);
}
}
}
/**
* 发送消息
* @param message 客户端消息
* @throws IOException
*/
private void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
//返回在线数
private static synchronized int getOnlineConunt() {
return onlineConunt;
}
//当连接人数增加时
private static synchronized void addOnlineCount() {
WebSocket.onlineConunt ++;
}
//当连接人数减少时
private static synchronized void subOnlineCount() {
WebSocket.onlineConunt --;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
}
前端界面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
var ws = null;
if('WebSocket' in window){
alert("你的浏览器支持 WebSocket");
ws = new WebSocket("ws://192.168.0.142:8080/ws/123");
} else {
alert('你的浏览器不支持webSocket');
}
//建立成功建立的回调方法
ws.onopen = function(event){
alert("消息已发送")
appendMessage("open");
}
//接收到消息的回调方法
ws.onmessage = function(event){
alert("接收到服务端发的消息")
appendMessage(event.data);
}
//连接关闭的回调方法
ws.onclose = function(){
alert("连接已关闭")
appendMessage("close");
}
//连接发送错误的回调方法
ws.onerror = function(){
alert("连接发送错误")
appendMessage("error");
}
//监听窗口关闭事件,当窗口关闭时,主动关闭webSocket连接
//防止连接还没断开就关闭窗口,server端会抛异常
ws.onbeforeunload = function(){
alert("窗口关闭了,关闭socket连接")
ws.onclose();
}
//将消息显示在网页上
function appendMessage(message){
var context = $("#context").html() +"<br/>" +message;
$("#context").html(context);
}
//关闭连接
function closeWebSocket(){
ws.close();
}
//发送消息
function sendMessage(){
var message = $("#message").val();
ws.send(message);
}
</script>
</head>
<body>
<input id="message" type="text"/>
<button onclick="sendMessage()" >发送消息</button>
<button onclick="closeWebSocket()" >关闭连接</button>
<div id="context"></div>
</body>
</html>
评论 (0)