![](/img/trans.png)
[英]Status messages on the Spring MVC-based site (annotation controller)
[英]How to tell if user is submitting a form with changed values, in a Spring MVC-based webapp?
在Spring MVC Web应用程序中,我有一个表单和一个相应的控制器。 在控制器中,我需要知道用户是否更改了表单中的任何值,以便知道是否要更新数据库状态表中的“ changed_on”列。
我不在乎知道哪个字段发生了更改,无论如何我都会保存用户的数据。 但是,如果用户在提交之前先将A-> B更改为A,然后又返回A,则我不想考虑该更改。 我只想在用户实际更改数据时更新日期/时间列,因为稍后需要知道用户最后一次更改数据的时间。
实现此目标的最佳方法是什么? 最好在后端还是在前端? 这似乎是一个非常普遍的问题:如何判断用户是否正在更改表单上的数据。
我已经提出了一些潜在的解决方案。 我的表单字段是布尔值,整数,字符串和枚举。
onChange
或onBlur
侦听器设置隐藏的表单字段。 $("form :input").change()
的jQuery 回调函数 ,并使用.data()
将changed
值设置为true
。 在Web表单绑定到的表单类中(通过我的控制器中的@InitBinder("formName")
),基于我想监视更改的所有字段来覆盖hashCode()
。 因为我没有在任何集合中使用表单类,也没有将其传递给Hibernate,所以我没有想到这样做会有任何不良影响。 这是一个使用Guava的实现:
@Override public int hashCode() { return Objects.hashCode(this.field1, this.field2, etc.); }
然后,我可以将旧的表单对象(在get()
方法中创建)与WebDataBinder
从提交的表单值创建的新表单对象进行比较。 如果哈希值不同,则用户更改了某些内容。
我使用这种方法的问题是,如何保留旧的表单对象? 有没有一种方法可以将其填充到页面的ModelAndView
,该方法可以从GET到POST生存下来? 还是可以通过重载基于db的持久实体,在doPost()
方法中重新创建它? 如果Hibernate缓存了我的实体,那么在持久保存任何新更改之前重新创建原始表单对象应该很快。
与#1类似,但是使用反射而不是对各个字段进行硬编码。 这样,如果添加了任何新的表单字段,我们就不会忘记将它们添加到hashCode()
方法中。 这是一个实现:
public static boolean hasFormChanged(Object form1, Object form2) { return HashCodeBuilder.reflectionHashCode(form1) != HashCodeBuilder.reflectionHashCode(form2); }
现在,我知道反射很慢。 在我的测试中,比上面的Objects.hashCode()
方法慢大约8-12倍。 但是,我只有大约4个表单字段,在本地计算机上的测试中,基于反射的方法每次调用大约需要3.5 微秒 。 反射的另一个缺点是,我们需要要留神添加任何新的实例变量到窗体类(或它的父类(ES))的,我们不希望在比较中包括。
对于前端解决方案,您可以实现更通用的示例,该示例可以应用于任何页面。 在页面加载时,遍历form
元素,然后遍历表单的每个字段并保存其名称和值
例如,
["form1", {field1: "value1"}, {field2 : "value2"}]
等
在提交之前,您可以检查新表单值是否等于旧表单值,并添加其他属性“已更改”
每个前端解决方案都很难看。 当然最好在服务器端进行
您可以将旧对象存储在httpSession中,也可以第二次请求它(注意,休眠状态默认情况下不使用缓存)。 使用hashCode
而不是equals
什么意义? 当不相同的对象返回相同的hashCode时,发生碰撞的可能性很小
最直接的方法-再次从Db请求您的对象,并使用equals比较它们
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.