前段时间做了一个二手平台,上面有个聊天功能,今天就给它写一写,具体页面就不写了,讲一讲功能

webSocket的是一种全双工的通信技术,通过websocket可以监控前端的页面变化,当然,这得与前端协调才行,我这边之前使用的是Vue作为前端,前端需要做一些对应的配置,具体前端内容就不说了,可以百度

这里说明一下后端,我是在springboot中来使用websocket的,使用起来很便捷

引入集成websocket的依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

添加配置类

1
2
3
4
5
6
7
@Configuration
public class WebSocketConfig{
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

声明服务端发送消息和接收消息的功能

1
2
3
4
5
6
public interface IWebSocketService {

void sendMessage(String message, List<String> toSids);

String getMessage(String msg);
}

实现类

简单解释一下这个实现类,存在注释的地方就不说明了,sendMessage其实就是服务端推送消息到另一个用户处,当然,因为是在线聊天,所以对方用户需要存在,如果不存在,你可以通过数据库将所发送的消息存储到数据库中,作为历史消息,在对方下一次上线后显示出来即可,服务端想获取消息,在onMessage这个方法,可以获取传入的数据,前端可以发json,后端使用json解析包解析一下就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
 
@Slf4j
@Service
@ServerEndpoint("/api/websocket/{sid}")
public class IWebSocketServiceImpl implements IWebSocketService {
@Autowired
RabbitTemplate rabbitTemplate;

//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static AtomicInteger onlineCount = new AtomicInteger(0);
//concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。
private static CopyOnWriteArraySet<IWebSocketServiceImpl> webSocketSet = new CopyOnWriteArraySet<>();

//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
//接收sid
private String sid = "";

@Override
public void sendMessage(String message, List<String> toSids) {
log.info("推送消息到客户端 " + toSids + ",推送内容:" + message);

for (IWebSocketServiceImpl item : webSocketSet) {
try {
if (CollectionUtils.isEmpty(toSids)) {
item.sendMessage(message);
} else if (toSids.contains(item.sid)) {
item.sendMessage(message);
}
} catch (IOException e) {
continue;
}
}
}

@Override
public String getMessage(String msg) {
return null;
}


/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
this.session = session;
webSocketSet.add(this); // 加入set中
this.sid = sid;
addOnlineCount(); // 在线数加1
try {
// sendMessage("conn_success");
log.info("有新客户端开始监听,sid=" + sid + ",当前在线人数为:" + getOnlineCount());
} catch (Exception e) {
log.error("websocket IO Exception");
}
}

/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this); // 从set中删除
subOnlineCount(); // 在线数减1
// 断开连接情况下,更新主板占用情况为释放
log.info("释放的sid=" + sid + "的客户端");
releaseResource();
}

@OnMessage
public void onMessage(String message, Session session) {
log.info("收到来自客户端 sid=" + sid + " 的信息:" + message);
//此处为MQ接收功能,如果不使用则可以屏蔽,如果有需要可使用
// if (rabbitTemplate == null) {
// ApplicationContext context = springUtils.getApplicationContext();
// rabbitTemplate = context.getBean(RabbitTemplate.class);
// }
// rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_TOPICS_INFORM, //RabbitmqConfig.ROUTINGKEY_RETURN, message);
// rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_TOPICS_INFORM, //RabbitmqConfig.ROUTINGKEY_RETURN, message);
// 群发消息
// List<String> sids = new ArrayList<>();
// for (WebSocketServer item : webSocketSet) {
// sids.add(item.sid);
// }
// try {
// sendMessage("客户端 " + this.sid + "发布消息:" + message, sids);
// } catch (IOException e) {
// e.printStackTrace();
// }
}

private void releaseResource() {
// 这里写释放资源和要处理的业务
log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
}

/**
* 发生错误回调
*/
@OnError
public void onError(Session session, Throwable error) {
log.error(session.getAsyncRemote() + "客户端发生错误");
error.printStackTrace();
}

/**
* 实现服务器主动推送消息到 指定客户端
*/
public void sendMessage(String message) throws IOException {
this.session.getAsyncRemote().sendText(message);
}

/**
* 获取当前在线人数
*
* @return
*/
public int getOnlineCount() {
return onlineCount.get();
}

/**
* 当前在线人数 +1
*
* @return
*/
public void addOnlineCount() {
onlineCount.getAndIncrement();
}

/**
* 当前在线人数 -1
*
* @return
*/
public void subOnlineCount() {
onlineCount.getAndDecrement();
}

/**
* 获取当前在线客户端对应的WebSocket对象
*
* @return
*/
public CopyOnWriteArraySet<IWebSocketServiceImpl> getWebSocketSet() {
return webSocketSet;
}

}

使用起来还是非常简单的,如果有小伙伴觉得哪里写的不太正确,可以指出,感谢支持!