1. 官网地址
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 截图
日拱一卒无有尽,功不唐捐终入海