1

我有一个带有 Java 和 Hibernate 的 Rest 后端,并且我使用带有 version 属性的 Optimistic Locking。对于并发控制,此版本属性必须通过 post 请求发送到客户端并再次发送到服务器。但是,在 javascript 客户端中,我无法控制此属性的完整性,例如:

  • 客户端“A”请求资源 1。
  • 客户端“B”请求相同的资源。
  • 服务器以资源 1 版本 1 响应两个客户端(在它们各自的响应中)
  • 客户端“A”修改资源并发布帖子以保存更改。
  • 服务器处理 post 请求,Hibernate 检查版本号。1 = 1,因此资源被修改。
  • 客户端 B 使用 javascript 并将 version 属性修改为 2 并发出 post 请求。服务器处理 post 请求,现在 2 = 2,因此资源被修改,客户端 A 所做的更改丢失。

请记住,这是一个 Rest 后端,因此我无法在服务器中保存交付给每个用户的对象的版本号,或者类似的东西。

所以,如果这是一个我认为的有效问题,我如何确保版本在客户端中保持不变?

4

2 回答 2

1

就个人而言,我会重新考虑这样做,因为我几乎没有看到客户端这样做的动机,并且根据定义,您无法控制客户端向您的 REST 服务发送的内容。

但是,如果您确实有业务案例,那么一个半解决方案是将版本属性设置为 GUID。这样,您只能在您拥有最新的 GUID 时提交,而客户端 B 没有该 GUID,这会使版本控制情况变得更加复杂,因为在请求成功之前您不能只增加 1。

但是,即使在那里你也不是完全安全的,因为理论上客户端 B 可以单独请求从资源中获取更新的 GUID,然后使用更新的 GUID 重新提交失败的请求。

但是由于客户 B 可以对更新版本进行编辑以恢复客户 A 所做的并添加他们自己的,这基本上与这样做是相同的,并且由于他们有权这样做,我们又要问自己为什么我们又开始担心那个案子了。

于 2015-04-30T17:31:20.647 回答
0

使用将数字隐藏在只读 getter 后面的构造函数:

var MyObject = function(version) {
    var _version = version;

    this.getVersion = function() { return _version; }
}

或者,使用允许变量仅设置一次的 getter 和 setter 对:

var MyObject = function() {
    var self = this;

    var _tripwire = false;

    var _value = null;

    self.setValue = function(val) {
        if (_tripwire==false)
            _tripwire = true;
        else
            throw "Value is read-only";

        _value = val;
    };

    self.getValue = function() {
        return val;
    }
};

JSFiddle

根据您希望它如何失败,您可以将 throw 语句替换为静默吃掉属性集的 return,但是对于 API 代码,当调用者做了一些非常不安全的事情时,最好大声而自豪地死去。

请注意,如果您更喜欢属性样式的访问方法,您也可以使用属性访问器完成相同的设计模式:

function setOnceProp(o, name) {
    var _value = null;

    var _tripwire = false;

    Object.defineProperty(o, name, {
        get: function() { 
            return _value; 
        },
        set: function(newValue) { 
            if (_tripwire==false)
                _tripwire = true;
            else
                throw "Value is read-only";

            _value = newValue; 
        },
        enumerable: true  
    });    
}

var MyObject = function() {
    var self = this;

    setOnceProp(self, 'value');    
};

这确实要求您的客户使用相对较新的浏览器。

于 2015-04-30T17:23:59.733 回答