WebSocket和Java
WebSocket是一項很酷的新技術(shù),它允許瀏覽器與服務(wù)器之間進行實時雙向通信,而幾乎沒有開銷。 我在這里想要做的是,提供一個非常簡潔但足夠全面的概述,以介紹如何開始使用該技術(shù)。 因此,從以下幾件事開始:
- 在瀏覽器和服務(wù)器之間打開了一個tcp套接字連接,并且各方可以向另一方發(fā)送消息(即,只要有可用,服務(wù)器就可以推送數(shù)據(jù)-無需輪詢,長時間輪詢,iframe等)。
- 并非所有瀏覽器都支持它-IE 10是第一個支持它的IE版本,Android仍然存在問題。 幸運的是,如果不支持WebSocket,則可以使用SockJS ,它可以回溯到其他推式仿真。
- 并非所有代理服務(wù)器都支持/允許它,因此可能需要再次進行回退
- 適用于游戲,交易應(yīng)用程序,以及實際上任何需要服務(wù)器將數(shù)據(jù)推送到瀏覽器的事物
- Java具有標(biāo)準(zhǔn)的API(JSR-356) ,您可以在服務(wù)器上使用它來處理WebSocket連接。
- Spring在Java API之上提供了一個 API。 spring支持的好處是它具有對SockJS的服務(wù)器端支持,您可以輕松使用依賴注入。 Spring還為消息驅(qū)動的體系結(jié)構(gòu)提供了STOMP支持 。 這兩篇Spring文章都包含指向我推薦的GitHub示例項目的鏈接。
在繼續(xù)一些示例代碼之前,這里是套接字的生命周期,包括客戶端和服務(wù)器(假設(shè)上述API之一):
當(dāng)前,沒有API或框架支持基于注釋的路由。 Java API支持基于注釋的終結(jié)點處理程序,但是它為每個連接URL提供一個類,并且通常您希望在單個連接上執(zhí)行多個操作。 即,您連接到ws://yourserver.com/game/,然后要傳遞“ joinGame”,“ leaveGame”消息。 同樣,服務(wù)器需要發(fā)回不止一種消息。 我的實現(xiàn)方式是通過一個枚舉,包含所有可能的動作/事件類型,并使用switch構(gòu)造確定要調(diào)用的內(nèi)容。
因此,我決定為我的算法音樂作曲家制作一個簡單的游戲 。 它使用的是Spring API。 這是我在我所工作的公司中所做的相關(guān)演示的幻燈片 。 下面是一些示例代碼:
@Component public class GameHandler extends WebSocketHandlerAdapter {private Map players = new ConcurrentHashMap<>();private Map playerGames = new ConcurrentHashMap<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {Player player = new Player(session);players.put(session.getId(), player);}@Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {leaveGame(session.getId()); }@Override protected void handleTextMessage(WebSocketSession session, TextMessage textMessage) throws Exception {try {GameMessage message = getMessage(textMessage); //deserializes the JSON payloadswitch(message.getAction()) { case INITIALIZE: initialize(message, session); break;case JOIN: join(message.getGameId(), message.getPlayerName(), session); break;case LEAVE: leave(session.getId()); break;case START: startGame(message); break;case ANSWER: answer(message, session.getId()); break;}} catch (Exception ex) {logger.error("Exception occurred while handling message", ex);} }讓我們看一個示例服務(wù),服務(wù)器需要在其中向客戶端發(fā)送消息。 讓我們以一個玩家加入游戲為例,而所有其他玩家都需要收到新的通知。 系統(tǒng)中的核心類是Game,其中包含玩家列表,并且如您所見,Player包含對WebSocket會話的引用。 因此,當(dāng)玩家加入游戲時,將調(diào)用以下Game方法:
public boolean playerJoined(Player player) {for (Player otherPlayer : players.values()) {otherPlayer.playerJoined(player);}players.put(player.getSession().getId(), player);return true; }然后player.playerJoined(..)通過基礎(chǔ)連接發(fā)送一條消息,通知瀏覽器新玩家加入:
public void playerJoined(Player player) {GameEvent event = new GameEvent(GameEventType.PLAYER_JOINED);event.setPlayerId(player.getSession().getId()); event.setPlayerName(player.getName());try {session.sendMessage(new TextMessage(event.toJson()));} catch (IOException e) {new IllegalStateException(e);}}從服務(wù)器向瀏覽器發(fā)送消息也可能由計劃的作業(yè)觸發(fā)。
關(guān)鍵是要保留所有已連接瀏覽器的列表,以便可以將信息發(fā)送回去。 該列表可以是一個靜態(tài)字段,但是對于單例spring bean,則不需要。
現(xiàn)在,兩個重要方面–安全性和身份驗證。 這是Heroku的一篇不錯的文章 ,同時討論了兩者。 如果有任何敏感內(nèi)容,您應(yīng)該首選wss(相對于TLS,它是websocket)。 您還應(yīng)該在兩端驗證您的輸入,并且不應(yīng)該依賴Origin標(biāo)頭,因為攻擊者可能很容易欺騙瀏覽器。
身份驗證可以依賴于HTTP會話cookie,但是顯然,有些人更喜歡實現(xiàn)自己的類似于cookie的工作流,以獲取短暫的令牌,該令牌可用于執(zhí)行經(jīng)過身份驗證的操作。
WebSocket使DDD變得自然。 您不再需要使用貧血對象-您的對象具有各自的狀態(tài),并且在該狀態(tài)下執(zhí)行操作。 與此相關(guān)的是,websocket應(yīng)用程序更易于測試。
這是開發(fā)WebSocket應(yīng)用程序時要記住的一般事項。 請注意,您不必在所有地方都使用WebSocket –我將其僅限于需要“推送”的功能。
總體而言,WebSocket是一項很好的有趣技術(shù),有望淘汰所有hacky推送仿真。
翻譯自: https://www.javacodegeeks.com/2013/12/websocket-and-java.html
總結(jié)
以上是生活随笔為你收集整理的WebSocket和Java的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 双路由器如何设置路由器如何调全双红
- 下一篇: 如何用路由器禁止迅雷路由器如何设置禁止迅