stomp.js+spring+sockjs+activemq实现websocket长连接,使用java配置。

pom.xml(只列出除了spring基本依赖意外的依赖,spring-version为4.3.3.RELEASE):

<dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.1</version><scope>provided</scope> <!-- 注意,scope必须为provided,否则runtime会冲突,如果使用tomcat 8,还需要将TOMCAT_HOME/lib下的javax.websocket-api.jar一并删除 --></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-websocket</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jms</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.apache.xbean</groupId><artifactId>xbean-spring</artifactId><version>3.16</version></dependency><dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-core</artifactId><version>5.7.0</version></dependency><dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-pool</artifactId><version>5.12.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.8.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.8.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.8.1</version></dependency><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-net</artifactId><version>2.0.7.RELEASE</version></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.0.33.Final</version></dependency><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-core</artifactId><version>2.0.8.RELEASE</version></dependency>

StompConfig.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;/*** @EnableWebSocketMessageBroker包含@EnableWebSocket* @author TD**/
@Configuration
@EnableWebSocketMessageBroker
@PropertySource("classpath:activemq.properties")
public class StompConfig extends AbstractWebSocketMessageBrokerConfigurer{@Autowiredprivate Environment env;/*** 注册代理,暴露节点用于连接。*/@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {// TODO Auto-generated method stubregistry.addEndpoint("/stompEndPoint.do").withSockJS();}/*** 修改消息代理的配置,默认处理以/topic为前缀的消息* setApplicationDestinationPrefixes:配置请求的根路径,表示通过MessageMapping处理/td/*请求,不会发送到代理* enableStompBrokerRelay:配置代理,匹配路径的请求会进入代理:mq等*/@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {/*基于内存实现的stomp代理,单机适用registry.enableSimpleBroker("/queue","/topic");*///以/td为目的地的消息使用MessageMapping控制器处理,不走代理registry.setApplicationDestinationPrefixes("/td","/app");/*** 设置单独发送到某个user需要添加的前缀,用户订阅地址/user/topic/td1地址后会去掉/user,并加上用户名(需要springsecurity支持)等唯一标识组成新的目的地发送回去,* 对于这个url来说 加上后缀之后走代理。发送时需要制定用户名:convertAndSendToUser或者sendtouser注解.registry.setUserDestinationPrefix("/user")*//*基于mq实现stomp代理,适用于集群。* 以/topic和/queue开头的消息会发送到stomp代理中:mq等。* 每个mq适用的前缀不一样且有限制。activemq支持stomp的端口为61613*/registry.enableStompBrokerRelay("/topic","/queue").setRelayHost(env.getProperty("mq.brokenHost")).setRelayPort(Integer.parseInt(env.getProperty("mq.brokenPort"))).setSystemLogin(env.getProperty("mq.username")).setSystemPasscode(env.getProperty("mq.password")).setClientLogin(env.getProperty("mq.username")).setClientPasscode(env.getProperty("mq.password"));/** systemLogin:设置代理所需的密码* client:设置客户端连接代理所需的密码,默认为guest*/}}

JSP页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>stomp测试</title>
</head>
<body>
<button οnclick="test()">stomp发送(服务端返回信息走订阅2)</button>
<button οnclick="test2()">stomp订阅1(@subscribeMapping,不过代理)</button>
<button οnclick="test3()">stomp订阅2 :通过代理</button>
</body>
<script type="text/javascript" src="/spring15_socket/js/sockjs-0.3.4.min.js"></script>
<script type="text/javascript" src="/spring15_socket/js/stomp.js"></script>
<script type="text/javascript">
var url = 'http://localhost:8089/spring15_socket/stompEndPoint.do';
//创建sockjs链接
var sock = new SockJS(url);
//创建stomp客户端
var stomp = Stomp.over(sock);
var msg = JSON.stringify({'name':'td','age':13});
stomp.connect({},function(frame){console.log('connecting...'+frame)stomp.send('/app/stomp1.do',{},msg);
})function test(){stomp.send('/app/stomp1.do',{},msg);
}function test2(){stomp.subscribe('/app/stomp2.do',function(msg){console.log("subscribemapping:"+JSON.parse(msg.body).content);})}function test3(){stomp.subscribe('/topic/hello',function(msg){console.log("topicHello:"+JSON.parse(msg.body).content);})}</script>
</html>

  

控制器:

package spring15_socket.controller;import java.sql.SQLException;import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import spring15_socket.bean.User;@Controller
public class TestController {@RequestMapping(value="/sockjs.do")public String test0(Model model){return "sockjs";}    @RequestMapping(value="/stompjs.do")public String test1(Model model){return "stomp";}    /*** 表示该方法处理客户端发来的/td/stomp1.do或者/app/stomp1.do。* sendTo:重新指定发送的位置,默认原路返回(url会加上/topic前缀)* 需走代理*/@MessageMapping("/stomp1.do")@SendTo("/topic/hello")public User handleStomp(User user) {System.out.println("stomp接收到客户端的请求:"+user);user.setName("messagemapping返回user");return user;}/*** 用于处理messagemapping抛出的异常,类比exceptionhandler* @return*/@MessageExceptionHandler({Exception.class,SQLException.class})@SendTo("/topic/errorTopic")public User errorHandler(Throwable t) {System.out.println("异常统一处理");User user = new User();user.setName("异常统一处理:"+t.getMessage());;return user;}/*** 触发方式和messagemapping一致。* sendTo:重新指定发送的位置,默认原路返回(url会加上/topic前缀)* 使用subscribemapping不走代理*/@SubscribeMapping("/stomp2.do")@SendTo("/topic/hello")public User subsTest() {User user2 = new User();user2.setName("订阅name");user2.setPhone("subscribePhone");return user2;}}

进入activemq的控制台,点击connection可以看到stomp连接:(这里连接了两个客户端,可以点击超链接查看连接状态)

查看启动日志可以发现:表明启动成功

进入页面点击第一个按钮,会触发send:

同时控制台可以看到:

单独点击第二个按钮不会有返回消息,点击第三个按钮之后会订阅/topic/hello,此时点击第一个触发send。在服务端执行完毕后通过sendto注解发布到/topic/hello,此时浏览器控制台会输出该频道发布的内容

注意点:

1:基于activemq作为代理,连接的端口号为61613。

2:setSystemLogin表示设置服务器连接代理(activemq)的账号密码,setClientLogin表示连接过来的客户端连接代理所需要的账号密码。

转载于:https://www.cnblogs.com/ForsakenCoder/p/10121723.html

Spring+Stomp+ActiveMq实现websocket长连接相关推荐

  1. Android websocket长连接+点对点订阅

    项目中使用到了websocket长连接+点对点订阅,博客记录下. 长连接通常使用的是名称叫做STOMP的协议,具体跟服务器端的开发人员确认即可. 直接贴干货: module build.gradle添 ...

  2. 实现单台测试机6万websocket长连接

    本文由作者郑银燕授权网易云社区发布. 本文是我在测试过程中的记录,实现了单台测试机发起最大的websocket长连接数.在一台测试机上,连接到一个远程服务时的本地端口是有限的.根据TCP/IP协议,由 ...

  3. java nio socket长连接_netty学习实战—实现websocket长连接和socket之间进程通信

    netty学习-实现websocket长连接和socket之间通信 最近正在学习netty,跟着教程写了一个基于WebSocket的网页聊天室,对netty有了一定的了解,现在正好项目使用到长连接,选 ...

  4. websocket 获取连接id_Swoole学习笔记七:搭建WebSocket长连接 之 使用 USER_ID 作为身份凭证...

    Swoole学习笔记七:搭建WebSocket长连接 之 使用 USER_ID 作为身份凭证 2年前 阅读 3678 评论 0 喜欢 0 ### 0.前言 前面基本的WebSocket操作,我们基本都 ...

  5. java与微信小程序通讯_java与微信小程序实现websocket长连接

    本文实例为大家分享了java与微信小程序实现websocket长连接的具体代码,供大家参考,具体内容如下 背景: 需要在小程序实现地图固定坐标下实时查看消息 java环境 :tomcat7 jdk1. ...

  6. WebSocket长连接因为网络波动而导致客户端的“假离线”---问题发现、分析到解决

    文章目录 简介 问题的现象.场景和解决方案 基本的部署架构 问题是什么呢? 假离线到底是怎么来的? 验证猜想 解决问题 如何发现问题的呢? 客户端离线预警 奇怪的现象来了 该怎么去发现呢 到底是谁改的 ...

  7. 微信是与服务器长连接,java与微信小程序实现websocket长连接.pdf

    java与与微微信信小小程程序序实实现现websocket长长连连接接 本文实例为大家分享了j ava与微信小程序实现websocket长连接的具体代码,供大家参考,具体内容 下 背背景景:: 需要在 ...

  8. WebSocket长连接

    WebSocket长连接 1.概述 1.1 定义 1.2 原理 2.Django中配置WebSocket 2.1安装第三方法包 pip install channels 2.2 Django 中的配置 ...

  9. 安卓中socket长连接和websocket长连接的实现

    现在一款成熟的app一般都会具备长连接推送功能,那么我们要想项目具备长连接的功能现在又两种选择的方案,一种基于原生tcp协议的socket长连接,另外一种基于ws协议的websocket的长连接,今天 ...

  10. Android 实现WebSocket长连接

    最近项目中引入了实时接收服务器数据的功能,考量后通过WebSocket长链接来实现. 接下来了解一下webSocket 的特点: 1.建立在 TCP 协议之上,服务器端的实现比较容易. 2.与 HTT ...

最新文章

  1. 使用isql连接Sybase ASE数据库的常见错误及处理方式
  2. The Text Splitting (将字符串分成若干份,每份长度为p或q)
  3. Android自定义控制(五)仿新浪微博的下拉刷新
  4. openfeign 负载均衡_再谈openfeign,聊聊它的源代码
  5. sscanf的高级用法
  6. c++ 加载库错误问题解决
  7. 电脑开机时光驱咔咔响_电脑机箱噪音大?看懂这篇内容,让你四步就能解决问题...
  8. php上证指数抽奖代码,[高手指点] 美团网的抽奖是什么原理?
  9. php爬虫框架phpfetcher,TrackRay:打造一款自己的渗透测试框架
  10. Python包:包的概念、2种建立包方式、包的使用(代码 + 图文)
  11. excel画正态分布与T分布
  12. 将/etc/passwd文件的内容写入/tmp/passwd文件中
  13. 上传文件时,服务器报错:IOFileUploadException: Processing of multipart/form-data request failed. 设备上没有空间
  14. linux中c语言结构体详解,Linux C语言结构体-学习笔记
  15. 解决华硕飞行堡垒8开机蓝屏问题
  16. 快速有效增加网站外链的技巧
  17. python四种抽样方法的使用:随机抽样、聚类抽样、系统抽样、分层抽样
  18. PHPExcel从Excel读取导入数据
  19. excel 数据的有效性检查
  20. 【前端系列教程之HTML5】01_HTML概述

热门文章

  1. Ubuntu 安装hadoop 伪分布式
  2. 程序关闭是总是出异常解决方法
  3. Java中的断言assert的用法
  4. vue el-date-picker 直接赋值不生效、数据绑定无效
  5. struts2 中 constant标签
  6. Python 函数参数传递的困惑
  7. golang中base64编码_Rust 中的字符集编码 Rust 实践指南
  8. 小明刚刚看完电影《第39级台阶》离开电影院的时候,他数了一下礼堂前的台阶,刚好是39级 站在台阶前,他突然又想到了一个问题 如果我每步只能迈上一个或者两个台阶,先迈左脚,然后左右交替,也就是说一共
  9. 使用spring ioc基于纯xml配置模拟crud
  10. mac php编译freetype,mac OS X自带PHP环境,没有freetype的解决办法