Spring+Stomp+ActiveMq实现websocket长连接
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长连接相关推荐
- Android websocket长连接+点对点订阅
项目中使用到了websocket长连接+点对点订阅,博客记录下. 长连接通常使用的是名称叫做STOMP的协议,具体跟服务器端的开发人员确认即可. 直接贴干货: module build.gradle添 ...
- 实现单台测试机6万websocket长连接
本文由作者郑银燕授权网易云社区发布. 本文是我在测试过程中的记录,实现了单台测试机发起最大的websocket长连接数.在一台测试机上,连接到一个远程服务时的本地端口是有限的.根据TCP/IP协议,由 ...
- java nio socket长连接_netty学习实战—实现websocket长连接和socket之间进程通信
netty学习-实现websocket长连接和socket之间通信 最近正在学习netty,跟着教程写了一个基于WebSocket的网页聊天室,对netty有了一定的了解,现在正好项目使用到长连接,选 ...
- websocket 获取连接id_Swoole学习笔记七:搭建WebSocket长连接 之 使用 USER_ID 作为身份凭证...
Swoole学习笔记七:搭建WebSocket长连接 之 使用 USER_ID 作为身份凭证 2年前 阅读 3678 评论 0 喜欢 0 ### 0.前言 前面基本的WebSocket操作,我们基本都 ...
- java与微信小程序通讯_java与微信小程序实现websocket长连接
本文实例为大家分享了java与微信小程序实现websocket长连接的具体代码,供大家参考,具体内容如下 背景: 需要在小程序实现地图固定坐标下实时查看消息 java环境 :tomcat7 jdk1. ...
- WebSocket长连接因为网络波动而导致客户端的“假离线”---问题发现、分析到解决
文章目录 简介 问题的现象.场景和解决方案 基本的部署架构 问题是什么呢? 假离线到底是怎么来的? 验证猜想 解决问题 如何发现问题的呢? 客户端离线预警 奇怪的现象来了 该怎么去发现呢 到底是谁改的 ...
- 微信是与服务器长连接,java与微信小程序实现websocket长连接.pdf
java与与微微信信小小程程序序实实现现websocket长长连连接接 本文实例为大家分享了j ava与微信小程序实现websocket长连接的具体代码,供大家参考,具体内容 下 背背景景:: 需要在 ...
- WebSocket长连接
WebSocket长连接 1.概述 1.1 定义 1.2 原理 2.Django中配置WebSocket 2.1安装第三方法包 pip install channels 2.2 Django 中的配置 ...
- 安卓中socket长连接和websocket长连接的实现
现在一款成熟的app一般都会具备长连接推送功能,那么我们要想项目具备长连接的功能现在又两种选择的方案,一种基于原生tcp协议的socket长连接,另外一种基于ws协议的websocket的长连接,今天 ...
- Android 实现WebSocket长连接
最近项目中引入了实时接收服务器数据的功能,考量后通过WebSocket长链接来实现. 接下来了解一下webSocket 的特点: 1.建立在 TCP 协议之上,服务器端的实现比较容易. 2.与 HTT ...
最新文章
- 使用isql连接Sybase ASE数据库的常见错误及处理方式
- The Text Splitting (将字符串分成若干份,每份长度为p或q)
- Android自定义控制(五)仿新浪微博的下拉刷新
- openfeign 负载均衡_再谈openfeign,聊聊它的源代码
- sscanf的高级用法
- c++ 加载库错误问题解决
- 电脑开机时光驱咔咔响_电脑机箱噪音大?看懂这篇内容,让你四步就能解决问题...
- php上证指数抽奖代码,[高手指点] 美团网的抽奖是什么原理?
- php爬虫框架phpfetcher,TrackRay:打造一款自己的渗透测试框架
- Python包:包的概念、2种建立包方式、包的使用(代码 + 图文)
- excel画正态分布与T分布
- 将/etc/passwd文件的内容写入/tmp/passwd文件中
- 上传文件时,服务器报错:IOFileUploadException: Processing of multipart/form-data request failed. 设备上没有空间
- linux中c语言结构体详解,Linux C语言结构体-学习笔记
- 解决华硕飞行堡垒8开机蓝屏问题
- 快速有效增加网站外链的技巧
- python四种抽样方法的使用:随机抽样、聚类抽样、系统抽样、分层抽样
- PHPExcel从Excel读取导入数据
- excel 数据的有效性检查
- 【前端系列教程之HTML5】01_HTML概述
热门文章
- Ubuntu 安装hadoop 伪分布式
- 程序关闭是总是出异常解决方法
- Java中的断言assert的用法
- vue el-date-picker 直接赋值不生效、数据绑定无效
- struts2 中 constant标签
- Python 函数参数传递的困惑
- golang中base64编码_Rust 中的字符集编码 Rust 实践指南
- 小明刚刚看完电影《第39级台阶》离开电影院的时候,他数了一下礼堂前的台阶,刚好是39级 站在台阶前,他突然又想到了一个问题 如果我每步只能迈上一个或者两个台阶,先迈左脚,然后左右交替,也就是说一共
- 使用spring ioc基于纯xml配置模拟crud
- mac php编译freetype,mac OS X自带PHP环境,没有freetype的解决办法