我这里的框架是SpringBoot
首先,我们要有一个前端页面
html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
layout:decorate="layout">
<head>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js" defer></script>
<meta charset="UTF-8"/>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<title>websocket</title>
</head>
<body>
<input type="text" placeholder="请输入您想显示的昵称" name="username" id="username" />
<button onclick="connection()">链接服务器</button>
<!--<button onclick="send()">发送数据到服务器</button>-->
<button onclick="closeSocket()">关闭连接</button>
<p style="border: 1px solid black;width: 680px;height: 500px" id="talkMsg"></p>
<input id="message"/><button id="sendBtn" onclick="send()">发送</button>
</body>
<script>
let sock=""
let username=""
function connection(){
username = $("#username").val()
//ws是WebSocket协议
sock = new WebSocket('ws://localhost:8080/v1/point/' + username);
//WebSocket事件
sock.onopen = () => {
console.log("已经与服务器建立连接.")
}
sock.onmessage = (e) => {
console.log("\n已获取服务器响应的数据.")
console.log(e)
document.getElementById("talkMsg").innerHTML = e.data
}
sock.onclose = () => {
console.log("已关闭与服务器的连接.")
}
sock.onerror = (e) => {
console.log("连接发生异常.")
console.log(e)
}
}
/**
* 发送数据到服务端
*/
function send() {
// sock.send(JSON.stringify({'message': ' hello world! '}))
// sock.send(JSON.stringify({'message': document.getElementById("message").value }))
if(document.getElementById("message").value===""){
alert("抱歉,消息不能为空^_^")
}else{
var message = username + ":" +document.getElementById("message").value
sock.send(message)
//发送完信息之后输入框变为空
document.getElementById("message").value=""
document.getElementById("talkMsg").innerHTML=""
}
}
/**
* 关闭当前用户与WebSocket的连接
*/
function closeSocket() {
//代码只能是 1000,或者[3000, 4999]之间
let code = 3000;
let reason = "我想关闭连接!";
sock.close(code, reason)
}
</script>
</html>
其次,要有相关配置类以及Controller
配置类
java
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 注解会把该方法的返回值当做一个JavaBean,存放在Spring上下文中,以供使用
* ServerEndpointExporter类的作用是,会扫描所有的服务器端点,
* 把带有 @ServerEndpoint 注解的所有类都添加进来
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
Controller
java
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* 该类是用于ws的
* value:当前 WebSocket 服务的访问(监听)地址
*/
@Component //生产对象,声明为类
@ServerEndpoint(value = "/v1/point/{username}") //表明监听地址
public class EndPointController {
//存储用户,通过一个Map来完成存储
private static final Map<String,EndPointController> online = new ConcurrentHashMap<>();
//发送数据是通过session对象实现的,那么就要给每个用户一个session对象
private Session session;
//记录所发出的信息
private static StringBuffer stringBuffer = new StringBuffer();
//以下方法都是被触发,而不是访问
/**
* 连接建立时被调用。
*/
@OnOpen
public void onOpen(@PathParam("username") String username, Session session, EndpointConfig config) throws IOException {
// System.out.println("连接已经建立.");
this.session = session; //等号之前的session指的是第24行的,后面的是该方法的
online.put(username,this);
//给前端的控制台返回数据
// session.getBasicRemote().sendText(username+"已加入群聊");
String message = username + "已加入群聊";
stringBuffer.append(message + "<br/>");
// broadcastAllUsers(stringBuffer.toString());
}
/**
* 收到消息时被调用。
* @param message 前端传递过来的消息。
* @param session
*/
@OnMessage
public void onMessage(String message, Session session) throws IOException {
// System.out.println("收到了消息:" + message);
//将消息推送到前端
// session.getBasicRemote().sendText("谢谢,我收到了你的消息:" + message);
stringBuffer.append(message);
broadcastAllUsers(stringBuffer.toString());
}
/**
* 连接关闭时被调用.
*
* @param session
* @param reason 关闭的理由
*/
@OnClose
public void onClose(Session session, CloseReason reason) {
System.out.println("连接已关闭,关闭理由:" + reason);
}
/**
* 当连接发生异常时被调用
*
* @param session
* @param e
*/
@OnError
public void onError(Session session, Throwable e) {
System.out.println("连接发生异常:" + e.getMessage());
e.printStackTrace();
}
//遍历map将数据发送给每个用户
private void broadcastAllUsers(String message) throws IOException {
Set<String> names = online.keySet(); //keySet返回所有key值列表
for (String name : names) {
EndPointController endPoint = online.get(name);
//将数据发送给每一个人
stringBuffer.setLength(0);
stringBuffer.append(message+ "<br/>");
endPoint.session.getBasicRemote().sendText(stringBuffer.toString());
// System.out.println(stringBuffer.toString());
}
}
}