awe*_*ome 5 java concurrency spring spring-mvc
我想知道如何确保每个会话一次只访问服务中的某些方法一次。
我将通过一个小例子来说明:
假设我们有一个用户处于状态 A (user.state = A)。这个用户向我们的 java spring 控制器发送一个 HTTP GET 请求来获取一个页面,比如 /hello。根据他的状态,他将被发送到 A 或 B。在此之前,我们将他的状态更改为 B(见下面的代码)。
现在,再次假设调用 dao.doSomething(); 需要很多时间。如果用户发送另一个 GET(例如通过刷新浏览器),他将调用完全相同的方法 dao.doSomething(),导致 2 次调用。
你怎么能避免呢?
如果您同时发送 2 个 HTTP GET 会发生什么?
如何在控制器/服务/模型/数据库中保持一致?
注意 1:这里我们不会从不同的浏览器发出 2 个 HTTP GET。我们只是在同一个浏览器上同时创建它们(我知道最大并发会话解决方案,但这并不能解决我的问题。)。
注2:解决方案不应阻塞不同用户对控制器的并发访问。
我已经阅读了一些关于服务交易的内容,但我不确定这是否是解决方案。我也阅读了一些关于并发的内容,但我仍然不明白如何在这里使用它。
我将不胜感激您的帮助!谢谢!
代码示例:
@Controller
public class UserController {
@RequestMapping(value='/hello')
public String viewHelloPage() {
// we get the user from a session attribute
if (user.getState() = A) {
user.setStatus(B);
return "pageA";
}
return "pageB";
}
@Service
public class UserService {
Dao dao;
@Override
public void setStatus(User user) {
dao.doSomething();
user.setStatus(B);
}
}
Run Code Online (Sandbox Code Playgroud)
如果dao.doSomething()您正在做的工作只想发生一次,则应该使用幂等方法,例如 PUT 或 DELETE。没有法律强制您使用正确的方法,但最坏的情况是,它是一种自我记录的方式,告诉世界应该如何使用您的 API。如果这对您来说还不够,大多数浏览器都会根据请求的类型尝试帮助您。例如,浏览器通常会使用缓存来避免多次 GET。
看来您真正想知道的是如何强制执行幂等性。这是非常特定于应用的。一种通用方法是在服务器端生成并存储一个伪唯一 ID,以便客户端附加到其请求。这样,第一个之后具有相同 id 的任何请求都可以被安全地忽略。显然,旧的 ID 应该被明智地驱逐。
正如我所说,解决方案通常是特定于应用程序的。在上面的例子中,看起来您正在尝试在两种状态之间切换,并且您的实现是服务器端切换。您可以利用客户端来确保多个请求不会出现问题。
@RequestMapping(value="/hello", method=RequestMethod.PUT)
public String test(@RequestParam("state") String state) {
dao.setState(user, state)
switch (state) {
case "A":
return "B";
case "B":
return "A";
default:
return "error";
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3433 次 |
| 最近记录: |