我的简单Web应用程序如下:我有一个JSP表单(MyForm.JSP
),它接受用户输入并将其传递给我的第一个servlet("/myfirstservlet"
)。
此Servlet将用户输入值的SQL插入处理到我的Fruits
表中,然后将用户重定向到我的结果servlet("/results"
)。
然后,我的结果servlet检查一个"ADD"
参数,如果结果为“ true”(即等于"success"
),它将最终将用户重定向到我的Results 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>
我的第一个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();
}
}
答案 0 :(得分:1)
如果您有一个已登录用户的id字段,这会更容易,因为您可以为特定用户提交的结果创建一个表,然后在将其输入水果表之前,检查该用户是否已提交相同的数据。
从外观上看,您似乎没有任何用户标识字段,因此,防止重复的一种骇人听闻的方法可能是利用会话。
会话是当前正在使用您的应用程序/网站的用户所独有的。每个访问您的网站/应用程序的人都会获得自己的唯一会话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重复数据库操作的注释。您需要分离出逻辑。人们通常这样做的方式是为所有数据库操作创建一个单独的类。
例如...
创建一个名为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();
}
}
要从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");
}