0

サーバー側では Spring 4 を使用しています。ブラウザ側では Ember.js を使用しています。

私のアプリケーションには、 や などのエンティティ クラスがPersonありProductます。これらのエンティティは、サーバーとブラウザーの両方で使用されており、同じようにモデル化されています。例えば:

//this is on the server side

public interface Person {    
    String getId();

    String getFirstName();
    void setFirstName(String firstName);

    String getLastName();
    void setLastName(String lastName);
}
//this is on the browser side, modeled with Ember Data

App.Person = DS.Model.extend({
    // id: DS.attr("string"), //property 'id' will be provided by Ember automatically
    firstName: DS.attr("string"),
    lastName: DS.attr("string")
});

サーバーとブラウザの間でエンティティの同期を維持する必要があります。したがって、たとえば、PersonfirstNameプロパティがサーバー側で変更されると、この変更は関連するすべてのブラウザにリアルタイムでプッシュされます。

Spring の WebSocket サポートを調査し、 Spring の「Hello WebSocket」の例に慣れた後、このテクノロジーを使用することが私の要件に適したアプローチであると確信しました。

WebSocket/STOMP は非常に低レベルであるため、このテクノロジの上に構築され、ブラウザー (ここでのエンティティの役割はobserver ) とサーバー (エンティティの役割)の間でオブザーバー パターンのような動作を提供するソリューションを探しています。ここではsubject/observableになります)。

この「キープ・エンティティー・イン・シンク」の課題に対する既存の解​​決策を見つけることができなかったので (Spring 内の解決策でも、サード・パーティー・ライブラリーの解決策でもありません)、独自の解決策を構築したいと考えていますが、設計はすでに興味深い問題を提起しています。 、 そのような:

  • プロトコルはどのように見えるべきですか? 変更が発生したら、サーバーはエンティティ タイプとその ID のみを含む最小限のフレームを送信する必要がありますか? (たとえばPerson、ID "3" を持つ のプロパティが変更されると{"type": "Person", "id": "3"}、関心のあるすべてのクライアントに送信されます)
  • サブスクライブできるエンティティの数に実際の制限はありますか? セッション中、1 つのブラウザが何百もの と接触することがありProductます。

Spring ベースのサーバーのエンティティと JavaScript クライアントのプロキシ エンティティ (必ずしも Ember.js である必要はありません) との同期を正常に維持することが証明されているソリューションを知りたいと思っています。

4

1 に答える 1

3

すべての詳細を提供するにはブログ投稿が必要なので、概要を説明します。

必要なもの

  • Socket.ioサーバー。
  • Socket.io クライアント、またはイベントを Redis にプッシュする新しいライブラリの 1 つ。Ruby Socket.io クライアントJava Socket.io クライアント
  • すべてのサーバー側データ アイソレーターにフックして、更新の通知を受け取ります。
  • すべての Ember Data モデルのオブザーバー。

プロトコルには 2 つのオプションがあります

オプション 1: イベントのみ

ペイロード:

{
  meta: {
    type: 'NAME_OF_YOUR_MODEL'
    id:   'ID_OF_UPDATED_MODEL'
  }
}

コード:

window.socket = io()

App.ApplicationRoute = Ember.Route.extend({
  activate: function(){
    var store = this.store;

    socket.on('recordUpdated', function(payload){
      store.find(Ember.get(payload, 'meta.type'), Ember.get(payload, 'meta.id'));
    };
  }
}

App.Model = DS.Model.extend({
  lastUpdate: function(){
    var payload = {
      id: this.get('id'),
      type: this.constructor.toString()
    };

    socket.emit('recordUpdated', payload);

    this.save(); // You should save the record to get it in saved state.

    return payload;
  }.observes('isDirty') 
});

オプション 2: モデルの JSON 表現、イベントあり

ペイロード:

{
  "meta": {
    "type": "person"
    "id": "18"
  },

  "persons": [
    {"id": "18", "firstName": "Yahuda", "lastName": "Katz"}
  ]
}

コード:

window.socket = io();

App.ApplicationRoute = Ember.Route.extend({
  activate: function(){
    var store = this.store;

    socket.on('recordUpdated', function(payload){
      store.pushPayload(payload);
    };
  }
});

App.Model = DS.Model.extend({
  lastUpdate: function(){
    var payload = this.toJSON();

    socket.emit('recordUpdated', payload);

    this.save();

    return payload;
  }.observes('isDirty') 
});

ノート

Stalkableを使用すると、すべてのプロパティをより適切に観察できます。これにより、lastUpdate プロパティの一部として save を呼び出す必要もなくなります。

于 2014-06-16T21:22:10.773 に答える