想要使用websockets向特定客户端发送通知。有一个用于发送通知的计划任务,但无法在该任务中获取Principal。找到了this帖子,但据我所知,Spring预定的方法必须是无参数的。
@Scheduled(fixedDelay=5000)
public void sendMessages(Principal principal)
messagingTemplate
.convertAndSendToUser(principal.getName(), "/queue/horray", "Horray, " + principal.getName() + "!");
}
这可能吗?如何在预定方法中获得websocket主体?
答案 0 :(得分:1)
您无法在预定方法中获取主体,因为方法调用不是由用户启动的。
您可以遵循以下方法:
1)创建一个websocket终点“/ app / events”
2)让所有用户订阅该终点
3)获取您要发送通知的所有用户ID
4)向单个用户发送通知
simpMessagingTemplate.convertAndSendToUser("userId", "/app/events", "messageEntity");
userId: can be actual user id if authenticated or it can be websocket session id.
答案 1 :(得分:0)
我为这种情况写了一个解决方法。首先,我为websockets事件创建一个监听器。在订阅请求的情况下,我将userId保留在请求中并保留在ConcurrentHashMap中。另一方面,当客户端断开连接或发送取消订阅请求时,我会从该Map中删除他的userId。
我的听众课程:
@Service
public class MyEventListener {
@Autowired
private NotificationPublisher notificationPublisher;
@EventListener({SessionSubscribeEvent.class})
public void onWebSocketSubscribeEvent(SessionSubscribeEvent event) {
notificationPublisher.subscribedUsers.put(event.getUser().getName(), Calendar.getInstance().getTimeInMillis());
}
@EventListener({SessionUnsubscribeEvent.class})
public void onWebSocketUnsubscribeEvent(SessionUnsubscribeEvent event) {
notificationPublisher.subscribedUsers.remove(event.getUser().getName());
}
@EventListener({SessionDisconnectEvent.class})
public void onWebSocketDisconnectEvent(SessionDisconnectEvent event) {
notificationPublisher.subscribedUsers.remove(event.getUser().getName());
}
}
实际作业正在运行的通知发布者类:
public class NotificationPublisher {
public final Map<String, Long> subscribedUsers = new ConcurrentHashMap<>();
@Autowired
private SimpMessagingTemplate messagingTemplate;
@Autowired
private MyService myService;
@Value("${task.notifications.publisher.websocket_timeout_seconds}")
private int websocketSessionTimeout;
public void sendDataUpdates() {
SocketResponseCount count = null;
for(String key: subscribedUsers.keySet()) {
long subscribeTime = subscribedUsers.get(key);
if(Calendar.getInstance().getTimeInMillis() - subscribeTime > websocketSessionTimeout*1000) {
subscribedUsers.remove(key);
continue;
}
count = myService.getNotificationsCount(key);
this.messagingTemplate.convertAndSendToUser(key, "/queue/publish",count);
}
}
}
也许它会帮助某人
答案 2 :(得分:0)
我的解决方案:我得到所有用户会话
@Autowired
private SimpMessagingTemplate template;
@Autowired
private MyRepository myRepository;
@Autowired
private SessionRegistry sessionRegistry;
@Scheduled(fixedRate = 5000)
public void greeting() {
List<SessionInformation> activeSessions = new ArrayList<>();
for (Object principal : sessionRegistry.getAllPrincipals() )
{
activeSessions.addAll( sessionRegistry.getAllSessions( principal, false ) );
}
for (SessionInformation session : activeSessions )
{
Object principalObj = session.getPrincipal();
if ( principalObj instanceof CurrentUser)
{
CurrentUser user = (CurrentUser) principalObj;
this.template.convertAndSendToUser(user.getUsername().toUpperCase(),"/queue/reply2",myRepository.findAll());
}
}
}