maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
Java 类
WebSocket 配置
package com.zpjiang.chat;
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 接口入径(ws://localhost:8087/socket/websocket/userId)
package com.zpjiang.chat;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {
private Session session;
private String userId;
private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();
private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<String, Session>();
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId) {
try {
this.session = session;
this.userId = userId;
webSockets.add(this);
sessionPool.put(userId, session);
log.info("【websocket消息】有新的连接,总数为:" + webSockets.size());
} catch (Exception e) {
}
}
@OnClose
public void onClose() {
try {
webSockets.remove(this);
sessionPool.remove(this.userId);
log.info("【websocket消息】连接断开,总数为:" + webSockets.size());
} catch (Exception e) {
}
}
@OnMessage
public void onMessage(String message) {
log.info("【websocket消息】收到客户端消息:" + message);
Message msg = JSONUtil.toBean(message, Message.class);
sendOneMessage(msg.getToUID(), message);
}
@OnError
public void onError(Session session, Throwable error) {
log.error("用户错误,原因:" + error.getMessage());
error.printStackTrace();
}
public void sendAllMessage(String message) {
log.info("【websocket消息】广播消息:" + message);
for (WebSocket webSocket : webSockets) {
try {
if (webSocket.session.isOpen()) {
webSocket.session.getAsyncRemote().sendText(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void sendOneMessage(String userId, String message) {
Session session = sessionPool.get(userId);
if (session != null && session.isOpen()) {
try {
log.info("【websocket消息】 单点消息:" + message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void sendMoreMessage(String[] userIds, String message) {
for (String userId : userIds) {
Session session = sessionPool.get(userId);
if (session != null && session.isOpen()) {
try {
log.info("【websocket消息】 单点消息:" + message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
controller
package com.zpjiang.chat;
import javax.annotation.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@RestController
public class WebsocketController {
@Resource
private WebSocket webSocket;
@GetMapping("/page")
public ModelAndView page() {
return new ModelAndView("webSocket");
}
@RequestMapping("/push/{toUID}/{msg}")
public ResponseEntity<String> pushToClient(@PathVariable("msg")String message, @PathVariable("toUID") String toUID) throws Exception {
webSocket.sendOneMessage(toUID, message);
return ResponseEntity.ok("Send Success!");
}
}
消息bean
package com.zpjiang.chat;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Data
@Getter
@Setter
public class Message {
private String toUID;
private String Msg;
}
main方法类
package com.zpjiang.chat;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class ChatApplication {
public static void main(String[] args) {
SpringApplication.run(ChatApplication.class, args);
}
}
配置文件
server:
port: 8087
servlet:
context-path: /socket
spring:
application:
name: websocket
视图文件 /src/main/resources/templates/webSocket.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebSocket消息通知</title>
</head>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
var socket;
function openSocket() {
if (typeof (WebSocket) === "undefined") {
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
var socketUrl = "http://localhost:8087/socket/websocket/"
+ $("#uid").val();
socketUrl = socketUrl.replace("https", "ws").replace("http", "ws");
console.log(socketUrl);
if (socket != null) {
socket.close();
socket = null;
}
socket = new WebSocket(socketUrl);
socket.onopen = function() {
console.log("WebSocket已打开");
};
socket.onmessage = function(msg) {
console.log(msg.data);
};
socket.onclose = function() {
console.log("WebSocket已关闭");
};
socket.onerror = function() {
console.log("WebSocket发生了错误");
}
}
}
var socket1;
function openSocket1() {
if (typeof (WebSocket) === "undefined") {
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
var socketUrl = "http://localhost:8087/socket/websocket/"
+ $("#toUID").val();
socketUrl = socketUrl.replace("https", "ws").replace("http", "ws");
console.log(socketUrl);
if (socket1 != null) {
socket1.close();
socket1 = null;
}
socket1 = new WebSocket(socketUrl);
socket1.onopen = function() {
console.log("WebSocket已打开");
};
socket1.onmessage = function(msg) {
console.log("socket1收到消息:");
console.log(msg.data);
};
socket1.onclose = function() {
console.log("WebSocket已关闭");
};
socket1.onerror = function() {
console.log("WebSocket发生了错误");
}
}
}
function sendMessage() {
if (typeof (WebSocket) === "undefined") {
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
console.log('{"toUID":"' + $("#toUID").val() + '","Msg":"'
+ $("#msg").val() + '"}');
socket.send('{"toUID":"' + $("#toUID").val() + '","Msg":"'
+ $("#msg").val() + '"}');
}
}
function sendMessage1() {
if (typeof (WebSocket) === "undefined") {
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
console.log('{"toUID":"' + $("#uid").val() + '","Msg":"'
+ $("#msg").val() + '"}');
socket1.send('{"toUID":"' + $("#uid").val() + '","Msg":"'
+ $("#msg").val() + '"}');
}
}
</script>
<body>
<p>【uid】:
<div>
<input id="uid" name="uid" type="text" value="1">
</div>
<p>【toUID】:
<div>
<input id="toUID" name="toUID" type="text" value="2">
</div>
<p>【Msg】:
<div>
<input id="msg" name="msg" type="text" value="hello WebSocket2">
</div>
<p>【第一步操作:】:
<div>
<button onclick="openSocket()">开启socket</button>
<button onclick="openSocket1()">开启socket2</button>
</div>
<p>【第二步操作:】:
<div>
<button onclick="sendMessage()">发送消息</button>
<button onclick="sendMessage1()">发送消息2</button>
</div>
</body>
</html>