php cdi_集成CDI和WebSockets
php cdi
考慮嘗試一個簡單的Java EE 7原型應(yīng)用程序,該應(yīng)用程序涉及JAX-RS(REST),WebSockets和CDI。
注意 :不想讓它成為破壞者-但本文主要討論我在嘗試使用Web套接字和使用CDI作為“膠水”(在Java EE應(yīng)用程序中)使用REST時遇到的問題。 整合并未實現(xiàn),但是仍然吸取了一些教訓(xùn):-)
這個想法是使用REST端點作為Web套接字端點的“提要”,從而將數(shù)據(jù)“推送”到所有連接的客戶端:
- JAX-RS端點,它從其他來源接收數(shù)據(jù)(可能是實時的)作為Web套接字端點的輸入
- 將CDI事件用作黑白JAX-RS和WebSocket端點的粘合點,并“觸發(fā)”有效載荷 @Path("/feed") public class RESTFeed {@InjectEvent<String> event;@POST@Consumes(MediaType.TEXT_PLAIN)public void push(String msg) {event.fire(msg);} }
- 在WebSocket端點實現(xiàn)中使用CDI Observer方法將數(shù)據(jù)推送到連接的客戶端: public void onMsg(@Observes String msg) {//different WS enpoint instance - notice the hash code value in the server logSystem.out.println("WS End point class ID -- " + this.hashCode());try {client.getBasicRemote().sendText(msg);} catch (IOException ex) {Logger.getLogger(ServerEndpoint.class.getName()).log(Level.SEVERE, null, ex);} }
當(dāng)然,目前還沒有考慮到更詳細(xì)的信息,例如性能,異步通信等。 更多實驗
但這有可能嗎?
這是我執(zhí)行的步驟
- 部署代碼
- 瀏覽到http:// localhost:8080 / Explore-WebSocket-CDI-Integration-Maven /并作為Web套接字客戶端連接
- 使用Postman在REST端點上觸發(fā)HTTP POST請求
繁榮! Observer方法中的NullPointerException –我等待了幾秒鐘,然后現(xiàn)實擊中了我!
根本原因(據(jù)我了解)
- WebSocket端點的行為
WebSocket端點與JAX-RS資源類相似,因為每個連接的客戶端都有一個Web套接字端點類的實例(至少默認(rèn)情況下)。 WebSocket規(guī)范中明確提到了這一點。 客戶端(對等方)連接后,就會創(chuàng)建一個唯一的實例,并且可以安全地將Web套接字會話對象(對等方的表示形式)作為實例變量進行緩存。 IMO,這是一個簡單干凈的編程模型
- 但是CDI容器還有其他計劃!
REST端點一旦觸發(fā)CDI事件(響應(yīng)POST請求),CDI容器就會創(chuàng)建WebSocket終結(jié)點(在本例中為CDI Observer)的其他實例。 為什么? 因為CDI bean本質(zhì)上是上下文相關(guān)的 。 該應(yīng)用程序不控制CDI bean的實例。 它只是使用它們(通過@Inject)。 由容器決定創(chuàng)建和銷毀bean實例,并確保在相同上下文中執(zhí)行的bean可以使用適當(dāng)?shù)膶嵗?容器如何確定上下文呢? 通過范圍 -應(yīng)用程序,會話,請求等…..
(再次,在CDI規(guī)范中明確提到)
因此,問題的要點是沒有WebSocket終結(jié)點當(dāng)前上下文的實例–因此,CDI將創(chuàng)建一個新實例以傳遞消息。 當(dāng)然,這意味著實例變量將指向null,因此將指向NPE(Duh!)
。
WebSocket端點將使用哪個CDI范圍? 我嘗試了@ ApplicationScoped,@ SessionScoped和@RequestScoped卻沒有太多運氣–仍然是一個新實例和一個NPE
還有其他選擇嗎?
- 將會話集定義為靜態(tài)變量將達(dá)到目的: private static Set<Session> peers = Collections.synchronizedSet(new HashSet());
但是,如果只是需要在觀察者方法中處理特定于客戶端的狀態(tài)(只能作為實例變量處理),則IMO只是一種黑客手段,因此不可行–它勢必會保持未初始化的狀態(tài)。
- 服務(wù)器發(fā)送事件 ? 但最終,SSE!= WebSocket。 如果用例要求服務(wù)器端僅“推送”,則可以選擇。 SSE尚不是Java EE標(biāo)準(zhǔn)-Java EE 8可能使之成為可能
解決方法
我不是專家,但是我想這取決于WebSocket規(guī)范,以便更清楚地說明如何將其與CDI結(jié)合使用。 鑒于CDI是Java EE規(guī)范中必不可少的一部分,因此將其與其他規(guī)范(特別是以HTML5為中心的規(guī)范,例如JAX-RS,WebSocket等)進行無縫集成非常重要。
Bruno Borges的這篇文章鏈接了與JMS,CDI和WebSocket有關(guān)的類似問題以及它們?nèi)绾蜗嗷ゼ伞?
我錯過了明顯的事情嗎? 您有任何意見/解決方案嗎? 請隨時鳴叫! :-)
示例代碼在GitHub上可用 (如果您想看一看)。 我在GlassFish 4.1和Wildfly 8.2.0上嘗試過
我想現(xiàn)在就這些了。 :-)
干杯!
翻譯自: https://www.javacodegeeks.com/2015/02/integrating-cdi-websockets.html
php cdi
總結(jié)
以上是生活随笔為你收集整理的php cdi_集成CDI和WebSockets的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 符文工房结晶(符文工房5合成水晶)
- 下一篇: 荣事达微电脑高压锅怎么用(荣事达高压锅怎