【问题标题】: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 显示这些数据。

我该怎么做?

【问题讨论】:

    标签: java html jsp servlets post-redirect-get


    【解决方案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 范围内的数据。
      猜你喜欢
      • 1970-01-01
      • 2013-08-15
      • 2012-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多