我正在尝试为一个移动应用程序(ionic 3)实现1对1聊天,使用Spring Boot后端,看起来遇到了一些配置问题。
无法发送消息,可能是因为目标通道没有被创建。
后端:
聊天控制器(ChatController):
@RestController
public class ChatController {
@Autowired
private PrivateChatService privateChatService;
private final static Logger logger = LogManager.getLogger(ChatController.class.getName());
@RequestMapping(value = "/chat/messages/{item_id}/chat_with/{buyer_login}", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<String> getExistingChatMessages(@PathVariable("item_id") String itemId, @PathVariable("buyer_login") String buyerLogin) {
List<ChatMessage> messages = privateChatService.getExistingChatMessages(itemId, buyerLogin);
logger.info("Here get messages");
return JSONResponseHelper.createResponse(messages, HttpStatus.OK);
}
@MessageMapping("/chat/{item_id}/send")
@SendTo("/topic/chat/{item_id}/chat_with/{buyer_login}")
public ChatMessage send(@Payload ChatMessage message,
@DestinationVariable("item_id") String item_id) throws Exception {
// logger.info(principal.getName());
logger.info(message.toString());
logger.info(item_id);
privateChatService.submitMessage(message);
return message;
}
}
WebSocketConfig:
@Configuration
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
private final static Logger logger = LogManager.getLogger(WebSocketConfig.class.getName());
@Autowired
private JwtTokenProvider jwtTokenProvider;
@Autowired
private PrivateChatService privateChatService;
private static final String MESSAGE_PREFIX = "/topic";
private static final String END_POINT = "/chat";
private static final String APPLICATION_DESTINATION_PREFIX = "/live";
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
if (registry != null) {
registry.addEndpoint(END_POINT).setAllowedOrigins("*").withSockJS();
}
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
if (registry != null) {
registry.enableSimpleBroker(MESSAGE_PREFIX);
registry.setApplicationDestinationPrefixes(APPLICATION_DESTINATION_PREFIX);
}
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new ChannelInterceptorAdapter() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String authToken = accessor.getFirstNativeHeader("Authentication");
String jwt = JwtUtils.resolveToken(authToken);
if (jwtTokenProvider.validateToken(jwt)) {
Authentication authentication = jwtTokenProvider.getAuthentication(jwt);
accessor.setUser(authentication);
String itemId = accessor.getFirstNativeHeader("item_id");
accessor.setDestination("/topic" + privateChatService.getChannelId(itemId, authentication.getName()));
logger.info(accessor.getDestination()); //ex: /topic/chat/3434/chat_with/user3797474342423
}
}
return message;
}
});
}
}
WebSocketSecurityConfig
的翻译是:WebSocket安全配置
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
移动客户端,ng2-stomp-service:
private _initWebsock(auth_token:string, item_id: number) {
let headers: Object = {
Authentication: `Bearer ${auth_token}`,
item_id: item_id
};
this.stomp.configure({
host :this.websocketApi + 'chat',
headers: headers,
queue:{'init':false}
});
console.log("Connecting stomp socket...");
//start connection
this.stomp.startConnect().then(() => {
this.stomp.done('init');
console.log('connected');
//subscribe
this.subscription = this.stomp.subscribe(`/chat/${item_id}/`, this.socketListener);
});
}
public socketListener = (data) => {
console.log(data)
};
send(msg: ChatMessage, item_id: number){
//send data
console.log(msg);
this.stomp.send(`/live/chat/${item_id}/send`, {}, JSON.stringify(msg));
}
问题 1(可能):
在浏览器控制台中显示客户端订阅了 /chat/item_id
,而不是 /topic/chat/3434/chat_with/user3797474342423
=> 看起来像是 configureClientInboundChannel
没有起作用?
问题 2:
尝试执行 this.stomp.send(/live/chat/${item_id}/send, {}, JSON.stringify(msg));
时,出现了 o.s.m.s.b.DefaultSubscriptionRegistry : No destination in GenericMessage [payload=byte[2], headers={simpMessageType=MESSAGE....
错误。