Предотвратить несколько кликов кнопки «Отправить» без использования JavaScript или JQuery в веб-приложении? - PullRequest
0 голосов
/ 17 октября 2018

Мое простое веб-приложение выглядит следующим образом: у меня есть форма JSP (MyForm.JSP), которая принимает пользовательский ввод и передает его моему первому сервлету ("/myfirstservlet").

Этот сервлет обрабатывает вставку SQL введенных пользователем значений в мою таблицу Fruits, а затем перенаправляет пользователя в мой сервлет результатов ("/results").

Мой сервлет результатов затем проверяет параметр "ADD" и, если "true" (т. Е. Он равен "success"), он, наконец, перенаправляет пользователя в мой JSP результатов (Results.JSP), который хранится внутрипуть: WEB-INF/MyFolder/Results.jsp.

Моя форма JSP (MyForm.JSP) также хранится внутри пути: WEB-INF/MyFolder/MyForm.jsp

Я сделал так, чтобы пользователь не мог повторно отправить формунажав кнопку обновления на странице результатов JSP, чтобы избежать одновременного ввода в базу данных нескольких записей одних и тех же данных, которые были только что ранее введены.

Теперь моя проблема: как запретить пользователю нажимать на кнопкуКнопка отправки несколько раз в моей форме (MyForm.JSP), тем самым предотвращая ввод в мою базу данных нескольких строк одних и тех же данных БЕЗ с использованием JavaScript или JQuery?

В основномЯ хочу подтвердить на своем сервере, а не на стороне клиента, что форма была отправлена ​​только ОДИН РАЗ.

Моя форма 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>

Мой первый сервлет("/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");
}

Myсервлет результатов ("/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>

РЕДАКТИРОВАТЬ: Исправлено мое подготовленное состояние в моем первомсервлет:

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();
        }

}

1 Ответ

0 голосов
/ 17 октября 2018

Если бы у вас было поле идентификатора для вошедшего в систему пользователя, это было бы проще, потому что вы могли бы просто создать таблицу для результатов, отправленных конкретным пользователем, и перед тем, как вводить их в таблицу фруктов, проверьте, уже ли пользователь отправилодни и те же данные.

Судя по всему, у вас нет полей идентификации пользователя, поэтому хакерским способом предотвращения дублирования может быть использование сессий.

Сессия является уникальной для пользователя, который в данный момент использует ваше приложение / веб-сайт.Каждый человек, который посещает ваш сайт / приложение, получает свой уникальный идентификатор сессии.(они хранятся в виде файла 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:

В отношении комментария о неповторенииоперация базы данных для каждого сервлета.Вы должны выделить логику.Люди обычно делают это путем создания отдельного класса для всех ваших операций с базой данных.

Например ...

создайте класс с именем FruitDao, здесь вы храните все операции с базами данных, связанные с фруктами

открытый класс 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();
          }

}

Чтобы вызвать это из вашего сервлета, просто сделайте:

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");
}
...