Spring MVC - 在 ajax 个请求之间保持对象状态
Spring MVC - Keeping object state between ajax requests
SpringMVC 4.1
你好,
我有一种情况,在一个页面上有几个输入字段。当用户在这些字段中输入数字时,将进行一系列计算并更新页面上的各种其他字段。
我希望整个计算模型发生在服务器端的 Java 中。我真的想避免在客户端的 Java 脚本中复制此逻辑。
我设想的是...
- 用户打开页面,创建执行计算的对象(我们称其为计算器)并设置其初始状态(其许多字段已预先填充值)。
- 此计算器实例会在用户浏览该页面期间存储并可用。
- 每当用户更改输入字段中的值时,新值都会通过 ajax 发送到服务器并插入到我们的计算器对象中。计算器根据新状态重新计算其他字段,并将结果 returns 发送到页面。
- 页面上的其他字段相应更新。
这里的关键是我没有在每个 ajax 请求中发送所有字段的状态。我只发送已更新的当前值。本质上,我试图确保后端的表单状态和计算器状态始终同步。
我查看了@SessionAttributes 和@ModelAttribute。
@ModelAttribute 的问题,据我所知,它会随着每个 ajax 请求重新创建。
@SessionAttributes 的问题在于它是一个会话变量。如果用户打开其中两个 windows 怎么办?当他们离开页面时,我如何确保对象从会话中删除?等...
也许没有魔法 Spring 子弹,我只需要弄清楚会话变量的事情。但是任何关于处理这个问题的建议都将不胜感激。
谢谢!
您有两个选择:
.1。就像您所说的使用 @SessionAttributes
,但是是的,它会遇到您提到的问题,同一会话的多个实例将看到相同的变量。
.2。将状态存储在其他地方并使用 @ModelAttribute
注释方法重新水化状态。我个人更喜欢这种方法,基本上当您创建表单时,使用当前状态的标识符创建它:
@RequestMapping(params = "form")
public String createForm(Model uiModel) {
uiModel.addAttribute("calculationId", UUID.randomUUID().toString());
return "calculationpage/create";
}
然后对于后续的 ajax 请求,确保您之前的 calculationId 被发送到:
@ModelAttribute("calculationState")
public CalculationState rehydrateState(String calculationId) {
//retrieve current state of calculation from some persistent store..
}
@RequestMapping("/calculate")
public String handleCalculation(@ModelAttribute("calculationState") CalculationState c) {
//you will get a calculationstate with the delta's at this point..
}
.3.另一种可能的方法可能是使用会话,但使用自定义 ID 消除会话中不同实例的歧义:
public String handleCalculation(HttpSession session, @RequestParam("calcId") String calcId) {
CalculationState calcState = (CalculationState) session.getAttribute("calculation" + calcId);
}
您需要任何类型的会话外部持久存储来存储和检索计算器模型的状态。就像Biju说的那样,我会选择像No 2这样的解决方案。
SpringMVC 4.1
你好, 我有一种情况,在一个页面上有几个输入字段。当用户在这些字段中输入数字时,将进行一系列计算并更新页面上的各种其他字段。 我希望整个计算模型发生在服务器端的 Java 中。我真的想避免在客户端的 Java 脚本中复制此逻辑。
我设想的是...
- 用户打开页面,创建执行计算的对象(我们称其为计算器)并设置其初始状态(其许多字段已预先填充值)。
- 此计算器实例会在用户浏览该页面期间存储并可用。
- 每当用户更改输入字段中的值时,新值都会通过 ajax 发送到服务器并插入到我们的计算器对象中。计算器根据新状态重新计算其他字段,并将结果 returns 发送到页面。
- 页面上的其他字段相应更新。
这里的关键是我没有在每个 ajax 请求中发送所有字段的状态。我只发送已更新的当前值。本质上,我试图确保后端的表单状态和计算器状态始终同步。
我查看了@SessionAttributes 和@ModelAttribute。
@ModelAttribute 的问题,据我所知,它会随着每个 ajax 请求重新创建。
@SessionAttributes 的问题在于它是一个会话变量。如果用户打开其中两个 windows 怎么办?当他们离开页面时,我如何确保对象从会话中删除?等...
也许没有魔法 Spring 子弹,我只需要弄清楚会话变量的事情。但是任何关于处理这个问题的建议都将不胜感激。
谢谢!
您有两个选择:
.1。就像您所说的使用 @SessionAttributes
,但是是的,它会遇到您提到的问题,同一会话的多个实例将看到相同的变量。
.2。将状态存储在其他地方并使用 @ModelAttribute
注释方法重新水化状态。我个人更喜欢这种方法,基本上当您创建表单时,使用当前状态的标识符创建它:
@RequestMapping(params = "form")
public String createForm(Model uiModel) {
uiModel.addAttribute("calculationId", UUID.randomUUID().toString());
return "calculationpage/create";
}
然后对于后续的 ajax 请求,确保您之前的 calculationId 被发送到:
@ModelAttribute("calculationState")
public CalculationState rehydrateState(String calculationId) {
//retrieve current state of calculation from some persistent store..
}
@RequestMapping("/calculate")
public String handleCalculation(@ModelAttribute("calculationState") CalculationState c) {
//you will get a calculationstate with the delta's at this point..
}
.3.另一种可能的方法可能是使用会话,但使用自定义 ID 消除会话中不同实例的歧义:
public String handleCalculation(HttpSession session, @RequestParam("calcId") String calcId) {
CalculationState calcState = (CalculationState) session.getAttribute("calculation" + calcId);
}
您需要任何类型的会话外部持久存储来存储和检索计算器模型的状态。就像Biju说的那样,我会选择像No 2这样的解决方案。