Я пытаюсь настроить личный чат с использованием веб-сокетов Spring. Я пытаюсь использовать SimpMessagingTemplate.convertAndSendToUser, но он не передает сообщение пользователю. Я могу установить соединение, и моя конечная точка addActiveUser работает нормально, но SimpMessagingTemplate.convertAndSendToUser не отправляет мое сообщение клиенту.
Кто-нибудь может увидеть, что мне не хватает? вот мой код
ПРИМЕЧАНИЕ: мой код клиента использует угловой 7, если это помогает
Серверная сторона
pom.xml
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gibsams</groupId>
<artifactId>wschatapplication</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>WSChatApplication</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- For Working with Json Web Tokens (JWT) -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
WebSocketConfig
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/socket")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/chat", "/queue");
registry.setUserDestinationPrefix("/user");
}
}
ChatController
@Controller
@RequestMapping("/api/chat")
public class ChatController {
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/send/message")
public void sendMessage(@Payload ChatMessage chatMessage,
SimpMessageHeaderAccessor headerAccessor
) throws Exception {
simpMessagingTemplate.convertAndSendToUser(chatMessage.getRecipient(), "/queue/reply", chatMessage);
}
@MessageMapping("/send/addActiveUser")
@SendTo("/chat/")
public ChatMessage addActiveUser(@Payload ChatMessage chatMessage,
SimpMessageHeaderAccessor headerAccessor
) {
String sender = chatMessage.getSender();
headerAccessor.getSessionAttributes().put("username", sender);
return chatMessage;
}
}
ChatMessage
public class ChatMessage {
private String sender;
private String recipient;
private String content;
public ChatMessage() {}
public ChatMessage(String sender, String recipient, String content) {
this.sender = sender;
this.recipient = recipient;
this.content = content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
Клиентская сторона
chat.service
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject, Observable } from 'rxjs';
import { ChatMessage } from '../models/chat.message';
import * as Stomp from 'stompjs';
import * as SockJS from 'sockjs-client';
import { AlertService } from './alert.service';
@Injectable({
providedIn: 'root'
})
export class ChatService {
private activeUsersSubject = new Subject<any>();
private chatMessagesSubject = new Subject<any>();
private apiUrl: string = environment.apiUrl;
private chatUrl: string = 'http://localhost:5000/socket';
stompClient = null;
activeUsers: string[] = [];
messages: ChatMessage[] = [];
constructor(private http: HttpClient, private alertService: AlertService) {
this.connect();
}
public connect() {
const socket = new SockJS(this.chatUrl);
this.stompClient = Stomp.over(socket);
const _this = this;
_this.stompClient.connect({}, lamda => {
this.stompClient.subscribe('/user/queue/reply', function(msg) {
_this.onMessageRecieved(msg);
});
this.stompClient.subscribe('/chat/', function(msg) {
_this.onMessageRecieved(msg);
});
this.setConnected(true);
this.connectToChat();
}, error => {
this.alertService.error('Unable to connect to WebSocket server: ' + error);
});
}
public getChatUsers(): Observable<any> {
return this.activeUsersSubject.asObservable();
}
public getChatMessages(): Observable<ChatMessage[]> {
return this.chatMessagesSubject.asObservable();
}
disconnect() {
if (this.stompClient != null) {
this.stompClient.disconnect();
}
this.setConnected(false);
}
public send(message: ChatMessage) {
try {
this.stompClient.send('/app/send/message', {}, JSON.stringify(message));
} catch (error) {
this.alertService.error(error);
}
}
private async connectToChat() {
const message: ChatMessage = <ChatMessage>({
sender: 'Sam',
type: 'JOIN'
});
try {
this.stompClient.send('/app/send/addActiveUser', {}, JSON.stringify(message));
} catch (error) {
this.alertService.error(error);
}
}
private onMessageRecieved(msg) {
const message = JSON.parse(msg.body);
if (message.type === 'CHAT') {
this.chatMessagesSubject.next(message);
} else if (message.type === 'JOIN') {
console.log('JOIN message: ' + msg);
this.activeUsersSubject.next(message.sender);
} else if (message.type === 'LEAVE') {
this.activeUsers.forEach( (item, index) => {
if (item === message.sender) {
this.activeUsers.splice(index, 1);
}
});
}
}
private setConnected(connected: boolean) {
if (connected) {
console.log('Connected!');
} else {
console.log('Disconnected!');
}
}
}