Java 防止REST客户端同时执行具有相同参数的相同方法

Java 防止REST客户端同时执行具有相同参数的相同方法,java,spring,rest,api,spring-mvc,Java,Spring,Rest,Api,Spring Mvc,考虑springmvcjavaweb应用程序,它提供了一些restapi 假设它有很多方法,其中一个是DELETE/api/foo/{id},它显然使用给定的id从数据库中删除foo实体 问题是,由于数据库中的大数据,此操作不是即时的,所以如果客户机尝试在同一实体上同时执行乘法删除操作,例如 DELETE/api/foo/123xn次(当然是客户端软件中的错误) 它会在数据库中引起一些不愉快的副作用(您知道,如果您尝试在多个事务中删除同一个实体,这通常是不好的) 我的问题是:springmvc中

考虑
springmvc
javaweb应用程序,它提供了一些
restapi

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

问题是,由于数据库中的大数据,此操作不是即时的,所以如果客户机尝试在同一实体上同时执行乘法删除操作,例如

DELETE/api/foo/123
xn次(当然是客户端软件中的错误)

它会在数据库中引起一些不愉快的副作用(您知道,如果您尝试在多个事务中删除同一个实体,这通常是不好的)

我的问题是:
springmvc
中防止这种情况的最佳实践是什么

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


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

这是一个并发问题,应该通过使用适当的事务和锁定级别来处理。不幸的是,这里没有适合所有情况的单一大小,根据您的实际需求,您可能必须实现乐观或悲观锁定,以及可能的事务级别(从根本没有事务到可序列化事务)

一般来说,在web级别处理此类问题是一个糟糕的主意,因为您会遇到这样的问题,例如在请求时如何处理?是否要删除另一个同时显示的某些数据?在SpringMVC中,常见的方法是在服务层中使用事务方法。另外,您应该在持久层中声明乐观或悲观锁定系统


乐观层通常提供更高的吞吐量,代价是某些事务以异常结束。在这种情况下,当前的最佳做法是向用户报告问题,要求他/她再次发送请求。

原则上,事务处理机制就是为此而设计的。还有什么要求,你认为事务回滚在DB中是不愉快的副作用吗?是的,问题是不同的DBS对这种事件有不同的行为。在我的例子中,由于复杂的复制结构,我遇到了某种阻塞。我通常不想捕捉和接收来自DB的任何类型的异常,我想阻止它们出现。我是对的还是错的。据我所知,我不知道我们可以做一件事,只需检查数据库中的数据是否可用,是否与getFooById(id)类似;如果你得到的数据比你可以删除相同的数据,否则你可以抛出一个例外,即数据不存在。问题是,这种方法没有解决我目前的麻烦。在重载数据库中删除同一原始数据的多个请求会导致某种阻塞,因此所有这些多个请求都会失败,并出现504超时错误。当然,所有删除方法本身都是在事务级别执行的。但它不包括数据库本身行为不正确的情况。504删除请求上的超时错误通常是无法获得(悲观)锁的症状。但是,这是优化数据库访问的一个困难部分,并且在很大程度上取决于数据库本身和主要用例。对不起,恐怕我不能再说太多了。也许您可以尝试用乐观锁替换悲观锁,以交换504超时错误,并发送消息,如系统正忙,无法完成您的请求,请重试..这不合适。正如我在问题中所写的,直接的方法是在特定实体的ID上引入同步。这将简单地防止DB被锁定,因此对于超时异常不会有任何麻烦-顺序执行的DELETE方法将很快返回OK,因为在我的API中删除不存在的实体是合法的操作。我的问题是:是否可以使用Spring MVC框架的现有功能在更高级别上执行相同的操作。@Andremoniy:除了Spring级别的事务之外,我不知道还有什么。在网络层面,没有比拦截器更好的了。。。