是否可以將消息發送到特定會話?Spring WebSocket @SendToSession:將消息發送到特定會話
我有一個客戶端和Spring servlet之間的未經身份驗證的websocket。當異步作業結束時,我需要將未經請求的消息發送到特定的連接。
@Controller
public class WebsocketTest {
@Autowired
public SimpMessageSendingOperations messagingTemplate;
ExecutorService executor = Executors.newSingleThreadExecutor();
@MessageMapping("/start")
public void start(SimpMessageHeaderAccessor accessor) throws Exception {
String applicantId=accessor.getSessionId();
executor.submit(() -> {
//... slow job
jobEnd(applicantId);
});
}
public void jobEnd(String sessionId){
messagingTemplate.convertAndSend("/queue/jobend"); //how to send only to that session?
}
}
正如您在此代碼中看到的,客戶端可以啓動一個異步作業,當它完成時,它需要結束消息。顯然,我只需要向申請人發送消息,而不是向所有人廣播。 有一個@SendToSession
註釋或messagingTemplate.convertAndSendToSession
方法將是很好的。
UPDATE
我嘗試這樣做:
messagingTemplate.convertAndSend("/queue/jobend", true, Collections.singletonMap(SimpMessageHeaderAccessor.SESSION_ID_HEADER, sessionId));
但這廣播到,不僅是一個指定的所有會話。
UPDATE 2
測試與convertAndSendToUser()方法。 這個測試是和官員,在春天教程黑客:https://spring.io/guides/gs/messaging-stomp-websocket/
這是服務器代碼:
@Controller
public class WebsocketTest {
@PostConstruct
public void init(){
ScheduledExecutorService statusTimerExecutor=Executors.newSingleThreadScheduledExecutor();
statusTimerExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
messagingTemplate.convertAndSendToUser("1","/queue/test", new Return("test"));
}
}, 5000,5000, TimeUnit.MILLISECONDS);
}
@Autowired
public SimpMessageSendingOperations messagingTemplate;
}
,這是客戶端代碼:
function connect() {
var socket = new WebSocket('ws://localhost:8080/hello');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/user/queue/test', function(greeting){
console.log(JSON.parse(greeting.body));
});
});
}
不幸的是客戶端沒有收到正如預期的那樣,它每個會話每5000ms回覆一次。我敢肯定,「1」是一個有效的sessionId的連接,因爲我看到它在調試模式SimpMessageHeaderAccessor.getSessionId()
背景情景
我想創建一個進度條進行遠程作業的第二客戶端,客戶端向服務器請求一個異步作業,並通過服務器發送的websocket消息檢查其進度。這不是文件上傳,而是遠程計算,所以只有服務器知道每個作業的進度。 我需要發送消息到特定的會話,因爲每個作業都是按會話啓動的。 客戶端要求進行遠程計算 服務器啓動此作業,併爲每個作業步驟回覆申請人客戶端的作業進度狀態。 客戶端收到有關其作業的消息並建立進度/狀態欄。 這就是爲什麼我需要每會話消息。 我也可以使用每個用戶的消息,但是Spring 不會爲每個用戶提供未經請求的消息。(Cannot send user message with Spring Websocket)
工作液
__ __ ___ ___ _ __ ___ _ _ ___ ___ ___ _ _ _ _____ ___ ___ _ _
\ \ /// _ \ | _ \| |/ /|_ _|| \| |/__| /__|/_ \ | | | | | ||_ _||_ _|/ _ \ | \| |
\ \/\/ /| (_) || /| ' < | | | .` || (_ | \__ \| (_) || |__| |_| | | | | || (_) || .` |
\_/\_/ \___/ |_|_\|_|\_\|___||_|\_| \___| |___/ \___/ |____|\___/ |_| |___|\___/ |_|\_|
從UPDATE2解決方案開始,我必須完成convertAndSendToUser方法與去年參數(MessageHeaders):
messagingTemplate.convertAndSendToUser("1","/queue/test", new Return("test"), createHeaders("1"));
其中createHeaders()
是這樣的方法:
private MessageHeaders createHeaders(String sessionId) {
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
headerAccessor.setSessionId(sessionId);
headerAccessor.setLeaveMutable(true);
return headerAccessor.getMessageHeaders();
}
我發現這個:https://jira.spring.io/browse/SPR-12143 – Tobia
我寫過你的例子。你怎麼知道誰是你想發送消息的特定會話? – Aviad
這是一個遠程作業管理,當控制器收到一個遠程作業請求時,它應該存儲申請人的會話以傳送未來作業狀態回覆 – Tobia