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);
});
});
},