刷新时如何防止重复条目?

Posted

技术标签:

【中文标题】刷新时如何防止重复条目?【英文标题】:How to prevent duplicate entries while refreshing? 【发布时间】:2012-09-25 07:51:30 【问题描述】:

我有一个 index.jsp 页面,我有一个表单,用户可以在其中输入一些数据,这些数据使用 Controller servlet 存储在数据库中。

在数据库中输入数据后,我想显示与该表单相同的页面 (index.jsp)。另外,我想显示用户在数据库中输入的所有条目。

我尝试使用RequestDispatcherforward() 方法。它工作正常(这意味着我能够再次显示相同的表单,并且还可以显示该用户使用 JSTL 在表单下方输入的所有数据)。

但问题是每当用户按下Refresh or F5 按钮时,所有以前的数据也会输入到数据库中,当我显示所有数据时,也会出现重复的条目。

我曾想过使用 POST-REDIRECT-GET 模式,但问题是当我重定向时,我无法使用 JSTL 显示这些数据。

我该怎么做?

【问题讨论】:

【参考方案1】:

我会在页面中添加一个不可见的 ID。如果数据是数据库中的新数据(ID = 未知),则插入并创建一个 ID 并使用该 ID 更新页面。这样您就知道它是否是 ID != 未知,并且您不必进行插入。如果数据没有改变,你甚至不必进行更新......

【讨论】:

恐怕我对 servlet 没有经验。我写的是一个典型的场景,我使用普通的旧 Java 和数据库。我想你可以采用这种方法。我无法确定的是 servlet 技术是否有一些内置功能可以为您执行此操作。 Fildor 的建议就是这样做的方法。在隐藏字段中包含页面中记录的数据库 ID。如果用户还没有提交数据,这应该是 -1 或 0。当您处理插入数据的请求时,获取新插入行的数据库 ID,并将其包含在下次页面中。如果用户再次提交表单,则使用 ID 更新详细信息,这是他们所期望的。顺便说一句,在您的表单中使用 POST 而不是 GET - 然后会提醒用户,如果他们刷新数据将被重新提交。【参考方案2】:

我认为 PRGP(Post Redirect Get Pattern)是解决这个问题的方法。如果您使用的是 Spring Web Flow,它有一个 FlashScope,您可以在其中放置要在 Post-get-redirection 之后保留的数据。使用这种方法,您可以保留的不仅仅是编辑 ID。

【讨论】:

【参考方案3】:

我曾想过使用 POST-REDIRECT-GET 模式,但问题是当我重定向时,我无法使用 JSTL 显示这些数据。

只需发送一个请求参数即可识别您希望在新 GET 请求中显示的信息。

// ...
Long id = dataService.save(data);
// ...
response.sendRedirect(request.getContextPath() + "/index?editId=" + id);

然后在servlet 中映射到/index 的URL 模式

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    Long editId = Long.valueOf(request.getParameter("editId")); // Handle nullcheck yourself.
    Data editData = dataService.find(editId);
    request.setAttribute("editData", editData); // For the edit form.
    List<Data> allData = dataService.list();
    request.setAttribute("allData", allData); // For the table/list of all data.
    request.getRequestDispatcher("/index.jsp").forward(request, response);

【讨论】:

谢谢 Balus,我认为这是一个很好的解决方案,我一定会尝试并让您知道。【参考方案4】:

这是最简单的解决方案

<%@page import="java.util.*"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%!
//This List is just for demonstration purposes
List<String> names = new ArrayList<String>();
%>
<%
if(request.getParameter("name")!=null )
    names.add(request.getParameter("name"));
    session.setAttribute("nameList", names);
    //Here you put your database insert code

    //Whenever the code execution reaches this line , 
    //then it means that you have a new page submission
    //and not a refresh or f5 case

    response.sendRedirect("index.jsp");

%>

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <form action="index.jsp" method="post">
            <input type="text" id="name" name="name"/>
        </form>
        <p>
            <table>
                <c:forEach items="$nameList" var="element">    
                    <tr>
                        <td>Name:  <c:out value="$element"/> </td>
                    </tr>
                </c:forEach>
            </table>
        </p>
    </body>
</html>

诀窍在于response.sendRedirect("index.jsp");。这使得null 成为所有请求参数。如果f5refresh 被命中,则if 永远不会被执行。如果是正常提交​​,则执行if,然后调用response.sendRedirect("index.jsp");

总之,您真正需要做的就是:

1) 检查if(request.getParameter("name")!=null )

2) 如果以上为真,则进行数据库插入

3) 如果以上为真则response.sendRedirect("index.jsp");

更新

if(request.getParameter("name")!=null )
    DbUtility.addNameToDb(request.getParameter("name"));
    ArrayList<String> currentList = DbUtility.getAllNamesFromDb();
    session.setAttribute("nameList", currentList);
    response.sendRedirect("index.jsp");

您只需要实现这两种方法。 addNameToDb(String) 将使insert 在您的数据库中。 getAllNamesFromDb() 将返回一个 ArrayList&lt;String&gt; 对象,该对象将代表您数据库中的条目。 (并且您不再需要我之前在第一个答案中介绍的names 列表)

【讨论】:

您好,感谢您的回复,但我也想在数据库中添加条目。我想要做的是假设我使用数据库中的表单创建了 1 个条目,然后我的所有条目(假设名称是主键)应该显示在我使用的相同表单下方。它现在显示正常,但是当我点击刷新时,我也发现了重复的条目。 我会尝试,但我不想使用session 范围来存储我需要在request 范围内的数据。

以上是关于刷新时如何防止重复条目?的主要内容,如果未能解决你的问题,请参考以下文章

如何在表单提交时防止表单在刷新时重新提交

Apollo 似乎刷新了,当 state 映射到 props 时,我该如何防止呢?

PHP避免刷新页面重复提交

php如何避免刷新页面重复提交

如何防止表单的重复提交

【delphi】动态刷新listview,如果条目过多,会出问题,求解