java - 在基于 Spring MVC 的 Web 应用程序中,如何判断用户是否提交了具有更改值的表单?

标签 java forms spring-mvc

在 Spring MVC webapp 中,我有一个表单和一个相应的 Controller 。在 Controller 中,我需要知道用户是否更改了表单中的任何值,以便我知道是否更新数据库中状态表中的“changed_on”列。

我不想知道哪个字段发生了变化,无论如何我都会保存用户的数据。但是,如果用户在提交之前更改了 A->B,然后又回到了 A,我不想将其视为更改。我只想在用户实际更改数据时更新日期/时间列,因为稍后我需要知道用户最后一次更改数据的时间。

实现此目标的最佳方法是什么?在后端还是在前端更好?这似乎是一个非常的普遍问题:如何判断用户是否正在更改表单上的数据。

我想出了一些可能的解决方案。我的表单字段是 boolean 值、整数、字符串和枚举。

前端解决方案

  1. 使用 Javascript 中的 onChangeonBlur 监听器设置隐藏的表单字段。
  2. 使用 jQuery callback function使用 $("form :input").change(),并使用 .data()changed 值设置为

后端解决方案

  1. 在 Web 表单绑定(bind)的表单类中(通过我的 Controller 中的 @InitBinder("formName")),覆盖基于 hashCode()在我有兴趣监控变化的所有领域。因为我没有在任何集合中使用我的表单类,也没有传递给 Hibernate,所以我不认为这有任何不良副作用。下面是一个使用 Guava 的实现:

    @Override
    public int hashCode() {
        return Objects.hashCode(this.field1, this.field2, etc.);
    }
    

    然后我可以将旧表单对象(在 get() 方法中创建)与 WebDataBinder 根据提交的表单值创建的新表单对象进行比较。如果哈希值不同,则说明用户更改了某些内容。

    我对这种方法的问题是,如何保留旧的表单对象?有没有一种方法可以将它填充到页面的 ModelAndView 中,从而从 GET 到 POST 中继续存在?或者我可以通过重新加载基于数据库的持久实体,在我的 doPost() 方法中重新创建它吗?如果 Hibernate 缓存了我的实体,那么在保留任何新更改之前重新创建原始表单对象应该会非常快。

  2. 与 #1 类似,但使用反射而不是对各个字段的硬编码依赖。这样,如果添加了任何新的表单字段,我们就不会忘记将它们添加到 hashCode() 方法中。这是一个实现:

    public static boolean hasFormChanged(Object form1, Object form2) {
        return HashCodeBuilder.reflectionHashCode(form1) != HashCodeBuilder.reflectionHashCode(form2);
    }
    

    现在,我知道反射很慢;在我的测试中,比上面的 Objects.hashCode() 方法慢大约 8-12 倍。但是,我只有 ~4 个表单字段,并且在我的本地计算机上进行的测试中,基于反射的方法每次调用大约需要 3.5 微秒。反射的另一个缺点是我们需要注意向表单类(或其父类)添加任何我们不想想要包含的新实例变量比较。

最佳答案

对于前端解决方案,您可以实现更通用的示例,可以应用于任何页面。在页面加载时,遍历 form 元素,然后遍历表单的每个字段并保存其名称和值

例如,

["form1", {field1: "value1"}, {field2 : "value2"}]

在提交之前,您可以检查新表单值是否等于旧表单值,并添加额外的属性“已更改”

每个前端解决方案都很丑陋。当然最好在服务器端制作它

你可以将旧对象存储在httpSession中,或者你可以第二次请求它(注意hibernate默认不使用缓存)。使用 hashCode 而不是 equals 有什么意义?当不同的对象返回相同的 hashCode 时,有很小的冲突可能性

最直接的方法 - 第二次从 Db 请求您的对象,并使用 equals 比较它们

关于java - 在基于 Spring MVC 的 Web 应用程序中,如何判断用户是否提交了具有更改值的表单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10400418/

相关文章:

java - 如何为 Android 制作 Wake On Lan?

java - 如何从方法的中间获取元素到 ArrayList

java - HTML 5 输入类型提交不会作为参数传递给 Controller

css - 如何将复选框和选项保留在 1 行上

jquery - Spring mvc 3 在 url 中的 "#"之后附加内容?例如www.example.com/example#ui-tabs-4

java - Android 中的 HTTP 获取和发布

java - 只有当物体进入范围时才触发接近检测器,而不是当他在范围内移动时

php - Bootstrap 表单使用 AJAX 和 PHP 添加新记录

java - Spring MVC 将请求参数绑定(bind)到 POJO 字段

java - 如何将动态列数据导出到excel