Repeated submission of forms: not complete once, first request the form page -> then submit the form process to complete the data submission
The root cause: not doing it in full, first request the form page -> then submit the form process.
Causes repeated submissions:
Note: After falling back, refresh the form page and submit again. At this time, instead of repeating the submission, a new request is sent. Under Firefox, the operation of repeating the submission to the same address is invalid.
Case:
@WebServlet("/trans")public class TransferServlet extends HttpServlet{ private static final long serialVersionUID = 1L; protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); PrintWriter out = resp.getWriter(); String money = req.getParameter("money"); //Simulate network delay try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Transfered out amount:"+money); out.print("Transfered out amount:"+money); }}Under the crazy point, you will find that the jsp page will not change, but you can see through the printout in the background, and it will be output continuously, indicating that it is being executed all the time
Solution:
Before submitting the guarantee, you must first request the form interface. The principle is the same as the verification code.----Token mechanism
When requesting the first time, when requesting to the form interface, create a token. When clicking on transfer and sending the request, bring this token and send it to the next interface. Verify the token in the servlet. This token is one in the session and one in the form. Equalization means that the form is correct, and the token in this session is destroyed.
Code in jsp page
<% //Create token String token = java.util.UUID.randomUUID().toString(); //One of the session exists, and then make a judgment session.setAttribute("TOKEN_IN_SESSION", token); %> <h3>Transfer interface</h3> <form action="/trans" method="post"> <input type="hidden" name="token" value="<%=token%>"/> Transfer amount:<input type="text" name="money" min="1" required /><br/> <input type="submit" value="transfer" /> </form>Code in TransferServlet
@WebServlet("/trans")public class TransferServlet extends HttpServlet{ private static final long serialVersionUID = 1L; protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); PrintWriter out = resp.getWriter(); //Get the token value in the form String token = req.getParameter("token"); //Get the token value in the session String sessionToken = (String) req.getSession().getAttribute("TOKEN_IN_SESSION"); //The token in the session is easy to be empty because the token in the session is a destructible if (token.equals(sessionToken)) { //Indicate that the token is the same req.getSession().removeAttribute("TOKEN_IN_SESSION"); String money = req.getParameter("money"); System.out.println("transfer amount:"+money); out.print("transfer amount:"+money); //Finally destroy the token in the session} //If the token is different, it means that it is a repeated submission and cannot be submitted}}Then, in order not to appear in the Java code in the jsp file, create and jump the token in another servlet
@WebServlet("/transfer")public class CopyOfTransferServlet extends HttpServlet{ private static final long serialVersionUID = 1L; protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //Create the token and jump to submit.jsp String token = UUID.randomUUID().toString(); System.out.println(token); req.getSession().setAttribute("TOKEN_IN_SESSION", token); req.setAttribute("token", token); req.getRequestDispatcher("/views/repeatsubmit/submit.jsp").forward(req, resp); }}This is what the jsp file looks like now
<h3>Transfer interface</h3> <form action="/trans" method="post"> <input type="hidden" name="token" value="${token }"/> Transfer amount:<input type="text" name="money" min="1" required /><br/> <input type="submit" value="transfer" /> </form>It's much cleaner than the above and more neat, but it still doesn't feel good, because if you need to use it in other places, you need to create tokens, verify tokens, and delete tokens, so you extract it to make a tool class
TokenUtil.java
//Token tool class//Create token//Verify token//Destroy token public class TokenUtil { private final static String TOKEN_IN_SESSION = "TOKEN_IN_SESSION"; public static void savaToken(HttpServletRequest req) { String token = UUID.randomUUID().toString(); System.out.println(token); req.getSession().setAttribute(TOKEN_IN_SESSION, token); req.setAttribute("token", token); } public static boolean validateToken(HttpServletRequest req, String tokenInrequest) { //Get the token value in the sessionString sessionToken = (String) req.getSession().getAttribute(TOKEN_IN_SESSION); if (tokenInrequest.equals(sessionToken)) { req.getSession().removeAttribute(TOKEN_IN_SESSION); return true; } return false; }}This is fine. The user only needs to call this tool class, and there is no need to write a series of operations such as creating a token.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.