1、pom.xml文件添加依赖
org.springframework.boot
spring-boot-starter-websocket
2、后台实现
WebSocketConfig.java站点配置
package com.huaxin.oe.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();
}
}
WebSocketServer.java服务端站点
package com.huaxin.oe.component.websocket;
import com.huaxin.oe.base.RespMsg;
import com.huaxin.oe.bean.Message;
import lombok.extern.slf4j.Slf4j;
import org.codehaus.jackson.map.ObjectMapper;
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.concurrent.CopyOnWriteArraySet;
/
*
*
*
@
a
u
t
h
o
r
X
i
e
K
o
n
g
*
@
d
a
t
e
2
0
1
8
/
6
/
2
2
1
1
:
3
4
*
/
@ServerEndpoint("/websocket/{userId}")
@Component
@Slf4j
public class WebSocketServer {
private static int
= 0;
private static CopyOnWriteArraySet
= new
CopyOnWriteArraySet();
private Session session;
private Integer userId = null;
@OnOpen
public void onOpen(Session session, @PathParam("userId") Integer userId) {
this.session = session;
.add(this);
();
.info("
ID:" + userId + "
,
" +
());
/
*
*
*
@
a
u
t
h
o
r
X
i
e
K
o
n
g
*
@
d
a
t
e
2
0
1
8
/
6
/
2
2
1
1
:
3
2
*
/
/
*
*
*
静
态
变
量
,
用
来
记
录
当
前
在
线
连
接
数
。
应
该
把
它
设
计
成
线
程
安
全
的
。
*
/
o
n
l
i
n
e
C
o
u
n
t
/
*
*
*
c
o
n
c
u
r
r
e
n
t
包
的
线
程
安
全
S
e
t
,
用
来
存
放
每
个
客
户
端
对
应
的
M
y
W
e
b
S
o
c
k
e
t
对
象
。
*
/
w
e
b
S
o
c
k
e
t
S
e
t
/
*
*
*
与
某
个
客
户
端
的
连
接
会
话
,
需
要
通
过
它
来
给
客
户
端
发
送
数
据
*
/
/
*
*
*
接
收
u
s
e
r
I
d
*
/
/
*
*
*
连
接
建
立
成
功
调
用
的
方
法
*
/
/
/
加
入
s
e
t
中
w
e
b
S
o
c
k
e
t
S
e
t
/
/
在
线
数
加
1
a
d
d
O
n
l
i
n
e
C
o
u
n
t
l
o
g
用
户
连
接
成
功
当
前
在
线
人
数
为
g
e
t
O
n
l
i
n
e
C
o
u
n
t
");
this.userId = userId;
try {
(userId, "
} catch (IOException e) {
e.printStackTrace();
}
}
.error("WebSocket IO
");
@OnClose
public void onClose() {
.remove(this);
();
.info("
:" +
());
}
@OnMessage
public void onMessage(String messageStr) {
ObjectMapper mapper = new ObjectMapper();
try {
Message message = mapper.readValue(messageStr, Message.class);
} catch (Exception e) {
e.printStackTrace();
}
}
.error("WebSocketServer onMessage", e);
(message.getUserId(), message.getData());
s
e
n
d
M
e
s
s
a
g
e
消
息
服
务
器
连
接
成
功
l
o
g
异
常
/
*
*
*
连
接
关
闭
调
用
的
方
法
*
/
/
/
从
s
e
t
中
删
除
w
e
b
S
o
c
k
e
t
S
e
t
/
/
在
线
数
减
1
s
u
b
O
n
l
i
n
e
C
o
u
n
t
l
o
g
有
一
连
接
关
闭
!
当
前
在
线
人
数
为
g
e
t
O
n
l
i
n
e
C
o
u
n
t
/
*
*
*
收
到
客
户
端
消
息
后
调
用
的
方
法
*
*
@
p
a
r
a
m
m
e
s
s
a
g
e
S
t
r
客
户
端
发
送
过
来
的
消
息
体
*
/
s
e
n
d
M
e
s
s
a
g
e
l
o
g
/
*
*
*
@
p
a
r
a
m
s
e
s
s
i
o
n
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
.error("WebSocketServer onError", error);
public void sendMessage(String message) throws IOException {
ObjectMapper mapper = new ObjectMapper();
this.session.getBasicRemote().sendText(mapper.writeValueAsString(new RespMsg(true,
message)));
}
public static void sendMessage(Integer userId, String message) throws IOException {
.info("
for (WebSocketServer item :
:" + userId + "
:" + message);
) {
if (userId == null) {
item.sendMessage(message);
} else if (item.userId.equals(userId)) {
item.sendMessage(message);
break;
}
}
}
public static synchronized int getOnlineCount() {
return
}
;
public static synchronized void addOnlineCount() {
WebSocketServer.
++;
*
@
p
a
r
a
m
e
r
r
o
r
*
/
l
o
g
/
*
*
*
实
现
服
务
器
主
动
推
送
*
/
/
*
*
*
消
息
推
送
接
口
,
可
以
群
发
和
指
定
用
户
推
送
*
/
l
o
g
推
送
消
息
到
用
户
,
推
送
内
容
w
e
b
S
o
c
k
e
t
S
e
t
/
/
这
里
可
以
设
定
只
推
送
给
这
个
u
s
e
r
I
d
的
,
为
n
u
l
l
则
全
部
推
送
o
n
l
i
n
e
C
o
u
n
t
o
n
l
i
n
e
C
o
u
n
t
}
public static synchronized void subOnlineCount() {
WebSocketServer.
}
}
--;
Message.java发送消息体
package com.huaxin.oe.bean;
public class Message {
private Integer userId;
private String data;
public Message() {
}
public Message(Integer userId, String data) {
this.userId = userId;
this.data = data;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getData() {
return data;
}
public void setData(String data) {
o
n
l
i
n
e
C
o
u
n
t
/
*
*
*
@
a
u
t
h
o
r
X
i
e
K
o
n
g
*
@
d
a
t
e
2
0
1
8
/
6
/
2
5
1
5
:
5
5
*
/
this.data = data;
}
}
3、前端
config下开发和生产环境全局配置添加
WS_URI: '"ws://localhost:8080/websocket/"'
vue界面
4、测试消息发送
@ResponseBody
@RequestMapping("/sendMessage")
public RespMsg pushToWeb(@RequestParam("userId") Integer userId,
@RequestParam("message") String message) {
RespMsg respMsg = new RespMsg();
try {
WebSocketServer.
respMsg.setSuccess(true);
} catch (IOException e) {
e.printStackTrace();
respMsg.setSuccess(false);
respMsg.setMessage(e.getMessage());
}
return respMsg;
}
(userId, message);
/
/
数
据
接
收
J
S
O
N
c
o
n
s
o
l
e
/
/
w
e
b
s
o
c
k
e
t
s
e
n
d
(
a
g
e
n
t
D
a
t
a
)
{
/
/
数
据
发
送
/
/
t
h
i
s
.
w
e
b
s
o
c
k
.
s
e
n
d
(
a
g
e
n
t
D
a
t
a
)
;
/
/
}
,
/
/
关
闭
c
o
n
s
o
l
e
c
o
n
s
o
l
e
s
e
n
d
M
e
s
s
a
g
e