需求:在新增报警事件和处理告警事件同时将消息进行推送
webSocket有什么用?
系统中的实时消息通讯是很常见的。之前的解释方式是使用轮询技术(具体我不懂,没使用过),但轮询技术的缺点就是需要反复发送请求。webSocket的出现机制就是可以不需要反复发送请求,又能做到实时通信。
webSocket怎么用?
知道了webSocket的作用,那它是怎么在代码中实现的。代码例子如下:
代码说明:必要注解
@ServerEndpoint:该注释表示将WebSocket服务器运行在ws://[Server端IIP]:[Server端端口]/websocket/echo
注意:使用该注解的类必须要有一个无参构造方法
@OnOpen :连接时调用
@OnClose:断开时调用
@OnError:错误时调用
@OnMessage:客户端发送消息时调用
自定义方法:
sendAll(String message):消息群发送
sendInfo(String userId, String message ):消息指定发送
@ServerEndpoint("/websocket/{userId}")
@Component
public class MyWebsocketServer {
public MyWebsocketServer() {
log.info("启动");
}
/**
* The Log.
*/
static Log log=LogFactory.get(MyWebsocketServer.class);
/**
* 存放所有在线的客户端
*/
private static Map<String, Session> clients = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId) {
log.info("有新的客户端连接了: {}", userId);
//将新用户存入在线的组
clients.put(userId, session);
log.info("当前在线人数: {}", clients.size());
}
/**
* 客户端关闭
* @param session session
*/
@OnClose
public void onClose(Session session, @PathParam(value = "userId") String userId) {
log.info("有用户断开了, id为:{}", userId);
//将掉线的用户移除在线的组里
clients.remove(userId);
log.info("当前在线人数: {}", clients.size());
}
/**
* 发生错误
* @param throwable e
*/
@OnError
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
/**
* 收到客户端发来消息
* @param message 消息对象
*/
@OnMessage
public void onMessage(String message) {
log.info("服务端收到客户端发来的消息: {}", message);
sendAll(message);
}
/**
* 群发消息
* @param message 消息内容
*/
public static void sendAll(String message) {
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
sessionEntry.getValue().getAsyncRemote().sendText(message);
log.info("发送消息: {}", message);
}
}
/**
* 发消息
* @param message 消息内容
*/
public static void sendInfo(String userId, String message ) {
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
if(sessionEntry.getKey().equals(userId)){
sessionEntry.getValue().getAsyncRemote().sendText(message);
log.info("发送消息: {}", message);
}
}
}
业务代码调用
public Result processingAlarmEventPush(String ids) {
pushAlarm();
return ResultUtil.success();
}
private void pushAlarm(){
//重新查询所有告警并推送
Map<String, List<AlarmVO>> allAlarm = getAllAlarm();
if(allAlarm == null){
MyWebsocketServer.sendAll("");
}else {
MyWebsocketServer.sendAll(allAlarm.keySet().toString());
}
}
webSocket怎么测试?
测试网址:【http://www.websocket-test.com/】
填入之前设置好的地址:ws://localhost:8075/camp/websocket/aa
点击连接时候会触发OnOpen函数,控制台输出:
2020-08-07 15:01:55.020 INFO 10208 --- [nio-8075-exec-1] c.s.s.c.websocket.MyWebsocketServer : 启动
2020-08-07 15:01:55.024 INFO 10208 --- [nio-8075-exec-1] c.s.s.c.websocket.MyWebsocketServer : 有新的客户端连接了: aa
2020-08-07 15:01:55.024 INFO 10208 --- [nio-8075-exec-1] c.s.s.c.websocket.MyWebsocketServer : 当前在线人数: 1
点击断开时会触发OnClose函数,控制台输出:
2020-08-07 15:03:16.339 INFO 10208 --- [nio-8075-exec-2] c.s.s.c.websocket.MyWebsocketServer : 有用户断开了, id为:aa
2020-08-07 15:03:16.340 INFO 10208 --- [nio-8075-exec-2] c.s.s.c.websocket.MyWebsocketServer : 当前在线人数: 0
业务逻辑发送数据,控制台输出:
2020-08-07 15:05:02.163 INFO 10208 --- [nio-8075-exec-5] c.s.smartweb.security.filter.SsoFilter : .............. /camp/alarm/insertPush
2020-08-07 15:05:02.168 INFO 10208 --- [nio-8075-exec-5] c.s.s.c.websocket.MyWebsocketServer : 发送消息: [testname3, testname2, testname1]
测试网页输出:
(这里很关键,网页有输出就意味着服务端已经主动向客户端发送信息,这就和轮询方式的最大区别)
服务器 15:5:2
[testname3, testname2, testname1]
到此为止,整个流程结束。
分享一篇网上的资料写的很有意思(https://www.cnblogs.com/nnngu/p/9347635.html)
代码优化体会:
场景:需要调用二维接口返回的结果。循环判断结果是否有标志位
原先的做法:在循坏中,重复调用二维接口。
优化:将二维接口提取到循环外,只调用一次就可以。