精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

SpringBoot 接口防重實現:基于哈希算法的解決方案

開發 架構
在高并發或用戶誤操作場景下,接口重復提交會引發數據不一致、業務邏輯異常等問題。防重復提交就是防止用戶在短時間內對同一接口進行多次重復提交,導致數據重復創建或狀態異常。

引言

在高并發或用戶誤操作場景下,接口重復提交會引發數據不一致、業務邏輯異常等問題。防重復提交就是防止用戶在短時間內對同一接口進行多次重復提交,導致數據重復創建或狀態異常。

實現

圖片圖片

方案原理

  • 生成請求唯一標識:服務端接收請求后,根據URL、請求參數等信息生成SHA-256哈希值,作為該請求的唯一標識。
  • 緩存校驗:將哈希值存入緩存(如Redis),并設置過期時間。若后續出現相同哈希值的請求,則判定為重復提交,直接攔截;若不存在,則放行并將哈希值存入緩存。

代碼實現

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatSubmit {
    /**
     * 防重過期時間(單位:秒),默認 10 秒
     */
    int expireSeconds() default 10;
}

哈希工具類

public class HashUtil {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 生成包含 JSON 體的請求哈希
     * @param url 請求地址
     * @param formParams 表單參數
     * @param jsonBody JSON 請求體
     */
    public static String generateSHA256(String url, Map<String, Object> formParams, String jsonBody) {
        StringBuilder sb = new StringBuilder(url);

        // 1. 加入排序后的表單參數
        TreeMap<String, Object> sortedFormParams = new TreeMap<>(formParams);
        for (Map.Entry<String, Object> entry : sortedFormParams.entrySet()) {
            sb.append(entry.getKey()).append(entry.getValue());
        }

        // 2. 加入 JSON 體(若存在)
        if (jsonBody != null && !jsonBody.isEmpty()) {
            try {
                // 將 JSON 轉為有序 Map 后拼接(避免 JSON 字段順序影響哈希)
                Map<String, Object> jsonMap = objectMapper.readValue(jsonBody, Map.class);
                TreeMap<String, Object> sortedJsonMap = new TreeMap<>(jsonMap);
                sb.append(objectMapper.writeValueAsString(sortedJsonMap));
            } catch (Exception e) {
                // 解析失敗時直接拼接原始 JSON(可能存在順序問題,視業務容忍度調整)
                sb.append(jsonBody);
            }
        }

        return DigestUtils.sha256Hex(sb.toString());
    }
}

請求體包裝類

public class RepeatableReadRequestWrapper extends HttpServletRequestWrapper {

    private final byte[] body;

    public RepeatableReadRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        // 讀取請求體并緩存
        body = readBytes(request.getInputStream());
    }

    private byte[] readBytes(InputStream inputStream) throws IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            return outputStream.toByteArray();
        }
    }

    @Override
    public ServletInputStream getInputStream() {
        // 返回緩存的請求體流
        ByteArrayInputStream inputStream = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public int read() {
                return inputStream.read();
            }

            @Override
            public boolean isFinished() {
                return inputStream.available() == 0;
            }

            @Override
            public boolean isReady() {
                returntrue;
            }

            @Override
            public void setReadListener(ReadListener listener) {}
        };
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(getInputStream(), StandardCharsets.UTF_8));
    }

    // 獲取請求體字符串
    public String getBody() {
        return new String(body, StandardCharsets.UTF_8);
    }
}

請求體過濾器

@Component
public class RepeatableReadFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 僅包裝 HTTP 請求
        if (request instanceof HttpServletRequest) {
            ServletRequest wrapper = new RepeatableReadRequestWrapper((HttpServletRequest) request);
            chain.doFilter(wrapper, response);
        } else {
            chain.doFilter(request, response);
        }
    }
}

防重攔截器

public class RepeatSubmitInterceptor implements HandlerInterceptor {

    private final RedisTemplate<String, Object> redisTemplate;

    public RepeatSubmitInterceptor(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            NoRepeatSubmit annotation = method.getAnnotation(NoRepeatSubmit.class);
            if (annotation != null) {
                // 1. 提取 URL
                String url = request.getRequestURI();

                // 2. 提取表單參數
                Map<String, Object> formParams = new HashMap<>();
                request.getParameterMap().forEach((key, values) -> 
                    formParams.put(key, values.length == 1 ? values[0] : values)
                );

                // 3. 提取 JSON 請求體(從包裝類中獲取)
                String jsonBody = "";
                if (request instanceof RepeatableReadRequestWrapper) {
                    jsonBody = ((RepeatableReadRequestWrapper) request).getBody();
                }

                // 4. 生成唯一哈希標識
                String hash = HashUtil.generateSHA256(url, formParams, jsonBody);

                // 5. 緩存校驗
                Boolean exists = redisTemplate.opsForValue()
                        .setIfAbsent(hash, "1", annotation.expireSeconds(), java.util.concurrent.TimeUnit.SECONDS);
                if (exists == null || !exists) {
                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().write("{\"code\":400,\"msg\":\"請勿重復提交請求\"}");
                    returnfalse;
                }
            }
        }
        returntrue;
    }
}

配置攔截器

@Configuration
public class WebConfig implements WebMvcConfigurer {

    private final RedisTemplate<String, Object> redisTemplate;

    public WebConfig(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Bean
    public RepeatSubmitInterceptor repeatSubmitInterceptor() {
        return new RepeatSubmitInterceptor(redisTemplate);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(repeatSubmitInterceptor())
                .addPathPatterns("/**"); // 攔截所有接口,可根據需求調整
    }
}


責任編輯:武曉燕 來源: 一安未來
相關推薦

2024-08-29 15:26:21

2011-03-07 14:29:18

2016-03-13 17:58:57

2025-04-14 04:01:00

2025-10-29 07:43:18

2024-05-28 09:26:46

2024-09-13 10:21:50

2025-06-09 01:22:00

2009-09-24 15:45:23

2024-06-14 09:30:58

2023-06-21 11:27:53

2009-08-26 18:17:26

C#基于Object解

2022-12-27 11:06:35

海量接口并發

2011-04-29 14:53:56

SimpleFrame

2009-04-02 08:23:24

ARM上網本移動OS

2020-12-18 17:27:20

物聯網資產跟蹤IOT

2025-06-05 00:00:00

向量數據庫線程安全Redis

2013-11-27 12:23:38

2025-04-24 11:09:13

2013-01-30 22:46:39

NFC鑰匙安防領域
點贊
收藏

51CTO技術棧公眾號

色黄视频在线观看| 中文字幕在线播放av| 成人看片爽爽爽| 欧美日韩一区二区在线| 日本一区免费在线观看| 国产又粗又猛又爽又黄的视频一| 午夜久久99| 日韩高清欧美高清| 一级黄色录像在线观看| 丁香花视频在线观看| 久久久精品天堂| 91社区国产高清| 日韩欧美成人一区二区三区| 999国产精品视频| 亚洲第一中文字幕在线观看| 美女黄色片视频| 丰乳肥臀在线| 中文在线一区二区| 精品国产_亚洲人成在线| 中文字幕日产av| 国产亚洲亚洲| 欧美黑人巨大xxx极品| 亚洲精品午夜视频| 成人激情自拍| 666欧美在线视频| 97在线免费公开视频| 综合久久2019| 国产精品丝袜91| 久久免费一区| 成人免费视频国产| 久久国产精品99精品国产| 欧美最顶级丰满的aⅴ艳星| 婷婷在线精品视频| 成人在线免费视频观看| 精品视频偷偷看在线观看| 中文字幕一二三| 欧洲午夜精品| 欧美色视频在线| 黄色免费视频大全| 97天天综合网| 亚洲激情在线播放| 宅男噜噜99国产精品观看免费| 亚洲欧洲视频在线观看| 高潮精品一区videoshd| 91夜夜未满十八勿入爽爽影院| 少妇久久久久久久| 国产欧美三级| 亚洲97在线观看| 久久网一区二区| 自拍视频亚洲| 另类少妇人与禽zozz0性伦| 激情五月深爱五月| 精品一区二区三| 亚洲网站在线观看| 美女脱光内衣内裤| 蜜臀av免费一区二区三区 | 91麻豆精品在线| 美女精品网站| 青青草99啪国产免费| 久久国产视频播放| 国产一区二区三区久久久久久久久 | 国产成人精品视频在线观看| 久久久久99精品成人片我成大片 | 韩剧1988免费观看全集| 国产一级片久久| 午夜亚洲福利| 欧美韩国理论所午夜片917电影| 青青草手机在线视频| 中文字幕一区二区av | 欧美大胆a人体大胆做受| 亚洲va韩国va欧美va| 欧美一级免费播放| 小早川怜子影音先锋在线观看| 午夜a成v人精品| 国产91在线免费| 日本欧美一区| 91精品国产综合久久小美女| 岛国av免费观看| 奇米777国产一区国产二区| 亚洲裸体xxxx| 阿v天堂2014| 欧美一区二区三区久久精品茉莉花 | 91九色综合久久| 亚洲第一成人av| 91片黄在线观看| 亚洲开发第一视频在线播放| 成码无人av片在线观看网站| 亚洲电影激情视频网站| 国产美女三级视频| 99er精品视频| 亚洲精品999| 中文字幕美女视频| 欧美精品九九| 国产91在线播放九色快色| 一本到在线视频| jizz一区二区| 天堂av一区二区| 欧洲一区二区三区| 日本黄色一区二区| 欧美性受xxxx黒人xyx性爽| 久久99精品久久久久久欧洲站| 亚洲视频在线观看视频| tube国产麻豆| 亚洲综合国产| 91观看网站| 精彩国产在线| 亚洲国产中文字幕| youjizzxxxx18| 成人在线视频你懂的| 中文字幕亚洲无线码a| 在线免费观看毛片| 美国十次了思思久久精品导航| 国产91一区二区三区| av在线资源网| 日韩欧美黄色动漫| 日本人妻一区二区三区| 欧美日韩亚洲在线观看| 午夜精品久久久久久久99热| 国产精品久久久久久久久久久久久久久久| av不卡一区二区三区| 中文字幕精品一区日韩| 亚洲人成午夜免电影费观看| 日韩欧美一区二区视频| 日日操免费视频| 亚洲欧美日韩视频二区| 国产精品日韩二区| 国产激情在线观看| 欧美在线免费观看亚洲| 韩国无码一区二区三区精品| 中文字幕免费一区二区| 国产区精品视频| 成人在线高清视频| 日韩欧美在线视频| 在线视频 日韩| 欧美精品不卡| 亚洲自拍在线观看| 欧美激情午夜| 欧美另类高清zo欧美| 亚洲一区视频在线播放| 久久国产成人| 欧美18视频| 亚洲黄色免费看| 亚洲男人天堂2024| 国产一级片毛片| 91免费版在线看| 欧美久久久久久久久久久久久| 一区二区三区视频免费视频观看网站| 波霸ol色综合久久| 97成人在线观看| 18成人在线视频| 人人干人人干人人| 欧美电影一区| 国产在线日韩在线| 免费黄网在线观看| 欧美日韩久久久一区| 亚洲天堂精品一区| 免费视频一区二区| 一区二区三区四区五区视频| 黄页免费欧美| 日韩有码视频在线| 国产乱码久久久久| 亚洲黄一区二区三区| 中文字幕第六页| 亚洲高清二区| 精品日产一区2区三区黄免费| 九色porny视频在线观看| 日韩精品在线看| 久久国产乱子伦精品| 中文字幕不卡在线| 亚洲五月激情网| 激情偷拍久久| 欧美大陆一区二区| 亚洲电影有码| 久久婷婷国产麻豆91天堂| 国产超碰人人模人人爽人人添| 亚洲一区二区在线免费观看视频| 国产伦精品一区三区精东| 噜噜噜91成人网| 亚洲第一综合| 日韩一二三区| 2020久久国产精品| a黄色在线观看| 精品国产一区二区三区久久影院| 偷偷操不一样的久久| 亚洲国产精品精华液2区45| 手机免费av片| 99国产精品99久久久久久粉嫩| 青娱乐一区二区| 一区二区三区日本视频| 高清欧美性猛交| 国产女主播在线写真| 欧美一区二区成人| 国产精品一区二区三区四| 136国产福利精品导航| 屁屁影院国产第一页| 秋霞av亚洲一区二区三| 久久精品无码中文字幕| 日韩欧美一区二区三区免费看| 亚洲综合国产精品| 欧美大片免费观看网址| 欧美另类极品videosbest最新版本| 婷婷五月综合激情| 欧美精品vⅰdeose4hd| 特一级黄色大片| 亚洲三级在线播放| 成人乱码一区二区三区av| 国产真实乱偷精品视频免| 男人天堂网视频| 欧美日韩福利| 亚洲在线不卡| 中文字幕中文字幕精品| **亚洲第一综合导航网站| 欧美片第一页| 韩国国内大量揄拍精品视频| 免费黄色在线| 亚洲欧美中文另类| 蜜桃av中文字幕| 91精品国产91热久久久做人人| 日韩在线播放中文字幕| 亚洲午夜电影在线| 三级影片在线看| 国产精品久久久久影院色老大 | 欧美国产一区视频在线观看| 国产视频久久久久久| 国产精品1区2区| mm131亚洲精品| 视频一区欧美精品| 欧美午夜小视频| 欧美另类亚洲| 可以免费看的黄色网址| 成人6969www免费视频| 精品人伦一区二区三区| 激情亚洲另类图片区小说区| 亚洲一区二区三区视频| 亚洲青青久久| 国产精品美女无圣光视频| 欧美电影免费观看网站| 2019中文字幕全在线观看| 丁香花在线高清完整版视频 | 最新中文字幕在线播放| 91国自产精品中文字幕亚洲| 丁香花视频在线观看| 久久久久久国产免费 | 亚洲国产欧美日韩另类综合| 高h视频免费观看| 亚洲天堂成人在线观看| 熟女少妇a性色生活片毛片| 国产精品色哟哟网站| 农村老熟妇乱子伦视频| 中日韩av电影| 中文字幕美女视频| 亚洲日韩欧美一区二区在线| 天天色影综合网| 亚洲欧美日韩国产中文在线| 欧美爱爱免费视频| 亚洲欧美区自拍先锋| 久久久国产精品黄毛片| 亚洲一区二区三区视频在线| 五月天婷婷丁香| 欧美日韩精品国产| 人人草在线观看| 在线观看区一区二| 亚洲永久精品视频| 日韩亚洲欧美成人一区| 日本黄色一区二区三区| 亚洲美女www午夜| 韩国福利在线| 精品国产一区av| 91麻豆一二三四在线| 久久久女人电视剧免费播放下载| 国产v日韩v欧美v| 国产成人高潮免费观看精品| 成人黄色毛片| 99免费在线视频观看| 女同另类激情重口| 神马影院我不卡午夜| 国产精品久久久久久久免费观看| 伊人再见免费在线观看高清版 | 亚洲精品一二三四五区| 国产一区在线看| www.日本高清| 国产精品视频线看| 草视频在线观看| 欧美性xxxxxxxxx| 国产精品乱码一区二区| 欧美videossexotv100| 日色在线视频| 日韩中文字幕在线精品| sm在线播放| 国产美女主播一区| 精品精品国产毛片在线看| 手机成人在线| 亚洲高清二区| 婷婷免费在线观看| fc2成人免费人成在线观看播放| 在哪里可以看毛片| 亚洲乱码国产乱码精品精98午夜 | 18视频在线观看网站| 51午夜精品视频| 国产日本亚洲| 欧美日韩喷水| 欧美日本不卡| 蜜臀av免费观看| 99精品欧美一区二区三区综合在线| 1024手机在线观看你懂的| 亚洲成av人片一区二区| 亚洲中文字幕在线观看| 日韩电影免费观看中文字幕 | 亚洲欧洲成人自拍| 97免费在线观看视频| 欧美一区二区三区白人| 青草久久伊人| 欧美精品久久久久久久久久| 国产成人精品一区二区三区视频 | 夜夜精品浪潮av一区二区三区| 国产亚洲欧美日韩高清| 欧美精品一区二区三区久久久 | 中文字幕亚洲欧美在线不卡| 久久一区二区三区视频| 精品黑人一区二区三区久久| 日本免费在线观看| 国产精品激情av电影在线观看| 黄色网一区二区| 精品人妻大屁股白浆无码| 麻豆成人在线观看| 在线不卡av电影| 偷窥国产亚洲免费视频| 亚洲成人黄色片| 久久综合色影院| 亚洲国产天堂| 亚洲午夜激情| 免费欧美日韩国产三级电影| 色一情一交一乱一区二区三区| 精品免费在线观看| 欧性猛交ⅹxxx乱大交| 欧美激情国产精品| 亚洲高清在线一区| 青青草影院在线观看| 久久99久久久欧美国产| 国产又粗又猛又爽又黄的视频小说| 岛国av在线不卡| 日本中文字幕电影在线观看 | 亚洲男人天天操| 在线男人天堂| 久久国产精品一区二区三区四区| 韩国一区二区三区在线观看| 久久发布国产伦子伦精品| 亚洲精品成人在线| 国产黄色美女视频| 欧美—级a级欧美特级ar全黄 | 欧美成人a∨高清免费观看| 国产在线观看91| 不卡一区二区三区视频| 欧美另类女人| 国产亚洲色婷婷久久99精品91| 亚洲大尺度视频在线观看| 色香蕉在线视频| 青草热久免费精品视频| 精品视频黄色| 蜜桃福利午夜精品一区| 亚洲女人的天堂| www.五月婷婷| 91sa在线看| 精品盗摄女厕tp美女嘘嘘| 超碰超碰在线观看| 亚洲欧美一区二区三区极速播放 | 狠狠噜天天噜日日噜| 成人一区在线看| 免费观看一区二区三区毛片| 亚洲欧美三级伦理| 日本欧美在线| 国产精品自拍合集| 91丨国产丨九色丨pron| 中文字幕视频在线播放| 九九热精品视频在线播放| 久久久精品国产**网站| 日韩视频第二页| 国产精品不卡一区| 可以免费看毛片的网站| 欧美在线免费视频| 手机在线一区二区三区| 免费观看污网站| 色婷婷国产精品久久包臀| 日本精品一区二区三区在线播放| 春色成人在线视频| 久久久久在线| 亚洲色图综合区| 亚洲美女动态图120秒| 国产一区二区三区国产精品| 蜜臀av无码一区二区三区| 日本一区二区免费在线观看视频| 国产熟女一区二区丰满| 欧美一区二区视频97| 久久久久久久久久久久久久| 欧美做受喷浆在线观看| 91精品久久久久久久久99蜜臂| 中国字幕a在线看韩国电影| 日韩最新中文字幕| 国产偷国产偷亚洲高清人白洁| 99热这里只有精品99|