博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Websocket/STOMP 和SpringSession整合 初步
阅读量:5735 次
发布时间:2019-06-18

本文共 5332 字,大约阅读时间需要 17 分钟。

共享Session

WebsocketSTOMPConfig:

@Configuration@EnableWebSocketMessageBroker@ConditionalOnWebApplicationpublic class WebsocketSTOMPConfig extends AbstractSessionWebSocketMessageBrokerConfigurer
{ /** * AbstractSessionWebSocketMessageBrokerConfigurer实现了在handshake时获取httpsession,并且每次websocket消息发生时也刷新了httpsession的时间。同时在websocket session中加入了SPRING.SESSION.ID字段。 */ @Override protected void configureStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws") // 在握手时就获得user,判断是否登录。 .addInterceptors(new SessionAuthHandshakeInterceptor()) .setHandshakeHandler(new DefaultHandshakeHandler(){ @Override protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map
attributes) { return new MyPrincipal((User) attributes.get("user")); } }) .setAllowedOrigins("http://127.0.0.1:8081"); } @Override public void configureClientInboundChannel(ChannelRegistration registration) { registration.setInterceptors(new ChannelInterceptorAdapter() { @Override public Message
preSend(Message
message, MessageChannel channel) { System.out.println("recv : "+message); StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); User user = (User)accessor.getSessionAttributes().get("user"); return super.preSend(message, channel); } }); } @Override public void configureClientOutboundChannel(ChannelRegistration registration) { registration.setInterceptors(new ChannelInterceptorAdapter() { @Override public Message
preSend(Message
message, MessageChannel channel) { System.out.println("send: "+message); return super.preSend(message, channel); } }); } @Override public void configureMessageBroker(MessageBrokerRegistry config) { // 这是配置到 @MessageMapping Controller config.setApplicationDestinationPrefixes("/app"); // 直接到broker message handler config.enableSimpleBroker("/topic", "/queue"); } class MyPrincipal implements Principal{ private User user; public MyPrincipal(User user) { this.user = user; } @Override public String getName() { return String.valueOf(user.getId()); } }}

SessionAuthHandshakeInterceptor: 这是自定义的握手拦截,获取已登录的User

public class SessionAuthHandshakeInterceptor implements HandshakeInterceptor {    private Logger logger = LoggerFactory.getLogger(this.getClass());    @Override    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map
attributes) throws Exception { HttpSession session = getSession(request); if(session==null || session.getAttribute("user")==null){ logger.error("websocket权限拒绝"); return false; } attributes.put("user",session.getAttribute("user")); return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { } // 参考 HttpSessionHandshakeInterceptor private HttpSession getSession(ServerHttpRequest request) { if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request; return serverRequest.getServletRequest().getSession(false); } return null; }}

然后在configureClientInboundChannel中可以通过以下获得User:

StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);User user = (User)accessor.getSessionAttributes().get("user");

还有一种获得User的方式,可以在WebsocketSTOMPConfig中注入SessionRepository来获得springsession:

StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);sessionRepository.getSession((String) accessor.getSessionAttributes().get("SPRING.SESSION.ID"))

设置Principal

Spring提供了"/user"前缀专门用于精准推送单个用户。

client 订阅 "/user/queue/msg",spring通过UserDestinationMessageHandler重新设置client的订阅地址,使与"/user/{username}/queue/msg"绑定。

前端代码:

var url = "ws://"+window.location.host+"/project/ws";var client = Stomp.client(url);client.connect({}, function (message) {    const subscription = client.subscribe("/user/queue/msg", function () {});    client.send("/app/test2", {}, "Hello, STOMP");},function (err) {    alert(err);});

Controller:

@Controllerpublic class MsgController {    private Logger logger = LoggerFactory.getLogger(this.getClass());    @Autowired    private SimpMessagingTemplate simpMessagingTemplate;    @MessageMapping("/test2")    public void test(String str, Principal principal){     simpMessagingTemplate.convertAndSendToUser(principal.getName(),"/queue/msg","haha2");    }}

在WebsocketSTOMPConfig中的configureStompEndpoints配置:

registry.addEndpoint("/ws")   .addInterceptors(new SessionAuthHandshakeInterceptor())   .setHandshakeHandler(new DefaultHandshakeHandler(){       @Override       protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map
attributes) { return new MyPrincipal((User) attributes.get("user")); } });

转载地址:http://kwwzx.baihongyu.com/

你可能感兴趣的文章
【Linux基本操作】系列02:vim的常用操作
查看>>
Android自适应不同分辨率或不同屏幕大小
查看>>
hdu4198(优先队列+bfs)
查看>>
另辟蹊径——使用 Photoshop 制作网页线框图
查看>>
VC 多文档用户界面设计及各个文档之间的切换
查看>>
reinterpret_cast运算符
查看>>
dbware 1.0.1 发布,主备数据库读写分离
查看>>
jquery ajax post 入门及简单实例
查看>>
iPhone设备、型号、版本
查看>>
js练习4(注册验证)
查看>>
监听文本框输入
查看>>
Android 相对布局
查看>>
基于精益分析的case学习[翻译]
查看>>
Conditioniz – 探测浏览器并条件加载 JavaScript 和 CSS
查看>>
一种由B+树实现的倒排索引--《电脑知识与技术》2011年08期
查看>>
两个容积互质的水杯可倒出任意从1到容积和的水量
查看>>
11g新特性:Rolling Upgrade With Physical Standby
查看>>
ActiveXObject
查看>>
-prefix-free:帮你从 CSS 前缀的地狱中解脱出来
查看>>
Java基础12 类型转换与多态
查看>>