spring对于基于stomp协议的websocket通信,其官网上面有一个guide,但是根据guide你只能写出来广播方式的通信,不能实现一对一的通信,这篇文章在这里把广播和一对一一起整理一下给大家。

服务端:

一,依赖,spring-websocket和spring-messaging,这里给出maven方式:

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-websocket</artifactId>
  4. <version>${spring-core.version}</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework</groupId>
  8. <artifactId>spring-messaging</artifactId>
  9. <version>${spring-core.version}</version>
  10. </dependency>

二,服务端代码:

服务端的初始化,只需要两个类:WebsocketConfig和WebSocketController

  1. import org.springframework.context.annotation.Configuration;
  2. import org.springframework.messaging.simp.config.MessageBrokerRegistry;
  3. import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
  4. import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
  5. import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
  6. @Configuration
  7. @EnableWebSocketMessageBroker
  8. public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
  9. @Override
  10. public void configureMessageBroker(MessageBrokerRegistry config) {
  11. config.enableSimpleBroker("/topic","/user");
  12. config.setApplicationDestinationPrefixes("/app");
  13. config.setUserDestinationPrefix("/user/");
  14. }
  15. @Override
  16. public void registerStompEndpoints(StompEndpointRegistry registry) {
  17. registry.addEndpoint("/webServer").withSockJS();
  18. }
  19. }

这个类表示启用websocket消息处理,以及收发消息的域

config.enableSimpleBroker("/topic","/user");这句表示在topic和user这两个域上可以向客户端发消息;config.setUserDestinationPrefix("/user/");这句表示给指定用户发送(一对一)的主题前缀是“/user/”;  config.setApplicationDestinationPrefixes("/app"); 这句表示客户端向服务端发送时的主题上面需要加"/app"作为前缀;registry.addEndpoint("/webServer").withSockJS();这个和客户端创建连接时的url有关,后面在客户端的代码中可以看到。

下面是一个spring风格的controller,用于接收客户端的消息及响应客户端:

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.messaging.handler.annotation.MessageMapping;
  3. import org.springframework.messaging.handler.annotation.SendTo;
  4. import org.springframework.messaging.simp.SimpMessagingTemplate;
  5. import org.springframework.messaging.simp.annotation.SendToUser;
  6. import org.springframework.stereotype.Controller;
  7. @Controller
  8. public class WebSocketController {
  9. public SimpMessagingTemplate template;
  10. @Autowired
  11. public WebSocketController(SimpMessagingTemplate template) {
  12. this.template = template;
  13. }
  14. @MessageMapping("/hello")
  15. @SendTo("/topic/hello")
  16. public Greeting greeting(Greeting message) throws Exception {
  17. return message;
  18. }
  19. @MessageMapping("/message")
  20. @SendToUser("/message")
  21. public UserMessage userMessage(UserMessage userMessage) throws Exception {
  22. return userMessage;
  23. }
  24. }

这个类里面织入SimpMessagingTemplate对象,后面动态发送消息时,需要用到这个对象。

第一个方法,表示服务端可以接收客户端通过主题“/app/hello”发送过来的消息,客户端需要在主题"/topic/hello"上监听并接收服务端发回的消息

第二个方法道理相同,只是注意这里用的是@SendToUser,这就是发送给单一客户端的标志。本例中,客户端接收一对一消息的主题应该是“/user/” + 用户Id + “/message” ,这里的用户id可以是一个普通的字符串,只要每个用户端都使用自己的id并且服务端知道每个用户的id就行。

这里的Greeting和UserMessage是一个普通的实现了序列化的Java bean

就这样,那么,在程序中的其他地方要动态发送消息,就是下面这两句代码:

  1. webSocketController.template.convertAndSend("/topic/hello",greeting) //广播
  2. webSocketController.template.convertAndSendToUser(userId, "/message",userMessage) //一对一发送,发送特定的客户端

客户端:

js客户端需要导入两个js组件:sockjs-0.3.4.js,stomp.js

  1. var url = 'http://localhost:8080/appRoot/webServer'
  2. var socket = new SockJS(url, undefined, {protocols_whitelist: ['websocket']});
  3. var stompClient = Stomp.over(socket);
  4. stompClient.connect({}, function(frame) {
  5. stompClient.subscribe('/topic/hello', function(message){
  6. var json = JSON.parse(message.body);
  7. });
  8. stompClient.subscribe('/user/' + userId + '/message', function(message){
  9. var messageEntity = JSON.parse(message.body);
  10. });
  11. });

第一个subscribe,是接收广播消息,第二个是接收一对一消息,其主题是'/user/' + userId+ '/message' , 不同客户端具有不同的userId

看到这里,你会发现,这里所谓的一对一,只是业务层面的一对一,也就是,需要不同客户端具有不同的userId才能实现,如果两个客户端使用相同的userid, 那么服务端给这个userId发送消息时,这两个客户端都会收到。要真正实现websocket技术层面的一对一发送,那就要使用websocket的session了。关于session方式,我这里上传一个demo,有兴趣可以下载:http://download.csdn.net/detail/valenon/8725195

spring websocket + stomp 实现广播通信和一对一通信<转>的更多相关文章

  1. spring boot websocket stomp 实现广播通信和一对一通信聊天

    一.前言 玩.net的时候,在asp.net下有一个叫 SignalR 的框架,可以在ASP .NET的Web项目中实现实时通信.刚接触java寻找相关替代品,发现 java 体系中有一套基于stom ...

  2. Spring 学习——基于Spring WebSocket 和STOMP实现简单的聊天功能

    本篇主要讲解如何使用Spring websocket 和STOMP搭建一个简单的聊天功能项目,里面使用到的技术,如websocket和STOMP等会简单介绍,不会太深,如果对相关介绍不是很了解的,请自 ...

  3. spring websocket 和socketjs实现单聊群聊,广播的消息推送详解

    spring websocket 和socketjs实现单聊群聊,广播的消息推送详解 WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随 ...

  4. spring+rabbitmq+stomp搭建websocket消息推送(非spring boot方式)

    前言: 两年前做过spring+activemq+stomp的ws推送,那个做起来很简单,但现在公司用的mq中间件是rabbitmq,因此需要通过rabbitmq去做ws通信.仔细搜了搜百度/谷歌,网 ...

  5. Spring Boot 中使用 WebSocket 实现一对多聊天及一对一聊天

    为什么需要WebSocket? 我们已经有了http协议,为什么还需要另外一个协议?有什么好处? 比如我想得到价格变化,只能是客户端想服务端发起请求,服务器返回结果,HTTP协议做不到服务器主动向客户 ...

  6. java WebSocket的实现以及Spring WebSocket

    开始学习WebSocket,准备用它来实现一个在页面实时输出log4j的日志以及控制台的日志. 首先知道一些基础信息: java7 开始支持WebSocket,并且只是做了定义,并未实现 tomcat ...

  7. spring WebSocket详解

    场景 websocket是Html5新增加特性之一,目的是浏览器与服务端建立全双工的通信方式,解决http请求-响应带来过多的资源消耗,同时对特殊场景应用提供了全新的实现方式,比如聊天.股票交易.游戏 ...

  8. Spring WebSocket教程(一)

    学习背景 很久以前就知道WebSocket,但那时不论是浏览器还是开发技术对它的支持都还很少.但是,Spring4突然发布,让我眼前一亮,Spring4直接支持WebSocket. 对于Spring我 ...

  9. spring websocket集群问题的简单记录

    目录 前言 解决方案 代码示例 前言 最近公司里遇到一个问题,在集群中一些websocket的消息丢失了. 产生问题的原理很简单,发送消息的服务和接收者连接的服务不是同一个服务. 解决方案 用中间件( ...

随机推荐

  1. 好的 IOS 学习网站

    http://www.objc.io/contributors.html codeproject. http://www.codeproject.com/KB/iPhone/

  2. Android百日程序 开篇章:Intent打开网页

    学习一下人家100日写100个网页的做法,我也用100日写100个完整的Android程序. 这些程序的最基本要求: 1 完整性-每一个程序都必须是独立可执行的 2 不反复性-所用的重点知识点都不一样 ...

  3. [fixed] 解决 slf4j + log4j eclipse 可以打印日志,而在云服务器上不能打印

    今天发现服务上没有打印任何日志,而log4j已经设置为了INFO 很奇怪,在eclipse中是可以打印的,也能输出到单独的日志中 后来发现原来是冲突了 把log4j注释掉即可 保留slf4j即可

  4. UIScrollView中图片放大后不居中,或居中后移动有偏差解决办法

    转自:http://blog.sina.com.cn/s/blog_6ae8b50d0100yret.html 问题的描述如下:要显示一张图片,也只需要显示一张图片,该图片可能很大,也可能很小,但是要 ...

  5. 【小白的CFD之旅】23 串行与并行

    夏日的早晨,被酷热和蚊子骚扰了一夜的小白刚进入梦乡就被老蓝的电话给惊醒了. “8点开会!”老蓝说话永远那么简短有力,根本不给人请假的时间就挂了电话. 小白一看时间,都7点半了,得,这懒觉睡不成了.小白 ...

  6. CCFollow

    //    CCFollow //    作用:创建一个跟随动作 //    参数1:跟随的目标对象 //    跟随范围,离开范围就不再跟随 //创建一个参照物spT //    CCSprite ...

  7. LL&LR parser

    https://stackoverflow.com/questions/5975741/what-is-the-difference-between-ll-and-lr-parsing https:/ ...

  8. Linux设备驱动开发详解

    Linux设备驱动开发详解 http://download.csdn.net/detail/wuyouzi067/9581380

  9. linux命令(35):diff命令

    diff 命令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方.diff在命令行中打印每一个行的改动.最新版本的diff还支持二进制文件.diff程序的 ...

  10. Android使用binder访问service的方式(一)

    binder机制是贯穿整个android系统的进程间访问机制,经常被用来访问service,我们结合代码看一下binder在访问service的情形下是怎么具体使用的. service 你可以理解成没 ...