防止REST客户

问题描述:

考虑Spring MVC的Java Web应用程序,它提供了一些REST API防止REST客户

假设它有很多方法,其中之一是DELETE /api/foo/{id},它显然从数据库中删除foo实体,给定的id

的问题是,由于DB大数据,这个操作不是即时的,因此,如果客户端尝试同时执行多重删除同一实体操作,说

DELETE /api/foo/123 X N次(错误地在客户端软件当然),

,它引起了一些DB令人不快的副作用(你知道,如果你尝试在几个交易删除同一实体,这不是一般的好看)。

我的问题是:什么是Spring MVC的最佳实践,以防止这样的情况呢?

我当然可以在每个这样的更新方法(PUT/DELETE)中引入Foo id的同步。我将需要为所有实体和所有PUT/DELETE API方法做到这一点,但我真的不想这样做。我想这应该是一些优雅而又不错的解决方案,如何在拦截器/ servlet级别上执行这种类型的同步,即不在控制器级别的服务上。

我还可以创建特定的拦截器,并执行那里等着重复请求(有相同的URL和参数请求)。但是,这听起来并不是一个优雅的解决方案(直到我将确保无法以更美观的方式在Spring MVC中进行配置)。

+1

原则上,交易机制是为此目的而设计的。你有什么进一步的要求,你认为事务回滚为DB **中令人不快的副作用? –

+0

是的,问题是不同的数据库对于这种事件有不同的行为。在我的情况下,由于复杂的复制结构,我得到了某种阻塞。我通常不想从数据库中接收和接收任何类似的例外情况,我想阻止他们的出现。 – Andremoniy

+0

我对或错。我不知道根据我的知识,我们可以做一件事情,只是检查数据可用的数据库或不像getFooById(ID);如果你得到的数据比你可以删除相同的数据,否则你可以抛出异常,数据不存在 –

这是一个并发问题,应通过使用适当的事务和锁定级别来处理。不幸的是,在这里没有单一的规模,根据你的实际需求,你可能必须实现乐观或悲观的锁定,以及可能的事务级别之一(从没有事务到可串行化事务)。

一般情况下,在网络层面处理这种问题是一个糟糕的主意,因为你会喜欢什么就做要求的提问要删除一些数据,另一种是在同一时间显示?在SpringMVC中,常用的方法是在服务层使用事务方法。另外,您应该在持久层中声明一个乐观或悲观的锁定系统。

乐观层通常给出更高的吞吐量,在异常终止某些交易的成本。在这种情况下,目前的最佳做法是向用户报告问题,要求他/她再次发送他/她的请求。

+0

这种方法并没有涵盖我目前的麻烦。在重负载的数据库中,几个多重请求的相同原始的DELETE会导致一种阻塞,所以所有这些多个请求都会失败,并发生504超时错误。当然,所有删除方法本身都是在事务级别执行的。但它不包括DB本身行为不正确的情况。 – Andremoniy

+0

504删除请求上的超时错误通常是无法获得(悲观)锁定的症状。但是,这是优化数据库访问的难点,它很大程度上取决于数据库本身和主要用例。我很抱歉,但我恐怕不能多说了。也许你可以尝试用乐观的方式替换悲观锁,以便像*系统忙,无法完成请求,请重试504超时错误,请再试一次。* –

+0

这不合适。正如我在我的问题中所写的,直接的方式是在特定实体的ID上引入同步。这将简单地阻止DB被锁定,所以它不会有任何超时异常的麻烦 - 顺序执行的DELETE方法将很快返回OK,因为删除我的API中的缺席实体是合法操作。我的问题是:是否有可能使用Spring MVC框架的现有功能在更高层次上执行相同的技巧。 – Andremoniy