亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Spring注解方式防止重復提交原理詳解

2024-07-14 08:42:58
字體:
來源:轉載
供稿:網友

Srping注解方式防止重復提交原理分析,供大家參考,具體內容如下

方法一: Springmvc使用Token

使用token的邏輯是,給所有的url加一個攔截器,在攔截器里面用java的UUID生成一個隨機的UUID并把這個UUID放到session里面,然后在瀏覽器做數據提交的時候將此UUID提交到服務器。服務器在接收到此UUID后,檢查一下該UUID是否已經被提交,如果已經被提交,則不讓邏輯繼續執行下去…**

1 首先要定義一個annotation: 用@Retention 和 @Target 標注接口

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Token {  boolean save() default false;  boolean remove() default false;}

2 定義攔截器TokenInterceptor:

 

public class TokenInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  if (handler instanceof HandlerMethod) {    HandlerMethod handlerMethod = (HandlerMethod) handler;    Method method = handlerMethod.getMethod();    Token annotation = method.getAnnotation(Token.class);    if (annotation != null) {      boolean needSaveSession = annotation.save();      if (needSaveSession) {        request.getSession(false).setAttribute("token", UUID.randomUUID().toString());      }      boolean needRemoveSession = annotation.remove();      if (needRemoveSession) {        if (isRepeatSubmit(request)) {          return false;        }        request.getSession(false).removeAttribute("token");      }    }    return true;  } else {    return super.preHandle(request, response, handler);  }}private boolean isRepeatSubmit(HttpServletRequest request) {  String serverToken = (String) request.getSession(false).getAttribute("token");  if (serverToken == null) {    return true;  }  String clinetToken = request.getParameter("token");  if (clinetToken == null) {    return true;  }  if (!serverToken.equals(clinetToken)) {    return true;  }  return false;}}

Spring MVC的配置文件里加入:

<mvc:interceptors>  <!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 -->     <mvc:interceptor>       <mvc:mapping path="/**"/>       <!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 -->       <bean class="****包名****.TokenInterceptor"/>     </mvc:interceptor> </mvc:interceptors>@RequestMapping("/add.jspf")@Token(save=true)public String add() {  //省略  return TPL_BASE + "index";} @RequestMapping("/save.jspf")@Token(remove=true)public void save() { //省略}

用法:

在Controller類的用于定向到添加/修改操作的方法上增加自定義的注解類 @Token(save=true)

在Controller類的用于表單提交保存的的方法上增加@Token(remove=true)

在表單中增加 用于存儲token,每次需要報token值傳入到后臺類,用于從緩存對比是否是重復提交操作

方法二:springboot中用注解方式

每次操作,生成的key存放于緩存中,比如用google的Gruava或者Redis做緩存

定義Annotation類

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documented@Inheritedpublic @interface LocalLock {  /**   * @author fly   */  String key() default "";  /**   * 過期時間 TODO 由于用的 guava 暫時就忽略這屬性吧 集成 redis 需要用到   *   * @author fly   */  int expire() default 5;}

設置攔截類

@Aspect@Configurationpublic class LockMethodInterceptor {  private static final Cache<String, Object> CACHES = CacheBuilder.newBuilder()      // 最大緩存 100 個      .maximumSize(1000)      // 設置寫緩存后 5 秒鐘過期      .expireAfterWrite(5, TimeUnit.SECONDS)      .build();  @Around("execution(public * *(..)) && @annotation(com.demo.testduplicate.Test1.LocalLock)")  public Object interceptor(ProceedingJoinPoint pjp) {    MethodSignature signature = (MethodSignature) pjp.getSignature();    Method method = signature.getMethod();    LocalLock localLock = method.getAnnotation(LocalLock.class);    String key = getKey(localLock.key(), pjp.getArgs());    if (!StringUtils.isEmpty(key)) {      if (CACHES.getIfPresent(key) != null) {        throw new RuntimeException("請勿重復請求");      }      // 如果是第一次請求,就將 key 當前對象壓入緩存中      CACHES.put(key, key);    }    try {      return pjp.proceed();    } catch (Throwable throwable) {      throw new RuntimeException("服務器異常");    } finally {      // TODO 為了演示效果,這里就不調用 CACHES.invalidate(key); 代碼了    }  }  /**   * key 的生成策略,如果想靈活可以寫成接口與實現類的方式(TODO 后續講解)   *   * @param keyExpress 表達式   * @param args    參數   * @return 生成的key   */  private String getKey(String keyExpress, Object[] args) {    for (int i = 0; i < args.length; i++) {      keyExpress = keyExpress.replace("arg[" + i + "]", args[i].toString());    }    return keyExpress;  }}

Controller類引用

@RestController@RequestMapping("/books")public class BookController { @LocalLock(key = "book:arg[0]") @GetMapping public String save(@RequestParam String token) {  return "success - " + token; }}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲男人的天堂在线| 91人成网站www| 亚洲国产日韩欧美在线99| 国产精品丝袜高跟| 久久久人成影片一区二区三区观看| 欧美日韩精品二区| 国产精品日日做人人爱| 久久久人成影片一区二区三区观看| 97国产在线视频| 青青草国产精品一区二区| 欧美精品在线第一页| 4444欧美成人kkkk| 亚洲美女性视频| 色香阁99久久精品久久久| 国产三级精品网站| 亚洲伊人久久综合| 久久久久国产精品免费| 国产精品久久久久高潮| 欧美综合国产精品久久丁香| 亚洲自拍偷拍在线| 92看片淫黄大片欧美看国产片| 久热精品视频在线观看一区| 成人福利在线观看| 成人免费直播live| 91视频免费在线| 日韩69视频在线观看| 国产成人综合精品| 国产97在线视频| 狠狠躁夜夜躁久久躁别揉| 午夜精品久久久久久久久久久久久| 成人在线播放av| 国产成人精品综合| 成人精品福利视频| 亚洲free性xxxx护士白浆| 国产91精品久久久久久久| 亚洲高清免费观看高清完整版| 成人精品久久久| 亚洲成人网久久久| 午夜精品久久久久久久久久久久| 狠狠躁18三区二区一区| 国产在线视频欧美| 亚洲精品wwwww| 久久91精品国产91久久跳| 日韩欧美极品在线观看| 亚洲人成五月天| 国产精品自产拍高潮在线观看| 亚洲精美色品网站| 国产精品日韩欧美大师| 精品中文字幕在线| 欧美成人三级视频网站| 欧美精品在线极品| 久久夜精品va视频免费观看| 久久久国产91| 亚洲精品乱码久久久久久按摩观| 国产精品jizz在线观看麻豆| 欧美激情一区二区久久久| 欧美国产亚洲视频| 国产精品日日摸夜夜添夜夜av| 日av在线播放中文不卡| 久久久久久国产精品三级玉女聊斋| 97碰在线观看| 欧美亚州一区二区三区| 少妇高潮 亚洲精品| 日本高清不卡在线| 国产精品美腿一区在线看| 欧美性猛交xxxx乱大交| 亚洲成人激情视频| 久久久久亚洲精品成人网小说| 日韩一区二区在线视频| 青青久久av北条麻妃黑人| 亚洲a在线播放| 欧美性受xxx| 久久韩剧网电视剧| 国产精品成人国产乱一区| 亚洲精品欧美日韩专区| 91精品国产自产91精品| 日韩av在线免费观看| 成人免费视频97| 尤物yw午夜国产精品视频| 91精品国产91久久久久久| 97久久伊人激情网| 亚洲欧美日韩国产精品| 国产精品美女主播在线观看纯欲| 欧美精品www在线观看| 51午夜精品视频| 久久天天躁夜夜躁狠狠躁2022| 色综合久久中文字幕综合网小说| 一区二区成人av| 精品国产一区二区三区久久久狼| 国产午夜精品全部视频在线播放| 亚洲自拍欧美色图| 操人视频在线观看欧美| 亚洲精品动漫100p| 欧美日韩一区二区免费在线观看| 欧美日韩精品在线播放| 久久6免费高清热精品| 日本韩国在线不卡| 色悠久久久久综合先锋影音下载| 亚洲偷欧美偷国内偷| 国产精品嫩草影院久久久| 亚洲护士老师的毛茸茸最新章节| 欧美专区日韩视频| 九九热精品视频国产| 欧美日韩另类字幕中文| 国产一区二区三区中文| 久久中文字幕视频| 国产91精品最新在线播放| 亚洲在线免费视频| 亚洲国产一区二区三区四区| 精品国产一区二区三区久久| 国产噜噜噜噜久久久久久久久| 91中文精品字幕在线视频| 亚洲色无码播放| 欧美成人一二三| 91精品啪aⅴ在线观看国产| 亚洲精品av在线播放| 国产精品永久在线| 久久九九国产精品怡红院| 欧美成人午夜激情| 日韩一区在线视频| 成人免费网站在线看| 亚洲视频欧美视频| 美女扒开尿口让男人操亚洲视频网站| 7777免费精品视频| 日韩一区在线视频| 国产精品白嫩初高中害羞小美女| 亚洲精品视频网上网址在线观看| 国产日韩欧美一二三区| 欧美日韩综合视频网址| 日韩中文视频免费在线观看| 操人视频在线观看欧美| 亚洲第一网站免费视频| 欧美日韩国产中字| 欧美亚洲日本网站| 欧美激情亚洲综合一区| 日韩中文在线中文网在线观看| 亚洲欧美日韩精品久久| 亚洲男人的天堂在线| 欧美成人性色生活仑片| 国产精品久久久| 中文字幕亚洲激情| 久久成人18免费网站| 国产午夜精品理论片a级探花| 日韩av影院在线观看| 日本在线观看天堂男亚洲| 国产精品视频播放| 国产日韩av在线| 人妖精品videosex性欧美| 一本一本久久a久久精品综合小说| 69久久夜色精品国产69乱青草| 97视频com| 久久久久久久久爱| 亚洲黄色av女优在线观看| 亚洲女人被黑人巨大进入al| 日本a级片电影一区二区| 欧美日韩国产精品一区二区不卡中文| 亚洲精品久久久久久久久久久久| 欧美国产激情18| 色悠悠久久88| 久久露脸国产精品| 国自产精品手机在线观看视频| 国产精品va在线播放| 日韩第一页在线| 午夜精品蜜臀一区二区三区免费|