SpringCloud集成WEBSOCKET实现即时通讯

SpringCloud集成WEBSOCKET实现即时通讯

在传统的web应用中,服务器只能在收到客户端的请求以后对该请求进行响应,这种机制对于信息变化不是特别频繁的应用尚能相安无事。但是在一些交互性比较强或者是数据变动频繁的项目中,某些业务需要服务器主动的向客户端推送一些信息,例如:在线游戏、在线的证券交易、在电商网站中订单状态发生变化,在网页中动态的提示用户、OA系统中下级单位向经理提交一次报销单,主管的主界面上会同时出现一条待办事项等等。要处理这种业务传统的请求-响应模式就显得力不从心,

这时一般的做法有两种。第一种是ajax轮询,也就是每隔N秒向服务器发送一次请求,服务器将最新的信息响应到客户端,这种方式的弊端主要有两点,由于轮询会不断的发送请求,所以弊端之一是浪费网络资源。同时轮询存在轮询间隔,所以弊端之二是无法保证数据的及时性。
第二种方式是服务器通知,通过TCP通讯协议使服务器和客户端保持持久的连接,通过服务器来向向客户端发送信息,客户端通过监听服务器的信息来达到一个通知的效果。WEBSOCKET就是基于这种思想所提出的一种技术,WEBSOCKET长连接是一种在单个tcp连接上进行全双工通信的协议,允许双向数据推送。一般微服务提供的restful API只是对前端请求做出响应。使用WEBSOCKET可以实现后端主动向前端推送消息。
WEBSOCKET单独使用比较简单,但是一旦在微服务架构中使用就要和SpringCloud进行整合。

  1. 在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

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值