2017-07-14 38 views
0

我希望我的udp服務器在一個線程中運行,每次收到一個數據報時都會觸發一個事件,並將數據格式化爲json。如何從運行在服務器中的線程中激發CDI事件?

public class UDPServer extends Thread { 

     private SocketUDPCommunication comm; 

     @Inject @Notify 
     private StatusChangeHandler sch; 

     public UDPServer() { 
      comm = new SocketUDPCommunication(); 
     } 


     @Override 
     public void run() { 

      DatagramPacket response; 

      comm.setPort(Utils.UDP_SERVER_PORT); 
      comm.createSocket(); 

      while (!Thread.currentThread().isInterrupted()) { 
       System.out.println("Waiting for clients to connect on port:" + comm.getSocket().getLocalPort()); 
       try { 
        response = comm.receiveResponse(); 
       } catch (SocketTimeoutException e) { 
        continue; 
       }       

       byte[] byteSend = comm.discardOffset(response); 

       Status status = frameToJson(byteSend); 

       Genson genson = new Genson(); 
       String json = genson.serialize(status); 

       sch.sendChangedStatus(json); //Raise the cdi event, sch not initialized!! 
      } 

     } 

     @Override 
     public void interrupt() { 
      super.interrupt(); 
      comm.closeConnection(); 
     } 
    } 

還有的定義對於這個事件的監聽器,它會調用WebSocket的終點法廣播這個消息到所有連接的客戶端:

public class StatusChangeObserver { 

     public void statusChanged(@Observes StatusChange sce) { 
      WebsocketEndPoint.sendAll(sce.getJson()); 
     } 
    } 

    @ServerEndpoint(value="/websocket") 
    public class WebsocketEndPoint { 
     private static Set<Session> userSessions = Collections.synchronizedSet(new HashSet<Session>()); 

     @OnOpen 
     public void onOpen(Session userSession) { 
      System.out.println("Opening new connection"); 
      userSessions.add(userSession); 
     } 

     @OnClose 
     public void onClose(Session userSession) { 
      System.out.println("Connection closed. Id: " + userSession.getId()); 
      userSessions.remove(userSession); 
     } 


     public static void sendAll(String message) { 
      for (Session session : userSessions) { 
       if (session.isOpen()) { 
        session.getAsyncRemote().sendText(message); 
       } 
      }  
     } 
    } 

而且處理程序將實際觸發事件:

@Notify 
    public class StatusChangeHandler { 

     @Inject 
     private Event<StatusChange> statusChangedEvent; 

     public void sendChangedStatus(String json) { 
      StatusChange sce = new StatusChange(json); 
      statusChangedEvent.fire(sce); 
     } 
    } 

StatusChange是一個簡單的POJO,它將包含要廣播的消息。該@Notify預選賽:

@Qualifier 
    @Retention(RUNTIME) 
    @Target({METHOD, FIELD, PARAMETER, TYPE}) 
    public @interface Notify { 
    } 

這是我的依賴注入的第一步,所以我不太確定我應該如何在線程中觸發事件,以及如何初始化sch對象。 我發現this page建議使用WeldWeldContainer類來初始化CDI,但我無法用maven找到這個類。這是正確的做法嗎?在那種情況下,任何人都知道如何將這些類包含到我的項目中?

+1

如果您要部署到Tomcat,則需要使用Weld Servlet https://docs.jboss.org/weld/reference/latest/en-US/html/environments.html#weld-servlet,而不是焊接SE。 –

回答

0

在這裏你有與焊接庫公共存儲庫。

https://mvnrepository.com/artifact/org.jboss.weld

但是,你需要什麼?在這個環境中你會使用它?例如,在wildfly中,集成了cdi 1.1或cdi 1.2,您不需要添加這些庫。

欲瞭解更多信息,請http://weld.cdi-spec.org/

+0

我正在使用Tomcat8,Weld文檔中指出的Maven依賴關係包含在「pom.xml」中。 「beans.xml」是在WEB-INF中,而在META-INF中是「context.xml」。不過,我不能導入「org.jboss.weld.environment.se.Weld」 – Juan

0

既然你是在Tomcat上,我們正在談論的servlet環境。爲此,Weld提供了一個servlet JAR,它會自動爲您啓動CDI。無需手動處理Weld/WeldContainer

這裏是一個link to Weld documentation,它解釋了您需要的工件/依賴以及如何使用它。

添加後,CDI應該在您將應用程序部署到Tomcat時簡單引導。

相關問題