Situation: After we insert the data, as long as the page is refreshed, the data will be re-inserted.
Reason: After we submit the data, the browser will keep the data requested last time! ! When the page is refreshed, the last request will be sent again, causing the resubmission problem.
Question: How to solve the resubmission problem?
Answer: The solution is to make the request not to resend the last request when resubmitting. Then we need to implement an anti-resubmission mechanism. The mechanism to implement anti-resubmission is implemented using Token (token mechanism).
So to solve this problem, first understand the implementation of the token mechanism! !
Implement an interceptor. Intercept multiple requests.
First step: Create a new interceptor
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.chu.annotation.TokenForm;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* Anti-resubmission
* @author ranger
*
*/
public class TokenInterceptor implements HandlerInterceptor {
@SuppressWarnings("unchecked")
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//The first step: If it is an increase request, we Just create a token
//Question: How to mark the requested method is an added method Woolen cloth? Identify by annotation
//The HandlerMethod object can obtain the method requesting the method to be called Information
ListtokenPool=null;
HandlerMethod hm=(HandlerMethod) handler;
TokenForm tokenForm = hm.getMethodAnnotation(TokenForm.class);
if (tokenForm!=null) {
HttpSession session = request.getSession();
//Question: If multiple functions use the same SessionToken . There will be mutual coverage
//The solution uses a collection to store the sessionToken. Divide Token into current Token (used to return to the page), Token pool
if (session.getAttribute("tokenPool")==null< span style="color: #000000;">) {
tokenPool=new ArrayList<>();
}else {
tokenPool=(List) session.getAttribute("tokenPool");
}
//As long as you enter or submit, you must leave the country with a new token Put it in the Session
String sessionToken = UUID.randomUUID().toString();
//Put the created Token in the tokenPool of the session span>
tokenPool.add(sessionToken);
//Place the created Token in a field on the conversation side Used to return to the page
session.setAttribute("sessionToken", sessionToken);
session.setAttribute("tokenPool", tokenPool);
//remove is true, which means it is a request to submit an increase< /span>
if (tokenForm.remove()) {
// Determine whether the token in the request form is the same as the Token in the session
String formToken = request.getParameter("formToken");
ListresultTokenPool = (List ) session.getAttribute("tokenPool");
boolean flag=false;
for (String token: resultTokenPool) {
if (token.equals(formToken)) {
//If you find a corresponding Token in the token pool, remove it< /span>
resultTokenPool.remove(token);
flag=true;
break;
}
}
//If the Token of the form is not in the Token pool. Just jump to the specified page
if (flag==false) {
response.sendRedirect(request.getParameter("token.invoke"));
return false;
}
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
Question: How to mark the request method is an increase Method? Identify by annotation
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The method used for the anti-resubmission sign and the anti-resubmission method
* @author ranger
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TokenForm {
//If create is true, it means a jump to increase Page request
boolean create() default false;
//If remove is true, it means it is an increase submission Request
boolean remove() default false;
}
Step 2: Add annotations to the corresponding method in the controller
Step 3: In the springmvc configuration file or configuration Class setting interceptor ok
import java. util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.chu.annotation.TokenForm;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* Anti-resubmission
* @author ranger
*
*/
public class TokenInterceptor implements HandlerInterceptor {
@SuppressWarnings("unchecked")
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//The first step: If it is an increase request, we Just create a token
//Question: How to mark the requested method is an added method Woolen cloth? Identify by annotation
//The HandlerMethod object can obtain the method requesting the method to be called Information
ListtokenPool=null;
HandlerMethod hm=(HandlerMethod) handler;
TokenForm tokenForm = hm.getMethodAnnotation(TokenForm.class);
if (tokenForm!=null) {
HttpSession session = request.getSession();
//Question: If multiple functions use the same SessionToken . There will be mutual coverage
//The solution uses a collection to store the sessionToken. Divide Token into current Token (used to return to the page), Token pool
if (session.getAttribute("tokenPool")==null< span style="color: #000000;">) {
tokenPool=new ArrayList<>();
}else {
tokenPool=(List) session.getAttribute("tokenPool");
}
//As long as you enter or submit, you must leave the country with a new token Put it in the Session
String sessionToken = UUID.randomUUID().toString();
//Put the created Token in the tokenPool of the session span>
tokenPool.add(sessionToken);
//Place the created Token in a field on the conversation side Used to return to the page
session.setAttribute("sessionToken", sessionToken);
session.setAttribute("tokenPool", tokenPool);
//remove is true, which means it is a request to submit an increase< /span>
if (tokenForm.remove()) {
// Determine whether the token in the request form is the same as the Token in the session
String formToken = request.getParameter("formToken");
ListresultTokenPool = (List ) session.getAttribute("tokenPool");
boolean flag=false;
for (String token: resultTokenPool) {
if (token.equals(formToken)) {
//If you find a corresponding Token in the token pool, remove it< /span>
resultTokenPool.remove(token);
flag=true;
break;
}
}
//If the Token of the form is not in the Token pool. Just jump to the specified page
if (flag==false) {
response.sendRedirect(request.getParameter("token.invoke"));
return false;
}
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The method used for the anti-resubmission sign and the anti-resubmission method
* @author ranger
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TokenForm {
//If create is true, it means a jump to increase Page request
boolean create() default false;
//If remove is true, it means it is an increase submission Request
boolean remove() default false;
}