Java 跺脚客户端不';在用户目的地上没有收到消息?
我遇到的问题是,客户端没有收到发送到用户目的地的stomp消息。让我解释一下: 在WebSocketMessageBrokerConfiguration中:Java 跺脚客户端不';在用户目的地上没有收到消息?,java,spring,spring-websocket,stomp,Java,Spring,Spring Websocket,Stomp,我遇到的问题是,客户端没有收到发送到用户目的地的stomp消息。让我解释一下: 在WebSocketMessageBrokerConfiguration中: public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/secured/topic", "/secured/user/queue"); config.setUserDe
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/secured/topic", "/secured/user/queue");
config.setUserDestinationPrefix("/secured/user");
..
在我的stompjs客户端(以“管理员”身份登录):
在日志中:
Processing SUBSCRIBE /secured/user/queue/notifications id=sub-0 session=d74f49b3-bb63-580f-b862-81647cc712b3
和发送消息的java代码:
simpMessagingTemplate.convertAndSendToUser(
"admin", "/secured/user/queue/notifications", out);
这将导致日志:
Processing MESSAGE destination=/secured/user/queue/notifications-userd74f49b3-bb63-580f-b862-81647cc712b3 session=null payload={"from":"server","text":"hello","recipient":"admin","time":"13:29:10"}
-
但控制台日志中未打印任何消息
正如您所看到的,sessionid在subscribe和send步骤中是相同的。但我不明白为什么客户没有收到信息。请注意,没有用户目标的消息工作正常
有谁能帮我一把吗?也许你应该创建自己的用户主体模型类来确定它是否有这样的正确用户名
public class StompPrincipal implements Principal {
String name;
String userid;
public StompPrincipal(String name) {
this.name = name;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
@Override
public String getName() {
return name;
}
}
此外,您还应该创建一个DefaultHandshakeHandler
实现,以使用您选择的名称创建用户
public class CustomHandshakeHandler extends DefaultHandshakeHandler {
// Custom class for storing principal
@Override
protected Principal determineUser(ServerHttpRequest request,
WebSocketHandler wsHandler,
Map<String, Object> attributes) {
// Generate principal with UUID as name
return new StompPrincipal(UUID.randomUUID().toString());
}
}
我尝试了很多变化,但我不知道为什么它能工作,但我没有抱怨。我所做的: 在configureMessageBroker(WebSocketMessageBrokerConfigure)中(与我阅读的所有示例相比,这让我非常困惑): convertAndSendToUser(convertAndSendToUser添加了“/secured/user”+用户名): 以及我在客户端上的订阅(不太喜欢在此处添加用户名): 但它是有效的;-) [编辑] 跟踪日志记录使您更容易理解正在发生的事情:
<Logger name="org.springframework.messaging" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
干杯,如果是匿名用户,这确实非常方便,但我使用spring security来完成所有登录工作,这是正确的。您还可以查看日志消息,找到用户“admin”的正确会话id(d74f49b3-bb63-580f-b862-81647cc712b3),它与该用户的订阅请求相匹配。我认为您可以将StompPrincipal
的构造函数参数设置为SecurityContextHolder.getContext().getAuthentication().getName()
在确定用户
功能中。正在等待它是否工作。感谢您的评论,但正如我在上一篇评论中指出的,我不认为主要类是问题所在,只要看一下会话id,“admin”解析为正确的“sessionid”。这里唯一的问题是我没有在客户端收到它。Stomp不知道“admin”用户。因此,如果您想将消息发送给此用户,您需要知道它是“sessionid”。stomp知道它正在创建自定义主体的一种方法,如上面的代码所示。另一种方法是打开包含用户名信息的标题参数的连接。之后,您可以将用户名和会话id存储在列表中。并从列表中发送带有sessionid的消息给管理员。stomp是上面的一个额外层websocket,如果我理解正确,如果您使用spring security+stomp,则主体是已知的。我做了一个快速测试,将“log.debug(SecurityContextHolder.getContext().getAuthentication().getName())”添加到带有@MessageMapping的方法中,它确实打印了登录的用户。
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("*")
.setHandshakeHandler(new CustomHandshakeHandler());
}
config.enableSimpleBroker("/secured/topic", "/secured/queue", "/secured/user");
simpMessagingTemplate.convertAndSendToUser( "admin", "/queue/notifications", out);
stompClient.subscribe("/secured/user/"+userName+"/queue/notifications"
, function (output) {
<Logger name="org.springframework.messaging" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>