1. 官网地址

https://docs.spring.io/spring/docs/5.2.6.RELEASE/spring-framework-reference/web.html#websocket-stomp-user-destination

2.入门示例

本示例在官网示例上稍加修改

2.1 依赖

   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

2.2 添加websocket配置类

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
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic", "/queue");  // 相当于定义了两个频道
        config.setApplicationDestinationPrefixes("/app");  // 前缀 , 与GreetingController类中@MessageMapping值一起使用("/app/hello")
        config.setUserDestinationPrefix("/queue");  // 表示其中queue这个频道是用于   一对一发送信息的. 默认是user
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/gs-guide-websocket")
                .setAllowedOrigins("*")
                .withSockJS();
    }

}

2.3 两个普通的实体类, 消息实例

public class Greeting {

  private String content;

  public Greeting() {
  }

  public Greeting(String content) {
    this.content = content;
  }

  public String getContent() {
    return content;
  }

}
public class HelloMessage {

  private String name;

  public HelloMessage() {
  }

  public HelloMessage(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}

2.4 controller

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.DestinationVariable;
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.SendToUser;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.HtmlUtils;

import javax.websocket.server.PathParam;
import java.security.Principal;
import java.time.LocalDateTime;

@RestController
public class GreetingController {

    @Autowired
    private SimpMessagingTemplate template;



    @GetMapping("/sendMsgToUser")
    public void sendMsgToUser() {
        HelloMessage message = new HelloMessage();
        message.setName("郑钦锋 to user," + LocalDateTime.now());
        // 一对一 [/queue/1/message]
        this.template.convertAndSendToUser("1", "/message", message);
    }

    /**
     * client可以直接将消息发送到指定的用户
     * DestinationVariable注解与PathVariable功能差不多
     * <p>
     * 使用 @SendToUser注解将消息发送给指定的用户还没弄明白, 不然也可以使用注解来实现,省去template
     */
    @MessageMapping("/sendMsgToUser/{userId}")
    public void sendMsgToUser1(@DestinationVariable("userId") Long userId, HelloMessage message) {
        System.out.println(message.getName());
        System.out.println(userId);
        message.setName("one to one ," + LocalDateTime.now());
        this.template.convertAndSendToUser(String.valueOf(userId), "/message", message);
    }


    /**
     * 测试通过SimpMessagingTemplate发送消息到"/topic/greetings"频道
     */
    @GetMapping("/sendMsg")
    public void sendMsg() {
        HelloMessage message = new HelloMessage();
        message.setName("郑钦锋," + LocalDateTime.now());
        // 将信息发送到"/topic/greetings"频道,然后只要是订阅了此频道的client都能收到发信息
        this.template.convertAndSend("/topic/greetings", message);
    }



    /**
     * 客户端可以通过@MessageMapping("/hello")[真实需要添加/app前缀]这个地址将消息发送到 @SendTo("/topic/greetings")这个地址,
     * 然后订阅了/topic/greetings这个地址的客户端就可以收到消息
     * <p>
     * ====================
     * 测试通过@SendTo注解发送消息到"/topic/greetings"
     */
    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Greeting sendMsg1(HelloMessage message) throws Exception {
        Thread.sleep(1000); // simulated delay
        System.out.println(message.getName());
        return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
    }


}

2.5 客户端实现

npm i stompjs -S
npm i sockjs-client -S
import SockJs from 'sockjs-client'
import Stomp from 'stompjs'
//测试websocket 通信
connect() {
    // http://127.0.0.1:8989/api 是服务端根路径 
    let socket = new SockJs('http://127.0.0.1:8989/api/gs-guide-websocket');
    let stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        console.log('连接服务端成功');
        console.log('Connected: ' + frame);

        // 接收消息 (客户端订阅了"/topic/greetings/")
        // stompClient.subscribe('/topic/greetings/', function (greeting) {
        //     console.log(greeting);
        // });

        // 发送消息到/app/hello
        // stompClient.send('/app/hello', {}, JSON.stringify({name: '郑钦锋'}),)

        // stompClient.send('/app/sendMsgToUser/1', {}, JSON.stringify({name: '郑钦锋'}),)

        // 接收消息 (一对一,感觉跟一对多一样的)
        stompClient.subscribe('/queue/1/message', function (greeting) {
            console.log(greeting);
        });
    });

},

2.6 截图

结果

posted on 2020-07-26 14:39  显示账号  阅读(1071)  评论(0编辑  收藏  举报