在 Web 应用程序中不使用 JavaScript 或 JQuery 防止多次提交按钮单击?

Prevent Multiple Submit Button Clicks Without Using JavaScript or JQuery in Web App?

我的简单网络应用程序如下:我有一个 JSP 表单 (MyForm.JSP),它接受用户输入并将其传递到我的第一个 servlet ("/myfirstservlet")。

此 servlet 处理 SQL 将用户输入值插入到我的 Fruits table 中,然后将用户重定向到我的结果 servlet ("/results")。

我的结果 servlet 然后检查 "ADD" 参数,如果 "true"(即它等于 "success")它最终将用户重定向到我的结果 JSP( Results.JSP) 存储在路径内:WEB-INF/MyFolder/Results.jsp.

我的JSP表格(MyForm.JSP)也存放在路径里面:WEB-INF/MyFolder/MyForm.jsp

我这样做是为了防止用户通过单击“结果”JSP 页面上的刷新按钮重新提交表单,以避免多次输入之前输入的相同数据数据库。

我现在的问题是:如何防止用户在我的表单 (MyForm.JSP) 上单击提交按钮 多次 次,从而防止相同的多行使用 JavaScript 或 JQuery?

将数据输入我的数据库 WITHOUT

基本上,我想在我的服务器而不是客户端验证表单只提交了一次。

我的 JSP 表格 (MyForm.JSP):

<form action="myfirstservlet" do="POST">
   <input type="text" name="fruit"><br>
   <input type="text" name="color"><br>
   <input type="submit" value="Submit">
</form>

我的第一个 servlet ("/myfirstservlet"):

protected void doPost(...){
   String fruit = request.getParameter("fruit");
   String color = request.getParameter("color");

   String sql = "INSERT INTO fruits (fruit, color) VALUES" + "(\"" + fruit +  "\", \""  + color +  "\");";

   utilitySQL.sqlInsert(sql); // My utility class that handles sql inserts

   response.sendRedirect("results?ADD=SUCCESS");
}

我的结果 servlet ("/results"):

protected void doPost(...){

   response.setContentType("text/html");    

   if (request.getParameter("ADD").equals("SUCCESS"))
      request.getRequestDispatcher("WEB-INF/MyFolder/Results.jsp").forward(request, response);

}

我的结果JSP (Results.JSP):

<body>
<h1>Results JSP</h1>


  //Reads data from MySQL database and prints it as an Array List.

</body>

编辑: 在我的第一个 servlet 中修复了我准备好的语句:

protected void doPost(...){


       String fruit = request.getParameter("fruit");
       String color = request.getParameter("color");

       try 
        {
            String sql2 = "INSERT INTO practice (fruit, color) VALUES (?, ?);";
            Connection connect = SQLHelperClass.connectOnly();
            PreparedStatement pstmt;
            pstmt = connect.prepareStatement(sql2);
            pstmt.setString(1, fruit);
            pstmt.setString(2, color);

            pstmt.execute();

            response.sendRedirect("results?ADD=success");
        } 

        catch (SQLException e) 
        {           
            e.printStackTrace();
        }

}

如果您有一个登录用户的 ID 字段,这会更容易,因为您可以为特定用户提交的结果创建一个 table,然后再将其输入水果 [=42] =],检查用户是否已经提交了相同的数据。

从外观上看,您似乎没有任何用户标识字段,因此防止重复的一种 hacky 方法可能是使用会话。

当前正在使用您的 application/website 的用户的会话是唯一的。每个访问您 website/application 的人都会获得他们自己唯一的会话 ID。 (它们存储为 cookie)

例如:

protected void doPost(...){
   String fruit = request.getParameter("fruit");
   String color = request.getParameter("color");

   //unless you wanna complicate things, i would create a string out of the two parameters and store it into an arraylist of strings
   String value = fruit+color; 

   HttpSession session = (request.getSession()); //get session
   if(null == session.getAttribute("duplicates")){ //if session variable empty then we know that user has not submitted anything yet so we let them insert into db

     insertFruit(fruit,color); //add to db

     ArrayList<String> duplicates = new ArrayList<String>(); //create arraylist
     duplicates.add(value); //add our unique value
     session.setAttribute("duplicates", duplicates); //set as session variable

    }else{
     //here the session variable is not empty so that means the user has already submitted something so lets check the arraylist and make sure the value does not already exist

     ArrayList<String> duplicates = (ArrayList<String>) session.getAttribute("duplicates");

     if(!duplicates.contains(value)){
      //if arraylist does not contain the same value, then it's safe to add
       insertFruit(fruit,color); //add to db

      //forgot this part
      duplicates.add(value);
      session.setAttribute("duplicates", duplicates); //update the variable
     }


    }


   response.sendRedirect("results?ADD=SUCCESS");
}

public void insertFruit(String fruit, String color){

       try(Connection connect = SQLHelperClass.connectOnly()){
         PreparedStatement pst = connect.prepareStatement("INSERT INTO practice (fruit, color) VALUES (?, ?);");

        pst.setString(1, fruit);
        pst.setString(2, color);

        pst.executeUpdate();

          }catch (SQLException e) {
            e.printStackTrace();
          }

}

编辑 1:

关于不为每个servlet重复数据库操作的评论。您需要分离出逻辑。人们通常这样做的方式是为所有数据库操作创建一个单独的 class。

例如...

创建一个名为 FruitDao 的 class,在这里你保留所有与水果相关的数据库操作

public class FruitDao{

public void insertFruit(String fruit, String color){

       try(Connection connect = SQLHelperClass.connectOnly()){
         PreparedStatement pst = connect.prepareStatement("INSERT INTO practice (fruit, color) VALUES (?, ?);");

        pst.setString(1, fruit);
        pst.setString(2, color);

        pst.executeUpdate();

          }catch (SQLException e) {
            e.printStackTrace();
          }

}

要从您的 servlet 中调用它,只需执行以下操作:

protected void doPost(...){
   FruitDao fdao = new FruitDao(); // get the db class for fruits
   String fruit = request.getParameter("fruit");
   String color = request.getParameter("color");

   //unless you wanna complicate things, i would create a string out of the two parameters and store it into an arraylist of strings
   String value = fruit+color; 

   HttpSession session = (request.getSession()); //get session
   if(null == session.getAttribute("duplicates")){ //if session variable empty then we know that user has not submitted anything yet so we let them insert into db

     fdao.insertFruit(fruit,color); //add to db

     ArrayList<String> duplicates = new ArrayList<String>(); //create arraylist
     duplicates.add(value); //add our unique value
     session.setAttribute("duplicates", duplicates); //set as session variable

    }else{
     //here the session variable is not empty so that means the user has already submitted something so lets check the arraylist and make sure the value does not already exist

     ArrayList<String> duplicates = (ArrayList<String>) session.getAttribute("duplicates");

     if(!duplicates.contains(value)){
      //if arraylist does not contain the same value, then it's safe to add
        fdao.insertFruit(fruit,color); //add to db

      //forgot this part
      duplicates.add(value);
      session.setAttribute("duplicates", duplicates); //update the variable
     }


    }


   response.sendRedirect("results?ADD=SUCCESS");
}