0

在服务器端,我使用 Spring 4。在浏览器端,我使用 Ember.js。

我的应用程序具有实体类,例如PersonProduct。这些实体在服务器和浏览器上都使用,并且建模相同。例如:

//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")
});

我需要在服务器和浏览器之间保持实体同步。因此,例如,当服务器端aPersonfirstName属性发生变化时,该变化应实时推送到所有感兴趣的浏览器。

我调查了Spring 的 WebSocket 支持,在熟悉了Spring 的“Hello WebSocket”示例之后,我确信使用这项技术是满足我需求的正确方法。

由于 WebSocket/STOMP 非常低级,我正在寻找一种基于该技术的解决方案,并在浏览器(这里的实体角色是观察者)和服务器(实体的角色)之间提供类似于观察者模式的行为这里将是主题/可观察的)。

由于我找不到这个“保持实体同步”挑战的现有解决方案(既不是 Spring 中的解决方案,也不是某些第三方库),我想构建自己的解决方案,但设计已经提出了有趣的问题, 如:

  • 协议应该是什么样的?一旦发生变化,服务器是否应该发送一个最小的帧,只包括实体类型和它的 ID?(例如,一旦PersonID 为“3”的任何属性发生更改,然后发送{"type": "Person", "id": "3"}给所有感兴趣的客户)
  • 可以订阅的实体数量是否存在现实限制?在一个会话期间,单个浏览器可能会接触到数百个Products。

我有兴趣了解哪些解决方案已被证明可以成功地使基于 Spring 的服务器的实体与 JavaScript 客户端的代理实体(不一定是 Ember.js)保持同步。

4

1 回答 1

3

我将为您提供一个高级别的概述,因为提供所有详细信息需要一篇博文。

你需要什么

您有两个协议选项

选项一:只有事件

有效载荷:

{
  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') 
});

选项二:模型的 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更好地观察所有属性。这也消除了调用 save 作为 lastUpdate 属性的一部分的需要。

于 2014-06-16T21:22:10.773 回答