handlerinterceptoradapter 获取请求参数_SSM框架防止重复请求
生活随笔
收集整理的這篇文章主要介紹了
handlerinterceptoradapter 获取请求参数_SSM框架防止重复请求
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
SSM框架防止重復請求
編者: wRitchie(吳理琪) 來源:http://www.bj9420.com
SSM框架,即Spring+Spring MVC+Mybatis,在實踐中由于網絡延遲或多次點擊提交等原因產生一個請求發送多次的情況,實際上,第一個請求才是客戶端發送的,后面的請求對客戶端并無意義。比如,客戶端發送了三次保存的請求,實際上,客戶端只想保存一條記錄,而服務端卻保存了三條,這導致重復數據,并且這些數據會對系統造成不必要的影響。另一種典型場景,用戶提現,如重復提交,會導致多次提現,會帶來巨大的經濟損失,為了防止此類情況發生,需解決重復提交表單,解決方式思路,驗證同一個URL及數據參數是否相同,如相同,則重復提交,否則,正常提交。
SSM框架后端解決
1、 自定義防止重復的注解
1. package?com.bj9420.framework.interceptor;??2. ??3. import?java.lang.annotation.ElementType;??4. import?java.lang.annotation.Retention;??5. import?java.lang.annotation.RetentionPolicy;??6. import?java.lang.annotation.Target;??7. ??8. /**?9. ?*?@author?:wRitchie?10. ?*?@Description?:自定義防止重復的注解?11. ?*?@Title?:PreventRepeat.java?12. ?*?@date?2020/12/7?13:45?13. ?*?@Version?:V1.0?14. ?*?@Copyright?(c):http://www.bj9420.com?2020?All?rights?reserved.?15. ?*/??16. @Target(ElementType.METHOD)??17. @Retention(RetentionPolicy.RUNTIME)??18. public?@interface?PreventRepeat?{??19. }??2、 自定義攔截器
1. package?com.bj9420.framework.interceptor;??2. ??3. import?com.fasterxml.jackson.databind.ObjectMapper;??4. import?lombok.extern.slf4j.Slf4j;??5. import?org.springframework.web.method.HandlerMethod;??6. import?org.springframework.web.servlet.handler.HandlerInterceptorAdapter;??7. ??8. import?javax.servlet.http.HttpServletRequest;??9. import?javax.servlet.http.HttpServletResponse;??10. import?java.lang.reflect.Method;??11. import?java.util.HashMap;??12. import?java.util.Map;??13. ??14. /**?15. ?*?@author?:wRitchie?16. ?*?@Description?:相同url和數據攔截器?為了防止重復提交等操作?17. ?*?繼承攔截器適配器?18. ?*?@Title?:RepeatUrlDataInterceptor.java?19. ?*?@date?2020/12/7?13:47?20. ?*?@Version?:V1.0?21. ?*?@Copyright?(c):http://www.bj9420.com?2020?All?rights?reserved.?22. ?*/??23. @Slf4j??24. public?class?RepeatUrlDataInterceptor?extends?HandlerInterceptorAdapter?{??25. ????/**?26. ?????*?@Author:?wRitchie?27. ?????*?@Description:?preHandle??覆蓋父類的preHandle方法?28. ?????*?預處理回調方法,實現處理器的預處理,驗證是否為重復提交,第三個參數為響應的處理器,自定義Controller?29. ?????*?返回值:true表示繼續流程(如調用下一個攔截器或處理器);false表示流程中斷(如登錄檢查失敗),不會繼續調用其他的攔截器或處理器,此時我們需要通過response來產生響應;?30. ?????*?@Param:?[request,?response,?handler]?31. ?????*?@return:?boolean?32. ?????*?@Date:?2020/12/7?13:54?33. ?????*/??34. ????@Override??35. ????public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{??36. ????????//?1、判斷handler參數是否為HandlerMethod類的實例??37. ????????if?(handler?instanceof?HandlerMethod)?{??38. ????????????//?2、獲取方法注解查看方式是否有PreventRepeat注解??39. ????????????HandlerMethod?handlerMethod?=?(HandlerMethod)?handler;??40. ????????????Method?method?=?handlerMethod.getMethod();??41. ????????????PreventRepeat?annotation?=?method.getAnnotation(PreventRepeat.class);??42. ????????????if?(annotation?!=?null)?{??43. ????????????????//?3、?調用重復數據驗證方法??44. ????????????????boolean?result?=?repeatDataValidator(request);??45. ????????????????if?(result)?{?? //重復提交,返回JSON信息 response.setCharacterEncoding("UTF-8"); response.setContentType("application/json;charset=utf-8"); PrintWriter out=response.getWriter(); JSONObject jsonObject = new JSONObject(); jsonObject.put( "msgcode", SystemConstant.MSG_CODE_FAIL); jsonObject.put( "message", "請不要重復提交。"); out.append(jsonObject.toString()); out.flush(); out.close(); //解決初次發布時,未返回給客戶端信息46. ????????????????????return?false;??47. ????????????????}?else?{??48. ????????????????????return?true;??49. ????????????????}??50. ????????????}?else?{??51. ????????????????return?true;??52. ????????????}??53. ????????}?else?{??54. ????????????//?4.?如果參數不是HandlerMethod類的實例,則調用父類的preHandle方法??55. ????????????return?super.preHandle(request,?response,?handler);??56. ????????}??57. ????}??58. ??59. ??60. ????/**?61. ?????*?@Author:?wRitchie?62. ?????*?@Description:?repeatDataValidator?驗證請求的url+請求數據參數提交是否相同?63. ?????*?相同返回true,表示重復請求;否則返回false,表示不是重復提交?64. ?????*?@Param:?[httpServletRequest]?65. ?????*?@return:?boolean?66. ?????*?@Date:?2020/12/7?13:53?67. ?????*/??68. ????public?boolean?repeatDataValidator(HttpServletRequest?httpServletRequest)?{??69. ????????try?{??70. ????????????//?1、將url+請求數據參數轉換為json字符串,需pom內引用jackson-databind??71. ????????????ObjectMapper?objectMapper?=?new?ObjectMapper();??72. ????????????String?params?=?objectMapper.writeValueAsString(httpServletRequest.getParameterMap());??73. ????????????//?2、?獲取當前請求的url地址,以url為key,請求數據參數為值存在map里??74. ????????????String?url?=?httpServletRequest.getRequestURI();??75. ????????????Map?map?=?new?HashMap(4);??76. ????????????map.put(url,?params);??77. ????????????String?curUrlData?=?map.toString();??78. ????????????log.info("****?curUrlData:"+curUrlData);??79. ????????????//?3、從session中獲取上一次請求存儲的url和請求數據參數字符串??80. ????????????Object?preUrlData?=?httpServletRequest.getSession().getAttribute("preUrlData");??81. ????????????//?4、若上次請求的url+數據為null,則表示尚未訪問的頁面,將當前請求的url+請求數據參數存儲到session中??82. ????????????if?(preUrlData?==?null)?{??83. ????????????????httpServletRequest.getSession().setAttribute("preUrlData",?curUrlData);??84. ????????????????return?false;??85. ????????????}?else?{??86. ????????????????//?5、若上次訪問的url+請求數據參數與本次url+請求數據參數相同,則表示重復提交??87. ????????????????if?(preUrlData.toString().equals(curUrlData))?{??88. ????????????????????return?true;??89. ????????????????}?else?{??90. ????????????????????//6、若上次訪問的url+請求數據參數和本次url+請求數據參數不同,則不是重復提交??91. ????????????????????httpServletRequest.getSession().setAttribute("preUrlData",?curUrlData);??92. ????????????????????return?false;??93. ????????????????}??94. ????????????}??95. ????????}?catch?(Exception?e)?{??96. ????????????log.info("驗證是否為重復請求異常。");??97. ????????????return?false;??98. ????????}??99. ????}??100. }??3、 Spring MVC 配置文件中添加配置
1. ??2. ??????3. ??????????4. ??????????????5. ??????????????6. ??????????????7. ??????????????8. ??????????9. ??????4、 使用方法,在Controller類的方法上,增加@PreventRepeat注解
1. /**?2. ???*?@Author:?wRitchie?3. ???*?@Description:?withdraw?提現?4. ???*?@Param:?[type,?userId,account,payType]?5. ???*?@return:?com.bj9420.model.Result>?6. ???*?@Date:?2020-12-07?15:15?7. ???*/??8. ???@RequestMapping("/withdraw")??9. ???@ResponseBody??10. ???@PreventRepeat??11. ???public?Result>?withdraw(String?type,String?userId,String?account,String?payType)?{??12. ???????//提現代碼???13. ???????......??14. ??15. ???}??這樣,基本實現了防止重復請求,但攔截器的方式需要優化的是將攔截重復請求的返回給請求端,目前的方式,只是不處理,沒有返回信息。
附:補正未返回給客戶端信息,2020-12-08
將攔截重復請求的返回給請求端,返回JSON信息,內容可根據自身需要而編寫,代碼發下:
//重復提交,返回JSON信息 response.setCharacterEncoding("UTF-8"); response.setContentType("application/json;charset=utf-8"); PrintWriter out=response.getWriter(); //PrintWriter out=new PrintWriter(response.getWriter()); JSONObject jsonObject = new JSONObject(); jsonObject.put( "msgcode", SystemConstant.MSG_CODE_FAIL); jsonObject.put( "message", "請不要重復提交。"); out.append(jsonObject.toString()); out.flush(); out.close(); //解決初次發布時,未返回給客戶端信息重復提交時:
處理返回信息后,以攔截器的方式,SSM框架完美實現防止重復請求。
總結
以上是生活随笔為你收集整理的handlerinterceptoradapter 获取请求参数_SSM框架防止重复请求的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql如何配置hbm.xml_配置数
- 下一篇: jupyter python版本_Ubu