如何忽略来自不耐烦用户的多次点击?

我有一个查询来回答远程客户端的标准请求。 标准,从服务器外部不占用任何参数。 每当有人向URL提交请求时,例如http://www.example.com/query ,他/她会在响应正文中获取reply.xml的内容,具体取决于数据库当时提供的内容。 reply.xml的内容仅在服务器上的数据库内容上reply.xml更改,并且不会更改任何外部内容,例如查询,输入等等,因此不会从客户端获取参数。 我甚至没有检查任何身份validation – 我们将所有内容留给防火墙。

所以我写了一个@POST方法,比如在发布到http://www.example.com/query的请求上调用query() ,并传递结果。 我使用Jersey ,所有这些都符合规格,除此之外

请求应该是跨时间的。 也就是说,应该一次提供一个请求 – 后续用户单击应该获取HTTP状态为309的消息,除非服务器没有运行我的方法query()调用的查询进程。

怎么做到这一点? 我尝试使query()服务@PUT而不是@POST响应,并得到相同的结果。

也许是关于这个主题的天真Q. 但是,不太熟悉Restful服务。

我可以通过线程化令牌来控制一次只运行一个查询并使同时请求接收HTTP 309,但是必须有更好,更简单的方法在服务器上实现这一点。

我正在使用Tomcat 8,Jersey 1.19。

TIA。

注意:我在其他一些有用的讨论中读过REST中的PUT和POST 。

// =====================

编辑:

哪个用户提交查询在任何时候都没有任何区别。

假设userA提交了一个查询。 当该查询仍在运行时,即在query()返回对userA的响应之前, userB提交了一个查询。 userB应该得到309–只是因为当时正在处理查询。

无论userA = userB还是userA userB在这里都是无关紧要的,因为当一个查询请求已经运行时,应返回309。 这就是用户获得309的唯一时间。

// ==============================================

EDIT 2:

我知道有并发控制的解决方案。 我猜测有一个使用Restfulfunction。 这是一个学术问题。

  • @Koos Gadellaa说客户端应该阻止第二个请求,直到响应到达为止。 让我解释为什么这是最好的事情。 从结构上讲 ,它涉及到问题。 服务器没有关于两个请求并行到达的原因的上下文感知。 因此,依靠带外知识来了解并行请求是不好的。 任何带外知识都会产生耦合,这意味着如果您改变系统的一部分工作方式,则必须更改另一部分。 RESTful架构很受欢迎,因为它们减少了耦合。 如果同一用户登录到两个客户端,则系统会中断。 您永远不想构建具有此类客户端 – 服务器耦合的系统。

  • 关于服务器的责任, 良好的编码实践发挥作用,最好的办法是确保服务不受用户的多个并行请求的阻碍。 缓存可能是你的朋友。 根据查询参数,可以将响应写入磁盘上的缓存文件。 客户端将始终使用HTTP 303重定向到缓存文件URL。 可以使用304 Not Modified,因此客户端不必下载两次答案。 在这种情况下, 唯一的带外知识是HTTP规范的正确实现,它具有良好的规范和健壮性。

  • 如果服务过载,则相应的响应代码似乎为503。

    10.5.4 503服务不可用

    由于服务器的临时过载或维护,服务器当前无法处理请求。 这意味着这是一个暂时的条件,经过一段时间的延迟后会得到缓解。 如果已知,延迟的长度可以在Retry-After报头中指示。 如果没有给出Retry-After,客户端应该像处理500响应一样处理响应。

      Note: The existence of the 503 status code does not imply that a server must use it when becoming overloaded. Some servers may wish to simply refuse the connection. 
  • 既然你在这里通过我的回复指示我,看起来你想知道正确的RESTful方法。 这将比上面的解决方案更复杂,我的猜测是你不想采取这条路线,但在这里。

    如果服务器需要与客户端通信正在执行请求以及何时完成请求,则需要为这些概念创建资源 。 这感觉很奇怪,因为它们存在于HTTP中,并且在更高级别(架构气味)重新实现它们很奇怪。

    1. 客户端会将RequestQuery资源POST到服务器。 此资源的Response属性为空, Status属性为空。 服务器将使用Status属性设置为“processing”的主体进行响应。
    2. 然后,客户端将对此资源执行GET(可能在此处使用长轮询)来检查更新。
    3. 创建ResponseResponse属性将链接到响应资源或嵌入响应。

    这种方法使用资源来传达正在发生的事情。 因此, 唯一的带外知识是资源的有效状态

我认为你错了。 多次单击的用户是使用前端客户端连接到服务器的用户。 因此,客户应确保不会发生多次点击。 Javascript可以完美地抵御这些请求。

话虽如此,根据您的要求:应返回309。 这是一个并发问题。
如果我正确读取您的规范,它与正在执行的数据库查询有关。 请考虑以下代码:

 result = do_database_thing(); out = make_up_result(result); return out; 

根据这些规范,唯一的要求是关键部分在do_database_thing上。 如果make_up_results很慢,则允许多个请求。 所以自然的解决方案是在数据库上使用锁定。 如果它应该包含整个query()方法(即不是数据库查询本身 ),请尽早请求锁定,最后释放锁定。 然后代码变成:

 boolean locked = get_lock(); if(!locked) return 302; result = do_database_thing(); release_lock(); out = make_up_result(result); return out;