springboot java websocket ws STOMP(二)

一、什么是STOMP?

STOMP源于需要通过脚本语言(例如Ruby,Python和Perl)连接到企业消息代理的需求。在这样的环境中,通常在逻辑上执行简单的操作,例如“可靠地发送单个消息并断开连接”或“在给定目的地上消耗所有消息”。

它是其他开放消息协议(例如AMQP)和JMS代理(例如OpenWire)中使用的实现特定有线协议的替代。它通过覆盖一小部分常用消息传递操作而不提供全面的消息传递API来与众不同。

STOMP协议是和AMQP,JMS消息协议是平级的是应用层的协议,STOMP是可以建立在WebSocket协议上面的,

一个STOMP帧由三部分组成: 命令,Header(头信息),Body(消息体)

一个STOMP客户端是一个可以以两种模式运行的用户代理,可能是同时运行两种模式。

  • 作为生产者,通过SEND框架将消息发送给服务器的某个服务
  • 作为消费者,通过SUBSCRIBE制定一个目标服务,通过MESSAGE框架,从服务器接收消息。

二、STOMP 命令

在客户端和服务端连接发送消息的命令有以下几种

  • SEND 发送
  • SUBSCRIBE 订阅
  • UNSUBSCRIBE 退订
  • BEGIN 开始
  • COMMIT 提交
  • ABORT 取消
  • ACK 确认
  • DISCONNECT 断开
2.1 客户端发送到服务端

都是建立在连接成功的情况下, 客户端想发送到服务端

  1. 服务端通过setApplicationDestinationPrefixes("/全局路径"); 设置路径
  2. 服务端编写controller代码 @MessageMapping("/路径") 可供调用
  3. 客户端通过stompClient.send(/全局路径/路径,body) 发送数据
2.2 服务端发送到客户端

连接成功的情况下 服务端想发送到客户端

  • 客户端需要去订阅服务器地址
    • 如果是公共的 /topic/路径
    • 如果是私有的 /queue/userId/路径
  • 服务端发送指定的路径到客户端,直接发送到订阅的路径就可以了
    • 可以通过 @SendTo(路径)
    • 可以通过 simpMessagingTemplate.convertAndSend("/queue/5214521/路径",“谢谢你hello”);

三、springboot 和stomp 最佳实践

3.1 添加依赖
 
        
            org.springframework.boot
            spring-boot-starter-websocket
        
        
            org.springframework
            spring-messaging
        

3.2 配置websocket stomp
package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
// @EnableWebSocketMessageBroker注解用于开启使用STOMP协议来传输基于代理(MessageBroker)的消息,这时候控制器(controller)
// 开始支持@MessageMapping,就像是使用@requestMapping一样。
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //注册一个 Stomp 的节点(endpoint),并指定使用 SockJS 协议。
        registry.addEndpoint("/sendStomp").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 广播式配置名为 topic 和 queue
        // topic一般用于广播推送
        // queue用于点对点推送
        registry.enableSimpleBroker("/topic","/queue");
        // 如果设置 前段请求过来必须带上 带上这个才会被 controller 拦截 (发送路径上体现)
        registry.setApplicationDestinationPrefixes("/server");
        // 点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是/user/
        // registry.setUserDestinationPrefix("/user/");

    }
}
3.3 实体类
package com.example.demo.request;

import lombok.Data;

/**
 * @Classname ClientRequest
 * @Description 
 * @Date 2021/3/19 14:35
 * @Created by dongzhiwei
 */
@Data
public class ClientRequest {

    /**
     * 用户名
     */
    private String name;

}

response

package com.example.demo.response;

import lombok.Data;

/**
 * @Classname ServerResponse
 * @Description 服务端返回
 * @Date 2021/3/19 14:35
 * @Created by dongzhiwei
 */
@Data
public class ServerResponse {

    public ServerResponse() {
    }

    public ServerResponse(String message) {
        this.message = message;
    }

    private String message;
}

3.4 控制层
package com.example.demo.controller;

import com.example.demo.request.ClientRequest;
import com.example.demo.response.ServerResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.stereotype.Controller;

/**
 * @Classname WebSocketController
 * @Description ws 的controller
 * @Date 2021/3/19 14:33
 * @Created by dongzhiwei
 */
@Controller
@Slf4j
public class WebSocketController {

    /**
     * 这个模板 可以发送到 客户端订阅的路径上,
     * 也就是调用这个发 必须要客户端先通过 subscribe 订阅这个地址
     */
    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;


    @MessageMapping("/hello") // @MessageMapping 和 @RequestMapping 功能类似,浏览器向服务器发起请求时,映射到该地址。
    public ServerResponse say(ClientRequest message) throws Exception {
        Thread.sleep(1000);
        simpMessagingTemplate.convertAndSend("/queue/5214521/subscribeTest","谢谢你hello");
        return new ServerResponse("Hello,"+message);
    }

    /**
     * 订阅点
     *
     */
    @SubscribeMapping("/subscribeTest")
    public ServerResponse sub() {
        log.info("XXX用户订阅了我。。。");
        return new ServerResponse("感谢你订阅了我。。。");
    }


}

3.5 编写客户端

如果spring boot 可以访问 web页面 可以通过 thymeleaf 实现 加依赖


org.springframework.boot
spring-boot-starter-thymeleaf

application.properties 里面配置访问路径

spring.thymeleaf.prefix=classpath:/public/

页面的代码




    Hello WebSocket
    
    
    
    



Greetings
3.6 测试连接

springboot java websocket ws STOMP(二)_第1张图片
连接成功!!

四、总结

这个对代码的侵入性比较高 但是涉及到有业务逻辑相关的 用这个也还行

你可能感兴趣的:(技术,ws,java,STOMP,websocket)