精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

深爱激情综合| 国产精品久久国产三级国电话系列| 精品无人区一区二区三区竹菊 | 欧美精品久久久久久久久46p| 亚洲第一成人av| 国产一区二区三区站长工具| 亚洲综合色成人| 国产精品视频免费在线观看| 亚洲 欧美 日韩在线| 亚洲精品久久久久久无码色欲四季 | 久久精品一区四区| 欧美巨猛xxxx猛交黑人97人| 嫩草av久久伊人妇女超级a| 性做久久久久久久| 欧美在线综合| 日韩av资源在线播放| 亚洲精品少妇一区二区| 91激情在线观看| 欧美少妇xxxx| 在线看不卡av| 日韩久久精品一区二区三区| 日产精品久久久| 国产精品男女| 亚洲综合视频在线观看| 久久涩涩网站| 日韩精品一区二区不卡| 日韩中文字幕无砖| 亚洲伦理在线精品| 91中文字幕在线| 九一在线免费观看| 经典三级一区二区| 国产欧美中文在线| 国产精品麻豆va在线播放| 青青草精品在线视频| 国产精品第一国产精品| 中文字幕不卡的av| 国产精品入口免费视频一| 国产精品99re| 日韩欧美天堂| 岛国av在线不卡| 欧美lavv| 中国一级片黄色一级片黄| 欧美色图国产精品| 亚洲精品永久免费| 免费看黄色一级大片| 夜级特黄日本大片_在线| 国产一区二区三区四区五区传媒| 日韩亚洲欧美中文三级| 国产精品久久久久久久久电影网| 亚洲精品一区二区三区蜜桃| 日本欧美一区二区在线观看| 日韩亚洲国产中文字幕| www.色.com| 97在线超碰| 久久久久久久综合日本| 国产伦精品一区二区三区四区免费 | 日韩午夜精品电影| 午夜视频在线观| 黄页网站在线观看免费| 97国产一区二区| 国产精品69精品一区二区三区| 国产精品天天干| 国产高清亚洲| 欧美午夜xxx| 亚洲精品乱码久久久久久蜜桃91 | 欧美日韩在线精品| 91精品人妻一区二区三区果冻| 久久久蜜桃一区二区人| 欧美在线视频一区二区| 在线视频这里只有精品| 乱亲女h秽乱长久久久| 欧美性videosxxxxx| 成人免费a级片| 在线中文字幕第一页| 91香蕉视频mp4| 国产欧美日韩高清| 日本天堂在线视频| 99re国产精品| 欧美精品一二区| 久久久久久亚洲中文字幕无码| 国模大尺度视频一区二区| 亚洲一区二区黄色| 手机看片福利永久国产日韩| 无码国精品一区二区免费蜜桃| 久久99精品久久久久久动态图 | 中文字幕亚洲欧美日韩高清| 一边摸一边做爽的视频17国产| av成人亚洲| 欧美视频一区二区三区四区| 亚洲热在线视频| 美女福利一区| 色综合亚洲精品激情狠狠| 午夜剧场免费看| 香蕉久久夜色精品国产更新时间| 亚洲性生活视频在线观看| 佐佐木明希电影| 亚洲精品大片| 91福利在线导航| 中国丰满人妻videoshd| 欧美14一18处毛片| 亚洲三级在线免费观看| 色噜噜一区二区| 日本在线视频中文有码| 中文字幕字幕中文在线中不卡视频| 精品在线观看一区二区| 最新电影电视剧在线观看免费观看| 99re66热这里只有精品3直播 | 国产免费一区视频观看免费 | a一区二区三区亚洲| 日本精品免费观看高清观看| 国产5g成人5g天天爽| 日本亚洲不卡| 亚洲精品动漫100p| 日本在线不卡一区二区| 精品黄色一级片| 国产亚洲精品久久久久久牛牛| 东方av正在进入| 亚洲欧美在线专区| 久久偷看各类女兵18女厕嘘嘘| 极品蜜桃臀肥臀-x88av| 成人三级视频| 久久久久免费视频| 亚洲国产成人精品综合99| 99精品国产一区二区青青牛奶| 91九色在线视频| 国产又粗又猛视频| 91色视频在线| 无码人妻精品一区二区蜜桃网站| 黑人一区二区三区| 91麻豆精品久久久久蜜臀| 日韩欧美中文视频| 成人国产精品一级毛片视频| 91精品国产高清自在线 | 国语精品一区| 久久久亚洲欧洲日产国码aⅴ| 中文字幕你懂的| 久久久一区二区三区| www.日本在线播放| 欧美特大特白屁股xxxx| 欧美影片第一页| 老司机福利av| 久久高清免费| 欧美乱大交xxxxx另类电影| 中文字幕第315页| 国产亚洲精久久久久久| 成年人免费观看的视频| 97最新国自产拍视频在线完整在线看| 精品国产乱码久久久久酒店| 久久国产亚洲精品无码| 色综合一本到久久亚洲91| 欧美精品一区二区三区在线播放| 视频免费在线观看| 欧美日本二区| 国产成人综合亚洲| 黄色在线小视频| 国产精品素人一区二区| www.日本xxxx| 色无极亚洲影院| 国产色综合天天综合网| 欧美熟妇交换久久久久久分类 | 久久精选视频| 欧美日韩电影一区二区三区| 成人香蕉视频| 日韩欧美成人一区二区| 国产精品无码久久久久久| 99热免费精品在线观看| 蜜桃日韩视频| 久久久久伊人| 久久91精品国产| 欧美自拍偷拍第一页| 精品久久久久久久久久久久久久| 野花社区视频在线观看| 一区二区三区午夜视频| 亚洲一区二区三区乱码aⅴ| 羞羞的视频在线看| 精品88久久久久88久久久| 日本系列第一页| 久久亚洲免费视频| 久久人人爽人人爽人人av| 久久91超碰青草在哪里看| 色偷偷av一区二区三区乱| 国产女人高潮时对白| 国产欧美一区二区精品久导航 | 91亚洲大成网污www| 人妻无码视频一区二区三区| 久久影院100000精品| 97色在线视频观看| www.天堂av.com| 中文字幕一区三区| 手机看片福利盒子久久| 国产国产精品| 国产精品女主播视频| 黄网页免费在线观看| 欧美性受极品xxxx喷水| 国产尤物在线播放| 91网站视频在线观看| 久久久久xxxx| 999久久久91| 懂色一区二区三区av片 | 欧美日本高清一区| 欧美日本网站| 一本到不卡免费一区二区| 亚洲一区二区在线免费| 久久最新视频| 蜜桃狠狠色伊人亚洲综合网站| 欧美成人家庭影院| 性金发美女69hd大尺寸| 欧美性猛交xxx乱大交3蜜桃| 欧美三级韩国三级日本三斤| www亚洲色图| 岛国一区二区在线观看| 999一区二区三区| 欧美久久精品一级c片| 国产精品日韩高清| 久久亚洲人体| 欧洲s码亚洲m码精品一区| 26uuu亚洲电影在线观看| 亚洲欧美激情在线视频| 日韩美一区二区| 久久久99久久| www.男人天堂| 国产成人av电影| www.av91| 亚洲精品91| 不卡视频一区二区三区| av成人福利| 欧美成人免费全部观看天天性色| 国产69久久| 欧美福利电影网| 久久久久久av无码免费网站| 99在线精品免费| 久久综合九色综合88i| 一区二区三区国产精华| 一区二区日本伦理| 欧美高清hd| 国产精品最新在线观看| 少妇一区视频| 人体精品一二三区| 性xxxxfreexxxxx欧美丶| 亚洲色图狂野欧美| 91成人在线免费| 欧美影视一区在线| 亚洲精品久久久久久久蜜桃| 亚洲图片激情小说| 黑人と日本人の交わりビデオ| 久久人人爽人人爽| 中国美女乱淫免费看视频| 91免费视频大全| 波多野结衣一本| 久久精品一区二区三区不卡| 黄色正能量网站| 久久久久国产精品人| 免费在线观看你懂的| 久久免费视频一区| 久久久视频6r| 高清日韩电视剧大全免费| 国模大尺度视频| 久久天堂精品| 久久黄色免费看| 强制捆绑调教一区二区| 天堂一区在线观看| 亚洲国产专区校园欧美| 亚洲乱码一区二区三区三上悠亚 | 制服诱惑一区| 中文视频一区| 国产婷婷一区二区三区| 久久中文字幕av| 国产精品夜夜夜爽张柏芝| 一区二区电影| 欧美视频免费看欧美视频| 销魂美女一区二区三区视频在线| 在线码字幕一区| 欧美成熟视频| 亚洲欧洲日韩综合二区| 香蕉综合视频| 男人日女人视频网站| 久久福利影视| 99日在线视频| 成人爱爱电影网址| 日韩欧美色视频| 国产99久久久久| 午夜理伦三级做爰电影| 国产精品国产三级国产aⅴ入口| 超碰在线国产97| 欧美性猛交xxxx黑人猛交| 国产三级理论片| 狠狠综合久久av一区二区小说| 波多野结衣高清视频| 在线播放国产精品二区一二区四区| 免费观看a视频| 亚洲偷欧美偷国内偷| 最爽无遮挡行房视频在线| 97精品一区二区三区| 国产精品久久久久久久久久齐齐| 91在线看网站| 国产高清日韩| 久久天天狠狠| 中出一区二区| 国产成人精品无码播放| 亚洲一区网站| 男人添女人下面免费视频| 国产成人自拍在线| 中文字幕55页| 国产日韩欧美电影| 国产一级特黄视频| 欧美三区在线观看| 天天操天天干天天舔| 亚洲精品国产电影| 看黄网站在线| 国产激情久久久| 国产精品香蕉| 91社在线播放| 日本在线不卡一区| 性欧美丰满熟妇xxxx性久久久| 中文字幕亚洲一区二区va在线| 四虎精品永久在线| 色综合 综合色| 国产 欧美 自拍| 亚洲国产欧美一区二区三区久久| 最近高清中文在线字幕在线观看| 午夜精品福利视频| 日韩一二三区在线观看| 亚洲欧洲另类精品久久综合| 亚洲免费网址| 人妻激情偷乱频一区二区三区| 亚洲免费毛片网站| 伊人精品一区二区三区| 亚洲天天在线日亚洲洲精| 自拍一区在线观看| 激情视频一区二区| 欧美日韩午夜| 亚洲一区二区三区三州| 国产精品久久久一本精品| 黄色片子在线观看| 欧美探花视频资源| 国产在线一在线二| 欧美专区福利在线| 要久久爱电视剧全集完整观看 | 欧美日韩视频精品二区| 性欧美xxxx交| 天海翼精品一区二区三区| 男人添女人荫蒂免费视频| 国产福利不卡视频| 久久精品一级片| 欧美岛国在线观看| 欧美精品videosex| 国产传媒一区二区| 伊人成人在线视频| www.色就是色| 国产欧美在线观看一区| 中文字字幕在线观看| 日韩一区二区久久久| 自拍偷拍亚洲| 永久免费网站视频在线观看| 亚洲精品资源| 国产真实乱人偷精品| 欧美日韩国产精品| 欧美在线观看在线观看| 日韩最新免费不卡| 曰本一区二区| 中国女人做爰视频| 波多野结衣91| 激情视频网站在线观看| 在线免费看av不卡| 3344国产永久在线观看视频| 国产日本一区二区三区| 婷婷久久综合| 女人扒开腿免费视频app| 亚洲国产精品久久人人爱| 中文字幕在线2019| www.日韩欧美| 凹凸成人在线| 视频一区二区视频| 粉嫩欧美一区二区三区高清影视 | 91亚洲天堂| 国产欧美一区二区视频| 免费精品视频| 少妇高潮在线观看| 一本到不卡精品视频在线观看| caoporn国产精品免费视频| 2019中文字幕在线观看| 亚洲福利合集| 精品国产免费av| 国产精品每日更新| 国内爆初菊对白视频| 日韩av成人在线观看| 在线精品自拍| 裸体裸乳免费看| 精东粉嫩av免费一区二区三区| 黑人巨大精品欧美| 欧美日韩精品欧美日韩精品一| 欧洲亚洲精品视频| 成人a在线视频| 99re6这里只有精品| 97精品人人妻人人| 亚洲成人免费影院| av电影在线网| 久久精品magnetxturnbtih| 激情综合一区二区三区| 国产精品美女久久久久av爽|