2016-08-01 18 views
1

我正在研究一個小型的Java項目,以下是我想要實現的基本概念:我有一個netty-socketio層,它接受來自socket.io請求瀏覽器,並且我使用JPA 2.1/hibernate將所請求的更改保存到數據庫。問題的關鍵是我也有一個流請求的概念,因爲用戶會請求集合的當前狀態以及所有未來的更新。爲了從數據庫獲得實時更新,我使用了Entity Listeners。我正在尋找一種將實體監聽器方法連接到socketio連接上的處理程序的可靠方法,即應該在它感興趣的數據發生變化時通知流處理程序,以便它可以將更新發送到管道中。我試圖想出一個實體監聽器可以發佈更新的單身主持人,並且訂閱處理程序可以使用它,全都基於String topic,非常像pubsub。我遇到的問題是這樣的:我們以POJO User爲例。當插入新的user時,UserEntityListener#PostInsert開始,並且它通過.publish調用將user轉發給Notifier。該Notifier使用<?>的數據類型,並通過Callable式的接口調用利害關係人:Hibernate Entity Listeners和netty-socketio之間的中介

public interface Notifiable { 
    public <T> void onEvent(T data); 
} 

所以現在執行這個被稱爲在適當的處理程序,但它具有通用型和我必須手動投射(處理程序知道它應該接收的類型)。我的問題是,我可以做到這一點沒有明確的演員?有沒有一個好的框架,使所有這些低級修補程序無用?我想要一個集中的解決方案來彌合差距,否則所有的樣板都會殺了我。

編輯添加相關的來源。

通知類:

class Subscriber { 
    public String topic; 
    public Notifiable notifiable; 
    public Subscriber(String topic, Notifiable n) { 
     this.topic = topic; 
     this.notifiable = n; 
    } 
} 

public class Notifier { 
    private static Notifier instance = null; 
    private List<Subscriber> subscribers = new ArrayList<Subscriber>(); 

    public Notifier() {}; 
    public void subscribe(String topic, Notifiable n) { 
     if (!this.hasSubscriber(topic, n)) { 
      this.subscribers.add(new Subscriber(topic, n)); 
     } 
    } 
    public <T> void publish(String topic, T data) { 
     for (Subscriber s : this.subscribers) { 
      if (s.topic.equals(topic)) { 
       s.notifiable.onEvent(data); 
      } 
     } 
    } 
    public Boolean hasSubscriber (String topic, Notifiable n) { 
     for (Subscriber s : this.subscribers) { 
      if (s.topic.equals(topic) && s.notifiable == n) { 
       return true; 
      } 
     } 
     return false; 
    } 

    public static Notifier getInstance() { 
     if (instance == null) { 
      instance = new Notifier(); 
     } 
     return instance; 
    } 
} 

實體監聽器:

@PostPersist 
public void PostInsert(User u) { 
    Notifier.getInstance().publish("user/new", u); 
} 

Socketio處理程序:

Notifier.getInstance().subscribe("user/new", (new Notifiable() { 
    @Override 
    public <T> void onEvent(T data) { 
     User u = (User) data; 
     logger.info("User name: " + u.getUsername()); 
    } 
})); 
+1

對不起,但我不理解你的問題......你只想避免在Notifiable執行的顯式轉換,是嗎?另外,你可以發佈'Notifier'類的代碼嗎? –

+0

嘿,我添加了相關的源代碼。有兩件事我不喜歡解決方案:第一件事是在處理程序對象中進行顯式投射,因爲它需要一種有效載荷,我想更自然地表達它。第二個是,我確信有更多優雅的方法來描述我描述的更一般的邏輯,我只是​​沒有意識到。 –

回答

1

如果你想避免顯式強制進行以下修改:

一個,讓您的法定接口通用:

public interface Notifiable<T> { 
    public void onEvent(T data); 
} 

兩個,讓用戶類也通用:

public class Subscriber<T> { 
    public String topic; 
    public Notifiable<T> notifiable; 
    public Subscriber(String topic, Notifiable<T> n) { 
     ... 
    } 
} 

三,適應通告類

public class Notifier { 
    private static Notifier instance = null; 

    @SuppressWarnings("rawtypes") 
    private List<Subscriber> subscribers = new ArrayList<Subscriber>(); 

    public Notifier() {}; 

    public <T> void subscribe(String topic, Notifiable<T> n) { 
     if (!this.hasSubscriber(topic, n)) { 
      this.subscribers.add(new Subscriber<T>(topic, n)); 
     } 
    } 

    @SuppressWarnings("unchecked") 
    public <T> void publish(String topic, T data) { 
     for (Subscriber<T> s : this.subscribers) { 
      if (s.topic.equals(topic)) { 
       s.notifiable.onEvent(data); 
      } 
     } 
    } 

    @SuppressWarnings("unchecked") 
    public <T> Boolean hasSubscriber (String topic, Notifiable<T> n) { 
     for (Subscriber<T> s : this.subscribers) { 
      /* XXX: Beware, is safe to compare two notifiable 
      * instances by their memory addresses?? 
      */ 
      if (s.topic.equals(topic) && s.notifiable == n) { 
       return true; 
      } 
     } 
     return false; 
    } 

    public static Notifier getInstance() { 
     if (instance == null) { 
      instance = new Notifier(); 
     } 
     return instance; 
    } 
} 

四,Socketio處理程序:

Notifier.getInstance().subscribe("user/new", (new Notifiable<User>() { 
    @Override 
    public void onEvent(User data) { 
     logger.info("User name: " + u.getUsername()); 
    } 
})); 
+0

您是否同意在這種情況下,使用原始類型是可以接受的,因爲發佈者和使用者有關於實際類型的隱式合約,因此不會出現轉換問題,並且通知程序不會自行使用數據? –

+0

是的,原始類型的使用在這裏是確定的,因爲通知程序不會自己消耗數據(就像你說的那樣)... –

相關問題