Repeated submission of the problem in the Web development is a very common problem, mainly divided into front and back-end two ways to solve, the front-end processing generally after the submission of events, the user is forbidden to click the Submit button again, waiting for the server end result and then reset the status of the Submit button.
This article focuses on the problem of repeating submissions through Java back-end processing. The development environment is: Spring boot 2.0+react+ant+dva, which is the main process idea:
Here is the detailed step code:
1: Client login, server login successful return to initial form token
Packagecom.df.web.manager.security;Importjavax.servlet.http.HttpServletRequest;ImportJavax.servlet.http.HttpServletResponse;ImportJava.util.UUID;/*** @ class Name: * @ class Description: * @ Creator Liu Dan * @ creation Time 2018/6/23 * @ Last modified by Liu Dan. * @ Last modified on 2018/6/23. * @ Version: 1.0*/ Public classFormtokenutil { Public Staticstring Refreshformtoken (httpservletrequest request, HttpServletResponse response) {string Newformtoken=Uuid.randomuuid (). toString (); Response.setheader ("Formtoken", Newformtoken); Request.getsession (true). SetAttribute ("Formtoken", Newformtoken); returnNewformtoken; }}
2: Formtoken returned by front end fetch server
Sessionstorage.setitem ("Formtoken", ResData.result.formToken);
3: Add form token to the headers of the front-end unified request (FETCH)
return request (Serviceurl, { "POST", headers: { ' Accept ': ' Application/json ', ' content-type ': ' Application/json ', ' Formtoken ': Sessionstorage.getitem ("Formtoken" }, body:data, ' include ' });
4: Service side uses AOP technology to intercept controller requests for specified annotations
PackageCOM.DF.WEB.MANAGER.AOP;ImportCom.df.web.manager.security.FormTokenUtil;ImportCom.empiresoft.annotation.FormToken;ImportCom.empiresoft.pojo.common.ActionResultGenerator;ImportOrg.aspectj.lang.ProceedingJoinPoint;ImportOrg.aspectj.lang.annotation.Around;ImportOrg.aspectj.lang.annotation.Aspect;ImportOrg.slf4j.Logger;Importorg.slf4j.LoggerFactory;Importorg.springframework.stereotype.Component;ImportOrg.springframework.web.context.request.RequestContextHolder;Importorg.springframework.web.context.request.ServletRequestAttributes;Importjavax.servlet.http.HttpServletRequest;ImportJavax.servlet.http.HttpServletResponse;/*** @ class Name: Form repeat commit interception processing * @ Class Description: * @ Creator Liu Dan * @ created on 2018/6/23 * @ Last modified by Liu Dan. * @ Last modified on 2018/6/23. * @ Version: 1.0*/@Aspect @component Public classFormtokenaspect {Private FinalLogger Logger = Loggerfactory.getlogger ( This. GetClass ()); /*** Repeat commit validation for action on formtoken annotations * *@paramProceedingjoinpoint *@paramFormtoken *@return */@Around ("@annotation (Formtoken)") PublicObject Execute (proceedingjoinpoint proceedingjoinpoint, Formtoken formtoken) {Try{servletrequestattributes attributes=(servletrequestattributes) requestcontextholder.getrequestattributes (); HttpServletRequest Request=attributes.getrequest (); HttpServletResponse Response=Attributes.getresponse (); String Strformtoken= Request.getheader ("Formtoken"); if(Strformtoken = =NULL) { returnActionresultgenerator.errorresult ("form token cannot be empty!")); } Object Sessionformtoken= Request.getsession (true). getattribute ("Formtoken"); if(Sessionformtoken = =NULL|| !sessionformtoken.tostring (). Equals (Strformtoken)) { returnActionresultgenerator.errorresult ("Do not submit data repeatedly!")); } //ReleaseObject o =proceedingjoinpoint.proceed (); //Resets the form token and writes response resets the front-end form tokenFormtokenutil.refreshformtoken (request, response); returno; } Catch(Throwable e) {logger.error (E.getmessage ()); returnActionresultgenerator.errorresult ("An exception has occurred!")); } }}
5: Front-end monitoring response The returned data contains the form token item, if included, resets the form token for the front-end sessionstorage.
ImportFetch from ' Dva/fetch ';Import{message} from ' Antd ';function Parsejson (response) {if(Response.headers.get ("Formtoken") {Sessionstorage.setitem ("Formtoken", Response.headers.get ("Formtoken")) } returnResponse.json ();} function CheckStatus (response) {if(Response.Status >= && Response.Status < 300) { returnresponse; }}/*** Requests a URL, returning a promise. * *@param{string} URL the URL of we want to request *@param{Object} [options] The options we want to pass to "fetch" *@return{Object} An object containing either "data" or "Err "*/Exportdefaultfunction request (URL, options) {returnfetch (URL, options). Then (CheckStatus) and then (Parsejson). Then (data=({data}).Catch(ERR) = { });}
Annotation definition:
Package com.empiresoft.annotation; import java.lang.annotation.*; /** */@Documented @retention (retentionpolicy.runtime) @Target (elementtype.method) public @Interface formtoken {}
Tag requires duplicate commit validation
@FormToken = "/call_service", method = requestmethod.post) public Throws Exception { return oauthclientutil.callunifiedplatformservice (Callservice, Securityutil.getloginuser (Request), request); }
Note: If you want to allow users different forms to use different forms of token, only for the same nature of the form to repeat the validation, can be in the front and back of the token name "Formtoken" the name of the extension processing.
Java+react front and back end separation project handling Duplicate commit issues