Maven依賴:
<!--screw依賴-->
<dependency>
<groupId>cn.smallbun.screw</groupId>
<artifactId>screw-core</artifactId>
<version>1.0.2</version>
</dependency>
<!--hutools-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.12</version>
</dependency>
<!--javaee-api-->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!--json-lib-->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<!--websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
在線模擬websocket請求工具:
https://www.bejson.com/httputil/websocket/

websocketConfig:
/**
* websocket配置
*/
@Configuration
public class websocketConfig {
/**
* 服務(wù)器端點導(dǎo)出器
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
WebSocketOneToOne:
/**
* @ServerEndpoint 注解是一個類層次的注解,它的功能主要是將目前的類定義成一個websocket服務(wù)器端,
* 注解的值將被用于監(jiān)聽用戶連接的終端訪問URL地址,客戶端可以通過這個URL來連接到WebSocket服務(wù)器端
*/
@RestController
@ServerEndpoint(value = "/webSocketOneToOne/{param}")
public class WebSocketOneToOne {
// 靜態(tài)變量,用來記錄當(dāng)前在線連接數(shù)。應(yīng)該把它設(shè)計成線程安全的。
private static int onlineCount;
//實現(xiàn)服務(wù)端與單一客戶端通信的話,可以使用Map來存放,其中Key為用戶標(biāo)識
private static Map<String,WebSocketOneToOne> connections = new ConcurrentHashMap<>();
// 與某個客戶端的連接會話,需要通過它來給客戶端發(fā)送數(shù)據(jù)
private Session session;
//角色
private String role;
//socketid
private String socketId;
/**
* 連接建立成功調(diào)用的方法
*
* @param session
* 可選的參數(shù)。session為與某個客戶端的連接會話,需要通過它來給客戶端發(fā)送數(shù)據(jù)
*/
@OnOpen
public void onOpen(@PathParam("param") String param, Session session) {
this.session = session;
String[] arr = param.split(",");
this.role = arr[0]; //用戶標(biāo)識
this.socketId = arr[1]; //會話標(biāo)識
connections.put(role,this); //添加到map中
addOnlineCount(); // 在線數(shù)加
System.out.println("有新連接加入!新用戶:"+role+",當(dāng)前在線人數(shù)為" + getOnlineCount());
}
/**
* 連接關(guān)閉調(diào)用的方法
*/
@OnClose
public void onClose() {
connections.remove(role); // 從map中移除
subOnlineCount(); // 在線數(shù)減
System.out.println("有一連接關(guān)閉!當(dāng)前在線人數(shù)為" + getOnlineCount());
}
/**
* 收到客戶端消息后調(diào)用的方法
*
* @param message
* 客戶端發(fā)送過來的消息
* @param session
* 可選的參數(shù)
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("來自客戶端的消息:" + message);
JSONObject json=JSONObject.fromObject(message);
String string = null; //需要發(fā)送的信息
String to = null; //發(fā)送對象的用戶標(biāo)識
if(json.has("message")){
string = (String) json.get("message");
}
if(json.has("role")){
to = (String) json.get("role");
}
send(string,role,to,socketId);
}
/**
* 發(fā)生錯誤時調(diào)用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("發(fā)生錯誤");
error.printStackTrace();
}
//發(fā)送給指定角色
public void send(String msg,String from,String to,String socketId){
try {
//to指定用戶
WebSocketOneToOne con = connections.get(to);
if(con!=null){
if(socketId==con.socketId||con.socketId.equals(socketId)){
con.session.getBasicRemote().sendText(from+"說11:"+msg);
}
}
//from具體用戶
WebSocketOneToOne confrom = connections.get(from);
if(confrom!=null){
if(socketId==confrom.socketId||confrom.socketId.equals(socketId)){
confrom.session.getBasicRemote().sendText(from+"說:"+msg);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 獲取在線人數(shù)
* @return
*/
public static synchronized int getOnlineCount() {
return onlineCount;
}
/**
* 在線數(shù)添加
*/
public static synchronized void addOnlineCount() {
WebSocketOneToOne.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketOneToOne.onlineCount--;
}
}
用戶1

連接請求:
ws://127.0.0.1:8888/webSocketOneToOne/1,520
JSON消息內(nèi)容:
{ 'message': '2號用戶你好', 'role': '2', 'socketId': '520' }
用戶2

連接請求:
ws://127.0.0.1:8888/webSocketOneToOne/2,520
JSON消息內(nèi)容:
{ 'message': '1號用戶你好', 'role': '1', 'socketId': '520' }
理解性
message:需要發(fā)送的消息內(nèi)容
role:需要發(fā)送的對象
socketId:需要發(fā)送的房間