spring websocket 使用@SendToUser

原文链接:https://blog.csdn.net/yingxiake/article/details/51224569

之前我们利用@SendTo在方法上进行注解,方法的返回值会被messageconverter转化并推送到消息代理器中,由消息代理器广播到订阅路径去

@MessageMapping("bar") //@MessageMapping接收客户端消息
@SendTo("/topic/brocast") //@SendTo广播消息出去
public String handle1(String msg) {
return msg;
}

上面msg会被广播到”/topic/brocast”这个订阅路径中,只要客户端订阅了这条路径,不管是哪个用户,都会接收到消息

那么需求来了,如果我只是想简单的用websocket向服务器请求资源而已,然后服务器你就把资源给我就行了,别的用户就不用你广播推送了,简单点,就是我请求,你就推送给我。

spring websocket 可以使用@SendToUser做到这一点,在使用@SendToUser之前,我们需要明白以下几点:

1.spring webscoket通道的建立最开始还是源于http协议的第一次握手,握手成功之后,就打开了浏览器和服务器的webscoket通过,这时,httprequest中的登录授权信息即javax.security.Principal会被绑定到websocket的session中

2.spring webscoket能识别带”/user”的订阅路径并做出处理,例如,如果浏览器客户端,订阅了’/user/topic/greetings’这条路径,

stompClient.subscribe('/user/topic/greetings', function(data) {
//...
});

就会被spring websocket利用UserDestinationMessageHandler进行转化成”/topic/greetings-usererbgz2rq”,”usererbgz2rq”中,user是关键字,erbgz2rq是sessionid,这样子就把用户和订阅路径唯一的匹配起来了

3.spring webscoket在使用@SendToUser广播消息的时候,

@MessageMapping("handle")
@SendToUser("/topic/greetings")
public String handle(String msg) {
//...
return msg;
}
 
“/topic/greetings”会被UserDestinationMessageHandler转化成”/user/role1/topic/greetings”,role1是用户的登录帐号,这样子就把消息唯一的推送到请求者的订阅路径中去,这时候,如果一个帐号打开了多个浏览器窗口,也就是打开了多个websocket session通道,这时,spring webscoket默认会把消息推送到同一个帐号不同的session,你可以利用broadcast = false把避免推送到所有的session中

@MessageMapping("handle")
@SendToUser(value = "/topic/greetings",broadcast = false)
public String handle(String msg) {
//...
return name;
}

下面来做个demo,首先是服务器要配置登录验证权限,这里利用tomcat的basic安全验证,在web.xml里面配置

<security-constraint>
<web-resource-collection>
<web-resource-name>protect resources </web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>HEAD</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>role1</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<security-role>
<description>Role1</description>
<role-name>role1</role-name>
</security-role>  

role1是登录的角色名,其中验证信息可以在tomcat-users.xml里面配置

<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>

这里有俩个帐号,role1和both,角色都有role1,password都是tomcat,我们可以利用这俩个帐号在IE9和谷歌浏览器进行登录

然后服务器,我们分别使用@SendTo和@SendToUser进行广播推送和精准推送

首先我们注册下spring webscoket服务器

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketMessageBrokerConfig implements WebSocketMessageBrokerConfigurer {

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {

//portfolio-stomp就是websocket的端点,客户端需要注册这个端点进行链接,withSockJS允许客户端利用sockjs进行浏览器兼容性处理
registry.addEndpoint("/portfolio-stomp").withSockJS();

}

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic"); //设置服务器广播消息的基础路径
registry.setApplicationDestinationPrefixes("/app"); //设置客户端订阅消息的基础路径
registry.setPathMatcher(new AntPathMatcher(".")); //可以已“.”来分割路径,看看类级别的@messageMapping和方法级别的@messageMapping
}

@Override
public boolean configureMessageConverters(List<MessageConverter> messageConverters) {

return true;
}

@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
// TODO Auto-generated method stub
registry.addDecoratorFactory(new MyWebSocketHandlerDecoratorFactory());
}

@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new MyChannelInterceptor());
}

@Override
public void configureClientOutboundChannel(ChannelRegistration registration) {
// TODO Auto-generated method stub

}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
// TODO Auto-generated method stub

}

@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
// TODO Auto-generated method stub

}

}

然后写下服务的的接收和发送

@Controller
@RequestMapping("/webSocket")
@MessageMapping("foo")
public class WebSocketController {

/**
* 精准推送
* @param msg
* @param principal
* @return
*/
@MessageMapping("handle1") 
@SendToUser(value = "/topic/greetings1",broadcast = false)
public String handle1(String msg,Principal principal) {

return "精准推送,只推送到" + principal.getName();
}

/**
* 广播推送
* @param msg
* @param principal
* @return
*/
@MessageMapping("handle2") 
@SendTo("topic/greetings2")
public String handle2(String msg,Principal principal) {

return "广播推送,所有用户都收得到";

}

最后在浏览器客户端,我们利用sockjs和stomp.js链接并发送和订阅消息,其中在websocket.js代码就是这样子的

var socket = new SockJS('/whats/portfolio-stomp');
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {

stompClient.subscribe('/user/topic/greetings1', function(data) {
$("#ret").text(data.body);
});

stompClient.subscribe('/topic/greetings2', function(data) {
$("#ret").text(data.body);
});
});

/**
* 精准推送
*/
document.getElementById("ws1").onclick = function() {
stompClient.send("/app/foo.handle2",{},{
msg : "精准推送"
});
}

/**
* 广播推送
*/
document.getElementById("ws").onclick = function() {

stompClient.send("/app/foo.handle1",{},{
msg : "广播推送"
});

}

jsp页面其实就是这样子的

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html >
<html>
<head>
<meta charset="UTF-8">
<title>websocket</title>

</head>
<body>

<h1>hello websocket client !!</h1>

<button id = "ws">精准推送</button>
<button id = "ws1">广播推送</button>

<span id ="ret"></span>

<script type="text/javascript" src="${pageContext.request.contextPath}/content/uilib/websocket/sockjs-1.0.3.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/content/uilib/websocket/stomp.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/content/js/websocket/websocket.js"></script>
</body>
</html>

到这里就完成了功能了

精准推送

广播推送

spring websocket 使用@SendToUser的更多相关文章

  1. 【转】Spring websocket 使用

    http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html https://spr ...

  2. spring websocket源码分析续Handler的使用

    1. handler的定义 spring websocket支持的消息有以下几种: 对消息的处理就使用了Handler模式,抽象handler类AbstractWebSocketHandler.jav ...

  3. spring WebSocket详解

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

  4. spring+websocket整合

    java-websocket的搭建非常之容易,没用框架的童鞋可以在这里下载撸主亲自调教好的java-websocket程序: Apach Tomcat 8.0.3+MyEclipse+maven+JD ...

  5. web即时通讯2--基于Spring websocket达到web聊天室

    如本文所用,Spring4和websocket要构建web聊天室,根据框架SpringMVC+Spring+Hibernate的Maven项目,后台使用spring websocket进行消息转发和聊 ...

  6. spring+websocket综合(springMVC+spring+MyBatis这是SSM框架和websocket集成技术)

    java-websocket该建筑是easy.儿童无用的框架可以在这里下载主线和个人教学好java-websocket计划: Apach Tomcat 8.0.3+MyEclipse+maven+JD ...

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

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

  8. Spring Websocket实现简易在线聊天功能

    针对Spring Websocket的实现,我参照了其他博主的文章https://www.cnblogs.com/leechenxiang/p/5306372.html 下面直接给出实现: 一.引入相 ...

  9. Spring WebSocket踩坑指南

    Spring WebSocket踩坑指南 本次公司项目中需要在后台与安卓App间建立一个长连接,这里采用了Spring的WebSocket,协议为Stomp. 关于Stomp协议这里就不多介绍了,网上 ...

随机推荐

  1. Java进阶知识24 Spring的事务管理(事务回滚)

    1.事务控制概述   1.1.编程式事务控制         自己手动控制事务,就叫做编程式事务控制.         Jdbc代码: connection.setAutoCommit(false); ...

  2. [Luogu] 程序自动分析

    题面:https://www.luogu.org/problemnew/show/P1955 题解:https://www.zybuluo.com/wsndy-xx/note/1143858

  3. thinphp5.1 使用redis作为缓存

    tp自带的cache类支持redis方式.但是 只有string类型.显然不符合我们的日常的业务需求. so.通过查看源码,发现 handler方法.代码见下图 所以, 这样就能用hash list等 ...

  4. jumpserver官方手动安装

    测试环境 CPU: 64位双核处理器 内存: 4G DDR3 数据库:mysql 版本大于等于 5.6 mariadb 版本大于等于 5.5.6 环境 系统: CentOS 7 IP: 192.168 ...

  5. jenkins之docker安装

    此方法安装还存在两个问题1.构建node程序:2.时区问题(在docker run 设置环境变量是否能解决没有试过) 不建议用此方法安装,查看我的其他安装方式 搬运官网步骤,稍微改动. 1.安装doc ...

  6. linux java -jar

    常见命令1 nohup java -jar /xxx/xxx/xxx.jar >/dev/>& & 分析各个指令代表什么意思: >,重写文件,如果文件里面有内容会覆盖 ...

  7. Nginx中配置非英文域名

    前两天遇到个配置越南语的域名的情况.域名和ip解析完成后,直接ping域名也不通,还以为是解析问题.研究了半天,nginx配置非英文域名时,需要有其他操作. 非英文域名转换成punycode编码才可以 ...

  8. centos7 设置 tomcat 开机自启

    1.创建文件 # vi /etc/systemd/system/tomcat.service [Unit] Description=Tomcat8540 After=syslog.target net ...

  9. mac安装mysql数据库及配置环境变量

    mac安装mysql数据库及配置环境变量 mac安装mysql数据库及配置环境变量 原文文链接:https://blog.csdn.net/qq_36004521/article/details/80 ...

  10. XML解析思想

    获取文档中的数据: 反序列化[巧记:反读] 把内存中的数据存储到文档中: 序列化[巧记:序写] XML解析思想 DOM: 就是将文档中的数据全部加载到内存,在内存中形成DOM树,然后对数据进行增删改查 ...