gpt4 book ai didi

java - 在 Spring Web 中更新/通知其他用户

转载 作者:行者123 更新时间:2023-12-01 19:46:36 24 4
gpt4 key购买 nike

我有一些设计/实现问题,我无法解决它。我目前正在开发一款多人参与的文本游戏。我有点理解玩家到服务器的工作原理,我的意思是服务器将每个单独的玩家视为相同。

我正在使用 spring-boot 2、spring-web、thymeleaf、hibernate。

我实现了一个自定义的UserDetails,它在用户登录后返回。

@Entity
@Table(name = "USER")
public class User implements Serializable {

@Id
private long userId;

@Column(unique = true, nullable = false)
private String userName;

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "playerStatsId")
private PlayerStats stats;
}

public class CurrentUserDetailsService implements UserDetailsService {

@Override
public CurrentUser loadUserByUsername(String userName) {

User user = this.accountRepository.findByUserName(userName)
.orElseThrow(() ->
new UsernameNotFoundException("User details not found with the provided username: " + userName));

return new CurrentUser(user);
}
}

public class CurrentUser implements UserDetails {

private static final long serialVersionUID = 1L;
private User user = new User();

public CurrentUser(User user) {
this.user = user;
}

public PlayerStats getPlayerStats() {
return this.user.getStats();
}

// removed the rest for brevity
}

因此,在我的 Controller 中,我可以执行此操作来获取 CurrentUser*请注意,每个用户也是一名玩家。

@GetMapping("/attackpage")
public String viewAttackPage(@AuthenticationPrincipal CurrentUser currentUser) {

// return the page view for list of attacks

return "someview";
}

这里的currentUser将反射(reflect)当前用户(玩家1或2或3等等)。这对于发生在自己身上的大多数事情都很有效,例如购买一些东西、更新个人资料等等。但我无法得到或不知道如何实现的是当两个玩家互动时

例如,玩家1攻击玩家2。如果我是玩家1,我要做的就是单击 View 上的“攻击”并选择玩家2,然后提交命令。因此,在 Controller 中,它会是这样的。

@GetMapping("/attack")
public String launchAttack(@AuthenticationPrincipal CurrentUser currentUser, @RequestParam("playername") String player2) {

updatePlayerState(player2);

return "someview";
}

public void updatePlayerState(String player) {

User user = getUserByPlayername(player);
// perform some update to player state (say health, etc)
// update back to db?
}

这才是真正让我困惑的地方。如前所述,当每个用户/玩家登录时,将从数据库中提取一组用户(玩家)当前状态并将其存储在“内存中”。因此,当玩家 1 攻击玩家 2 时,

  1. 如何“通知”或更新玩家 2 统计数据已更改,因此,玩家 2 应该将更新的统计数据从数据库提取到内存。

  2. 如何解决这里可能出现的并发问题?例如,玩家 2 的生命值在 DB 中为 50。然后,玩家 2 执行一些操作(例如购买生命药水 + 30),然后更新数据库(生命值到 80)。然而,就在数据库更新之前,玩家1已经发起了攻击,并从数据库中获取了玩家2的状态,由于数据库尚未更新,因此它将返回50。因此,现在,在 getUserByPlayername() 中所做的任何更改以及对数据库的更新都将是错误的,并且 Player 的整个状态将“不同步”。我希望我在这里说得有道理。

我知道 hibernate 中有 @Version 用于乐观锁定,但我不确定它是否适用于这种情况。在这种情况下 spring-session 有用吗?

当用户登录时,我不应该在内存中存储任何数据吗?当执行某些操作时,我是否应该始终从数据库检索数据?就像 viewProfile 时一样,然后我从 accountRepository 中提取。或者当 viewStats 时,我从 statsRepository 中提取等等。

请为我指明正确的方向。对于任何具体的例子或某种视频/文章,我们将不胜感激。如果需要任何其他信息,请告诉我,我会尽力更好地解释我的案例。

谢谢。

最佳答案

我认为您不应该在 Controller 方法中更新currentUser,也不应该依赖该对象中的数据来表示玩家的当前状态。可能有多种方法可以使其发挥作用,但您需要花点时间更新安全上下文。

我还建议您通过 id 而不是 userName 查找用户,因此将使用这种方法编写此答案的其余部分。如果您坚持按用户名查找用户,请根据需要进行调整。

因此,为了简单起见,我将引用 Controller 中的 accountRepository,然后,每当您需要获取或更新玩家的状态时,请使用

User user = accountRepository.findById(currentUser.getId())

是的,@Version 和乐观锁定将有助于解决您担心的并发问题。您可以从数据库重新加载实体,并在捕获 @OptimisticLockException 时重试该操作。或者,您可能想回复玩家 1,例如“玩家 2 刚刚购买了治疗药水,现在已经 80 健康,您还想攻击吗?”

关于java - 在 Spring Web 中更新/通知其他用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53020459/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com