SpringCloud集成WEBSOCKET实现即时通讯
在传统的web应用中,服务器只能在收到客户端的请求以后对该请求进行响应,这种机制对于信息变化不是特别频繁的应用尚能相安无事。但是在一些交互性比较强或者是数据变动频繁的项目中,某些业务需要服务器主动的向客户端推送一些信息,例如:在线游戏、在线的证券交易、在电商网站中订单状态发生变化,在网页中动态的提示用户、OA系统中下级单位向经理提交一次报销单,主管的主界面上会同时出现一条待办事项等等。要处理这种业务传统的请求-响应模式就显得力不从心,
这时一般的做法有两种。第一种是ajax轮询,也就是每隔N秒向服务器发送一次请求,服务器将最新的信息响应到客户端,这种方式的弊端主要有两点,由于轮询会不断的发送请求,所以弊端之一是浪费网络资源。同时轮询存在轮询间隔,所以弊端之二是无法保证数据的及时性。
第二种方式是服务器通知,通过TCP通讯协议使服务器和客户端保持持久的连接,通过服务器来向向客户端发送信息,客户端通过监听服务器的信息来达到一个通知的效果。WEBSOCKET就是基于这种思想所提出的一种技术,WEBSOCKET长连接是一种在单个tcp连接上进行全双工通信的协议,允许双向数据推送。一般微服务提供的restful API只是对前端请求做出响应。使用WEBSOCKET可以实现后端主动向前端推送消息。
WEBSOCKET单独使用比较简单,但是一旦在微服务架构中使用就要和SpringCloud进行整合。
- 在springcloud项目中新建socket模块
2.在socket模块中引入相关依赖,如下图:
3.修改application.properties配置文件
#当前服务的注册信息
#当前服务的端口
server.port=8082
#配置服务注册中心的域名
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
#配置服务名称
spring.application.name=socket-service
#注意:socket项目中没有具体的服务,只是作为websocket服务器,所以并不需要将该服务注册到
4.启动类注解>
5.创建WEBSOCKET处理器
WEBSCOKET处理器是核心组件,用于处理所有用户发送的消息,就拿在线拍卖来讲,一个用户叫价一次就需要将本次叫价信息发送到WEBSOCKET服务器,服务器收到该消息后,就将该消息通知到其他所有的拍卖参与者。
基于以上的分析,那么该处理器就必须要负责以下工作:
a.由于服务器要向所有用户推送,那么服务器必须有组织的保存所有用户的Socket对象
b.服务器必须能够接受用户的连接,并在连接时将用户Socket记录下来
c.服务器必须可以接受每一个用户发送的消息
d.服务器需要根据用户发送的消息向客户端进行推送
有了以上的认识,那么接下来我们来看看这个处理器的主体代码。
public class WebSocketHandler extends AbstractWebSocketHandler {
//定义全局变量用于保存所有用户的会话
/**
* webSocket连接创建后调用
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) {
}
/**
* 接收到消息会调用
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
}
/**
* 连接出错会调用
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
}
/**
* 连接关闭会调用
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
}
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* 封装方法发送消息到客户端
*/
public void sendMessage(){
}
}
先了解这个结构,我们一会再来完善这里面的代码。
6.创建WEBSOCKET拦截器>
在WEBSOCKET拦截器中主要用于将请求中的参数获取出来,并保存到WEBSOCKET会话信息中。
public class WebSocketInterceptor implements HandshakeInterceptor {
/**
* handler处理前调用,attributes属性最终在WebSocketSession里,可能通过webSocketSession.getAttributes().get(key值)获得
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
// 获取请求路径携带的参数
String user = serverHttpRequest.getServletRequest().getParameter("user");
attributes.put("user", user);
return true;
} else {
return false;
}
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
}
7.将WEBSOCKET处理器和拦截器加入到WEB组件中>
@Configuration @EnableWebSocket public class WebSocketAutoConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 注册websocket组件 添加处理器和拦截器
// websocket是websocket服务器的请求路径可以自己定义
registry.addHandler(new WebSocketHandler(), "/websocket")
// 指定自定义拦截器
.addInterceptors(new WebSocketInterceptor())
// 允许跨域
.setAllowedOrigins("*");
// 在某些低版本的浏览器中不支持websocket可以用sock-js替代
registry.addHandler(new WebSocketHandler(), "/sock-js")
.addInterceptors(new WebSocketInterceptor())
.setAllowedOrigins("*")
// 开启sockJs支持
.withSockJS();
} }
8.页面使用js和websocket服务器进行连接>
websocket连接:
// 创建Socket对象和服务器进行连接
var ws = new WebSocket("ws://localhost:8082/websocket?user=zhansgan");
// 连接成功监听 当客户端成功连接到服务器时该监听触发
ws.onopen = function() {
ws.send("测试发送");
console.log('open');
};
// 消息监听 当服务器向客户端发送信息时触发该监听
ws.onmessage = function (e) {
console.log('message', e.data);
};
// 当连接关闭时监听触发
ws.onclose = function() {
console.log('close');
};
sock-js连接
<script src="//cdn.jsdelivr.net/sockjs/1.0.0/sockjs.min.js"></script>
var sock = new SockJS('http://localhost:8080/sock-js?user=zhansgan');
sock.onopen = function() {
sock.send("测试发送");
console.log('open');
};
sock.onmessage = function(e) {
console.log('message', e.data);
};
sock.onclose = function() {
console.log('close');
};
无论你在学习上有任何问题,重庆蜗牛学院欢迎你前来咨询,联系QQ:296799112