首頁 > Java > java教程 > 主體

springboot如何實現介面自動冪等

WBOY
發布: 2023-05-11 21:52:21
轉載
1651 人瀏覽過

冪等

1.概念: 任意多次執行所產生的影響皆與一次執行的影響相同。
依照這個意義,最終的意義就是 對資料庫的影響只能是一次性的,不能重複處理。如何保證其冪等性,通常有以下手段:

1: 資料庫建立唯一性索引,可以保證最終插入資料庫的只有一條資料

2: token 機制,每次介面請求前先取得一個token,然後再下次請求的時候在請求的header 體中加上這個token,後台進行驗證,如果驗證通過刪除token,下次請求再次判斷token

3: 悲觀鎖或樂觀鎖,悲觀鎖可以保證每次for update 的時候其他sql 無法update 資料(在資料庫引擎是innodb 的時候, select 的條件必須是唯一索引, 防止鎖全表)

4: 先查詢後判斷,首先透過查詢資料庫是否存在數據,如果存在證明已經請求過了,直接拒絕該請求,如果沒有存在,就證明是第一次進來,直接放行。

redis 實作自動冪等的原理圖:

springboot如何實現介面自動冪等

#一. 搭建redis的服務Api

1: 首先是搭建redis 伺服器。

2: 引入springboot 中到的redis 的stater,或者Spring 封裝的jedis 也可以,後面主要用到的api 就是它的set 方法和exists 方法, 這裡我們使用springboot 的封裝好的redisTemplate
程式碼如下:

/*
redis工具类
*/
@Component
public class RedisService {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 写入缓存
     * @param key
     * @param value
     * @return
     */
    public  boolean set(final String key,Object value){
        boolean result = false;
        try {
            ValueOperations<Serializable,Object> operations = redisTemplate.opsForValue();
            operations.set(key,value);
            result = true;
        }catch (Exception e){
            result = false;
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 写入缓存有效期
     * @return
     */
    public boolean setEx(final String key ,Object value,Long expireTime){
        boolean result = false;
        try {
            ValueOperations<Serializable,Object> operations = redisTemplate.opsForValue();
            operations.set(key,value);
            redisTemplate.expire(key,expireTime, TimeUnit.SECONDS);//有效期
            result = true;
        }catch (Exception e){
            result = false;
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 判断缓存中是否有对应的value
     * @param key
     * @return
     */
    public boolean exists(final String key){
       return redisTemplate.hasKey(key);
    }

    /**
     * 读取缓存
     * @param key
     * @return
     */
    public Object get(final String key){
        Object obj = null;
        ValueOperations<Serializable,Object> operations= redisTemplate.opsForValue();
        obj =  operations.get(key);
        return obj;
    }

    /**
     * 删除对应的value
     * @param key
     * @return
     */
    public boolean remvoe(final String key){
        if(exists(key)){
            Boolean delete = redisTemplate.delete(key);
            return delete;
        }
        return false;
    }


}
登入後複製

二.自訂AutoIdempotent

自訂一個註解,定義此註解的主要目的是把它加在需要實作冪等的方法上,凡是某個方法註解了它,都會實現自動冪等。後台利用反射如果掃描到這個註解,就會處理這個方法實現自動冪等,使用元註解ElementType.METHOD 表示它只能放在方法上,etentionPolicy.RUNTIME 表示它在運行時

package com.yxkj.springboot_redis_interceptor.annotion;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoIdempotent {
}
登入後複製

三. token 創建和檢驗

1.token服務接口

我們新建一個接口,創建token 服務,裡面主要是兩個方法,一個用來創建token,一個用來驗證token。創建 token 主要產生的是字串,檢驗 token 的話主要是傳達 request 對象,為什麼要傳 request 物件?主要作用就是取得header 裡面的token, 然後檢驗,透過拋出的Exception 來獲取具體的報錯資訊回傳給前端

public interface TokenService {

    /**
     * 创建token
     * @return
     */
    String createToken();

    /**
     * 检验token的合法性
     * @param request
     * @return
     * @throws Exception
     */
    boolean checkToken(HttpServletRequest request) throws Exception;
}
登入後複製

2.token 的服務實作類別

token 引用了redis服務,創建token 採用隨機演算法工具類別產生隨機uuid 字串, 然後放入到redis 中(為了防止資料的冗餘保留, 這裡設定過期時間為10000 秒, 具體可視業務而定),如果放入成功,最後回傳這個token 值。 checkToken 方法就是從 header 中取得 token 到值 (如果 header 中拿不到,就從 paramter 中取得),如若不存在, 直接拋出異常。這個異常訊息可以被攔截器捕捉到,然後回到前端。

以上是springboot如何實現介面自動冪等的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:yisu.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!