java搭建websocket服务器,将后台收到的信息推送到前端,完善之前的图片弹窗报警功能
第一步首先搭建websocket服务器:创建WebSocketProcess的类,因为有多台机器人,可能有多个websocket对象,可以看到,将每个websocket都存储到ConcurrentHashMap里,并且提供了发送到指定客户端和发送到全部客户端的方法import lombok.extern.slf4j.Slf4j;import org.springframework.stereoty
第一步首先搭建websocket服务器:
创建WebSocketProcess的类,因为有多台机器人,可能有多个websocket对象,可以看到,将每个websocket都存储到ConcurrentHashMap里,并且提供了发送到指定客户端和发送到全部客户端的方法
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Component
@ServerEndpoint(value = "/testWebsocket/{id}")
public class WebSocketProcess {
/*
* 持有每个webSocket对象,以key-value存储到线程安全ConcurrentHashMap,
*/
private static ConcurrentHashMap<Long, WebSocketProcess> concurrentHashMap = new ConcurrentHashMap<>(12);
/*private static WebSocketProcess webSocketProcess;
@Autowired
public void setWebSocketProcess(WebSocketProcess webSocketProcess) {
WebSocketProcess.webSocketProcess = webSocketProcess;
}*/
/**
* 会话对象
**/
private Session session;
/*
* 客户端创建连接时触发
* */
@OnOpen
public void onOpen(Session session, @PathParam("id") long id) {
//每新建立一个连接,就把当前客户id为key,this为value存储到map中
this.session = session;
concurrentHashMap.put(id, this);
log.info("Open a websocket. id={}", id);
}
/**
* 客户端连接关闭时触发
**/
@OnClose
public void onClose(Session session, @PathParam("id") long id) {
//客户端连接关闭时,移除map中存储的键值对
concurrentHashMap.remove(id);
log.info("close a websocket, concurrentHashMap remove sessionId= {}", id);
}
/**
* 接收到客户端消息时触发
*/
@OnMessage
public void onMessage(String message, @PathParam("id") String id) {
log.info("receive a message from client id={},msg={}", id, message);
}
/**
* 连接发生异常时候触发
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("Error while websocket. ", error);
}
/**
* 发送消息到指定客户端
* @param id
* @param message
* */
public void sendMessage(long id, String message) throws Exception {
//根据id,从map中获取存储的webSocket对象
WebSocketProcess webSocketProcess = concurrentHashMap.get(id);
if (!ObjectUtils.isEmpty(webSocketProcess)) {
//当客户端是Open状态时,才能发送消息
if (webSocketProcess.session.isOpen()) {
webSocketProcess.session.getBasicRemote().sendText(message);
} else {
log.error("websocket session={} is closed ", id);
}
} else {
log.error("websocket session={} is not exit ", id);
}
}
/**
* 发送消息到所有客户端
*
* */
public void sendAllMessage(String msg) throws Exception {
log.info("online client count={}", concurrentHashMap.size());
Set<Map.Entry<Long, WebSocketProcess>> entries = concurrentHashMap.entrySet();
for (Map.Entry<Long, WebSocketProcess> entry : entries) {
Long cid = entry.getKey();
WebSocketProcess webSocketProcess = entry.getValue();
boolean sessionOpen = webSocketProcess.session.isOpen();
if (sessionOpen) {
// webSocketProcess.session.getBasicRemote().sendText(msg);
webSocketProcess.session.getBasicRemote().sendText(msg);
} else {
log.info("cid={} is closed,ignore send text", cid);
}
}
}
}
第二步,在MyResourceServerConfigurerAdapter里(加了@EnableResourceServer注解的)开启路径权限,系统采用的oauth2做的权限认证,应该给websocket开启权限
注:@EnableResourceServer是为OAuth2资源服务器提供方便的注解,启用Spring Security 过滤器,通过传入的OAuth2令牌对请求进行身份验证。用户应添加此注释并提供一个ResourceServerConfigurer的@Bean (例如,通过 ResourceServerConfigurerAdapter),指定资源的详细信息(URL路径和资源ID)
这个testWebsocket就是上面WebSocketProcess里面的websocket路径
如果没有开启,会报拒绝访问的错org.springframework.security.access.AccessDeniedException: Access is denied
第三步:添加websocket的配置类:
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();
}
}
服务端基本搭建完成,然后就是在接口里面调用WebSocketProcess的发送方法,因为@Autowired无法注入WebSocketProcess,我之前写过可以通过SpringContextUtil工具类拿到WebSocketProcess对象
点击这里可以查看相关代码
然后就是在合适的地方调用这个方法:
两个参数,一个是id,一个是需要推送的报警信息
前端:
var ws = new WebSocket('ws://127.0.0.1:8089/newRobot/testWebsocket/'+that.robotId+'');
//var ws = new WebSocket('ws://127.0.0.1:12340/chat');
//open event
ws.onopen = function() {
console.log("open websocket...");
};
//close event
ws.onclose = function() {
console.log("close websocket...");
};
// 响应onmessage事件:
ws.onmessage = function(msg) {
//这里可以处理接收到服务器的数据
console.log(msg);
let mes2="data:image/jpg;base64,"+msg.data;
that.openHTML(mes2);
};
function ws_send(){
// 给服务器发送一个数字
ws.send(document.getElementById('input_msg').value);
}
openhtml是弹出方法,用的是elementUI的功能:
openHTML(mes) {
this.$refs.audio.currentTime = 0; //从头开始播放提示音
this.$refs.audio.play(); //播放
this.$message({
type: "警报",
dangerouslyUseHTMLString: true,
message: '<img width="400" height="200" alt="star" src="'+mes+'"/>'
});
},
通过postman测试:
成功推送消息弹出图片
更多推荐
所有评论(0)