最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot接口防抖實戰(zhàn)之防重復(fù)提交的5種高級方案

 更新時間:2026年04月07日 10:25:46   作者:天天摸魚的java工程師  
在日常業(yè)務(wù)開發(fā)中處理重復(fù)請求是需要經(jīng)常注意的,在某些情況下是可能重復(fù)發(fā)送的,如果是查詢類操作并無大礙,但其中有些請求是涉及寫入操作的,重復(fù)了很可能會導(dǎo)致很嚴(yán)重后果,這篇文章主要介紹了SpringBoot接口防抖實戰(zhàn)之防重復(fù)提交的5種高級方案,需要的朋友可以參考下

前言

作為一名摸爬滾打八年的 Java 開發(fā),我敢說:線上 80% 的 “數(shù)據(jù)錯亂” 故障,都和接口重復(fù)提交有關(guān)。上周大促,用戶瘋狂點擊下單按鈕,導(dǎo)致同一訂單被創(chuàng)建了 3 次;去年支付接口被爬蟲高頻調(diào)用,直接產(chǎn)生了雙倍扣款 —— 這些血淋淋的案例告訴我們:接口防抖不是 “可選功能”,而是 “必做防護(hù)”。

很多人覺得 “防重復(fù)提交不就是前端按鈕禁用嗎?”—— 太天真了!爬蟲、Postman 直接調(diào)用、網(wǎng)絡(luò)延遲重發(fā),這些場景前端防護(hù)形同虛設(shè)。今天就從實戰(zhàn)出發(fā),分享 5 種 SpringBoot 接口防抖的高級方案,覆蓋單機、分布式、高并發(fā)等所有場景,每一種都附可直接復(fù)制的代碼和八年踩坑總結(jié),讓你徹底解決 “手抖黨” 和 “惡意刷接口” 的煩惱。

一、先分清:防抖 vs 防重?別再混淆了!

在講方案前,先澄清兩個高頻混淆的概念(八年開發(fā)見過太多人用錯):

  • 接口防抖(Debounce) :阻止短時間內(nèi)重復(fù)觸發(fā)同一接口(比如 1 秒內(nèi)點 5 次下單),核心是 “限制觸發(fā)頻率”;
  • 接口防重(Idempotent) :保證同一請求多次執(zhí)行結(jié)果一致(比如重復(fù)支付只扣一次錢),核心是 “結(jié)果唯一性”。

本文的方案是 “防抖 + 防重” 結(jié)合 —— 既阻止高頻重復(fù)調(diào)用,又保證即使調(diào)用多次也不會出問題,真正做到 “雙重防護(hù)”。

二、5 種高級方案:從單機到分布式,覆蓋所有場景

方案 1:基于 Redis+Lua 腳本(分布式高并發(fā)首選)

核心原理

利用 Redis 的原子性 + Lua 腳本,給接口加 “限時鎖”:同一請求標(biāo)識(比如用戶 ID + 接口名 + 參數(shù)摘要)在指定時間內(nèi)只能執(zhí)行一次,超過時間自動釋放鎖。

為什么用 Lua?

Redis 單條命令是原子的,但多條命令組合(比如先查 key 是否存在,再 set 值)會有并發(fā)問題。Lua 腳本能把多步操作打包成原子執(zhí)行,避免 “競態(tài)條件”—— 這是分布式防重的關(guān)鍵(八年開發(fā)踩過的坑:以前用 Redis+Java 代碼判斷,高并發(fā)下還是會出現(xiàn)重復(fù)提交)。

實戰(zhàn)代碼

  1. 先定義防抖注解(標(biāo)記需要防重的接口)
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AntiDuplicateSubmit {
    // 防抖時間(默認(rèn)1秒)
    long timeout() default 1;
    // 時間單位(默認(rèn)秒)
    TimeUnit unit() default TimeUnit.SECONDS;
    // 提示信息
    String message() default "操作過于頻繁,請稍后再試!";
}
  1. Lua 腳本(原子執(zhí)行 “查鎖 + 加鎖”)在resources/lua/anti_duplicate_submit.lua創(chuàng)建腳本:
-- 1. 接收參數(shù):key=請求標(biāo)識,timeout=過期時間
local key = KEYS[1]
local timeout = ARGV[1]
-- 2. 查鎖:存在則返回1(重復(fù)提交),不存在則加鎖返回0
if redis.call('EXISTS', key) == 1 then
    return 1
else
    redis.call('SET', key, '1', 'EX', timeout)
    return 0
end
  1. AOP 切面(攔截注解,執(zhí)行 Lua 腳本)
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
@Aspect
@Component
@Slf4j
public class AntiDuplicateSubmitAspect {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    private final DefaultRedisScript<Long> antiDuplicateScript;
    // 初始化Lua腳本
    public AntiDuplicateSubmitAspect() {
        antiDuplicateScript = new DefaultRedisScript<>();
        antiDuplicateScript.setLocation(new ClassPathResource("lua/anti_duplicate_submit.lua"));
        antiDuplicateScript.setResultType(Long.class);
    }
    @Around("@annotation(com.example.demo.annotation.AntiDuplicateSubmit)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        AntiDuplicateSubmit annotation = method.getAnnotation(AntiDuplicateSubmit.class);
        // 3. 生成唯一請求標(biāo)識(用戶ID+接口名+參數(shù)摘要)
        String requestKey = generateRequestKey(joinPoint, method);
        long timeout = annotation.unit().toSeconds(annotation.timeout());
        // 4. 執(zhí)行Lua腳本
        Long result = stringRedisTemplate.execute(
                antiDuplicateScript,
                Collections.singletonList(requestKey),
                String.valueOf(timeout)
        );
        // 5. 結(jié)果判斷:1=重復(fù)提交,0=正常執(zhí)行
        if (result != null && result == 1) {
            log.warn("接口重復(fù)提交,key:{}", requestKey);
            throw new RuntimeException(annotation.message());
        }
        // 6. 正常執(zhí)行接口邏輯
        try {
            return joinPoint.proceed();
        } finally {
            // 可選:非冪等接口執(zhí)行完手動釋放鎖(冪等接口可依賴自動過期)
            // stringRedisTemplate.delete(requestKey);
        }
    }
    // 生成唯一請求標(biāo)識:避免不同用戶/不同參數(shù)被誤判為重復(fù)
    private String generateRequestKey(ProceedingJoinPoint joinPoint, Method method) {
        // 獲取用戶ID(實際項目從Token/上下文獲取,這里簡化)
        String userId = "anonymous"; // 替換為真實用戶標(biāo)識
        // 獲取接口名(類名+方法名)
        String methodName = method.getDeclaringClass().getName() + "." + method.getName();
        // 獲取參數(shù)摘要(避免參數(shù)不同但被誤判,用MD5加密)
        String paramDigest = DigestUtils.md5DigestAsHex(
                (joinPoint.getArgs() != null ? joinPoint.getArgs().toString() : "").getBytes(StandardCharsets.UTF_8)
        );
        // 拼接key:redis key前綴+用戶ID+接口名+參數(shù)摘要
        return "anti_duplicate:" + userId + ":" + methodName + ":" + paramDigest;
    }
}
  1. 接口使用(只需加注解)
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
    // 下單接口:1秒內(nèi)禁止重復(fù)提交
    @AntiDuplicateSubmit(timeout = 1, message = "下單太頻繁啦,1秒后再試~")
    @PostMapping("/api/order/create")
    public String createOrder(@RequestBody OrderDTO orderDTO) {
        // 下單邏輯(省略)
        return "下單成功,訂單號:" + System.currentTimeMillis();
    }
}

八年踩坑提示

  • 過期時間別設(shè)太短(比如小于 500ms):網(wǎng)絡(luò)延遲可能導(dǎo)致正常請求被誤判;也別設(shè)太長(比如超過 10 秒):用戶正常重試會被攔截;
  • 請求標(biāo)識必須包含 “用戶 ID”:否則不同用戶調(diào)用同一接口會被誤判為重復(fù);
  • 非冪等接口(比如退款)建議執(zhí)行完手動釋放鎖:避免正常流程結(jié)束后還占用鎖。

適用場景:分布式系統(tǒng)、高并發(fā)場景(電商大促、支付接口)

方案 2:基于 Token 令牌(前后端聯(lián)動,最安全)

核心原理

前端請求接口前,先向服務(wù)端申請 “唯一令牌”,服務(wù)端生成令牌存入 Redis;前端帶著令牌調(diào)用業(yè)務(wù)接口,服務(wù)端驗證令牌存在后執(zhí)行邏輯,并刪除令牌(確保只能用一次)。

為什么安全?

令牌是一次性的,且綁定用戶,即使接口被爬蟲抓取,沒有令牌也無法重復(fù)提交 —— 這是防御 “惡意刷接口” 的終極方案。

實戰(zhàn)代碼

  1. Token 生成接口(前端先調(diào)用獲取令牌)
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@RestController
public class TokenController {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    // 生成防重令牌(前端調(diào)用接口前先獲取)
    @GetMapping("/api/token/get")
    public String getAntiDuplicateToken() {
        // 生成UUID作為令牌
        String token = "anti_duplicate_token:" + UUID.randomUUID().toString().replace("-", "");
        // 存入Redis,過期時間5分鐘(根據(jù)業(yè)務(wù)調(diào)整)
        stringRedisTemplate.opsForValue().set(token, "1", 5, TimeUnit.MINUTES);
        return token;
    }
}
  1. 令牌驗證切面(可復(fù)用方案 1 的注解,新增驗證邏輯)
// 在AntiDuplicateSubmitAspect的around方法中新增Token驗證邏輯
private void validateToken(HttpServletRequest request) {
    String token = request.getHeader("Anti-Duplicate-Token");
    if (StringUtils.isEmpty(token)) {
        throw new RuntimeException("缺少防重令牌,請先獲取令牌!");
    }
    // 驗證令牌是否存在,存在則刪除(一次性使用)
    Boolean exists = stringRedisTemplate.delete(token);
    if (exists == null || !exists) {
        throw new RuntimeException("令牌無效或已過期!");
    }
}
  1. 前端調(diào)用流程(偽代碼)
// 1. 先獲取令牌
fetch('/api/token/get').then(res => res.text()).then(token => {
    // 2. 帶著令牌調(diào)用下單接口
    fetch('/api/order/create', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Anti-Duplicate-Token': token // 令牌放在請求頭
        },
        body: JSON.stringify({orderNo: 'xxx', amount: 100})
    });
});

八年踩坑提示

  • 令牌過期時間要合理:太短(比如 1 分鐘)用戶操作慢會失效,太長(比如 30 分鐘)占用 Redis 內(nèi)存;
  • 前端要處理令牌失效:如果調(diào)用業(yè)務(wù)接口時提示令牌過期,需重新獲取令牌再重試;
  • 建議和方案 1 結(jié)合:令牌驗證 + Redis 限時鎖,雙重防護(hù)更穩(wěn)妥。

適用場景:支付接口、退款接口等核心敏感接口

方案 3:基于本地緩存(Caffeine)(單機高并發(fā)首選)

核心原理

如果是單機部署的應(yīng)用,沒必要用 Redis,直接用本地緩存(Caffeine)存儲請求標(biāo)識,效率更高(本地緩存響應(yīng)時間微秒級)。

為什么用 Caffeine?

Caffeine 是 Java 領(lǐng)域性能最好的本地緩存,支持過期時間、最大容量限制,比 HashMap + 定時任務(wù)更優(yōu)雅,比 Guava Cache 性能高 5-10 倍。

實戰(zhàn)代碼

  1. 引入 Caffeine 依賴(SpringBoot 3.x)
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.8</version>
</dependency>
  1. 配置 Caffeine 緩存
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
public class CaffeineConfig {
    @Bean
    public CacheManager antiDuplicateCacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        // 配置緩存:最大容量10萬(防止內(nèi)存溢出),過期時間1秒
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .maximumSize(100000)
                .expireAfterWrite(1, TimeUnit.SECONDS));
        return cacheManager;
    }
}
  1. 改造切面(用本地緩存替代 Redis)
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
// 在AntiDuplicateSubmitAspect中注入本地緩存管理器
@Resource(name = "antiDuplicateCacheManager")
private CacheManager cacheManager;
// 替換Lua腳本邏輯,用本地緩存實現(xiàn)
private boolean checkLocalCache(String requestKey) {
    Cache cache = cacheManager.getCache("antiDuplicateCache");
    if (cache == null) {
        throw new RuntimeException("本地緩存初始化失??!");
    }
    // 查緩存:存在則返回true(重復(fù)),不存在則存入緩存
    if (cache.get(requestKey) != null) {
        return true;
    }
    cache.put(requestKey, "1");
    return false;
}

八年踩坑提示

  • 必須設(shè)置最大容量:避免惡意請求導(dǎo)致緩存無限增長,引發(fā) OOM;
  • 僅適用于單機部署:多實例部署會出現(xiàn)緩存不一致,導(dǎo)致重復(fù)提交;
  • 過期時間要短:本地緩存不支持分布式過期,太長會占用內(nèi)存。

適用場景:單機部署、高并發(fā)讀少寫多的接口(比如查詢 + 提交類接口)

方案 4:基于數(shù)據(jù)庫唯一索引(兜底方案,最可靠)

核心原理

無論前端、緩存層防護(hù)得多好,數(shù)據(jù)庫層都要加 “最后一道防線”—— 給核心業(yè)務(wù)字段建唯一索引(比如訂單號、用戶 ID + 商品 ID),即使重復(fù)提交,數(shù)據(jù)庫也會拋出唯一約束異常,避免數(shù)據(jù)錯亂。

為什么是兜底?

緩存可能失效,令牌可能被繞過,但數(shù)據(jù)庫唯一索引是 “物理防護(hù)”,除非刪索引,否則絕對不會出現(xiàn)重復(fù)數(shù)據(jù) —— 八年開發(fā)的底線:核心業(yè)務(wù)必須加唯一索引!

實戰(zhàn)代碼

  1. 數(shù)據(jù)庫表設(shè)計(以訂單表為例)
CREATE TABLE `t_order` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `order_no` varchar(64) NOT NULL COMMENT '訂單號(唯一)',
  `user_id` bigint NOT NULL COMMENT '用戶ID',
  `product_id` bigint NOT NULL COMMENT '商品ID',
  `amount` decimal(10,2) NOT NULL COMMENT '金額',
  PRIMARY KEY (`id`),
  -- 唯一索引:訂單號唯一(防止重復(fù)下單)
  UNIQUE KEY `uk_order_no` (`order_no`),
  -- 聯(lián)合唯一索引:同一用戶不能同時買同一商品(根據(jù)業(yè)務(wù)需求)
  UNIQUE KEY `uk_user_product` (`user_id`,`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='訂單表';
  1. 業(yè)務(wù)代碼處理唯一約束異常
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
    // 捕獲數(shù)據(jù)庫唯一約束異常,返回友好提示
    @ExceptionHandler(DuplicateKeyException.class)
    public String handleDuplicateKeyException(DuplicateKeyException e) {
        log.error("重復(fù)提交導(dǎo)致唯一約束沖突:", e);
        return "操作失敗,請勿重復(fù)提交!";
    }
}

八年踩坑提示

  • 唯一索引要貼合業(yè)務(wù):別盲目建唯一索引,比如 “用戶 ID + 商品 ID” 適合 “限購一件” 的場景,“訂單號” 適合所有訂單唯一的場景;
  • 避免過度建索引:索引會影響插入性能,核心字段才需要;
  • 異常信息要脫敏:別把數(shù)據(jù)庫表結(jié)構(gòu)、字段名暴露給前端。

適用場景:所有核心業(yè)務(wù)接口(支付、下單、退款),作為兜底方案

方案 5:基于 AOP + 自定義注解(優(yōu)雅封裝,復(fù)用性強)

核心原理

把方案 1-4 的邏輯封裝成通用注解,業(yè)務(wù)接口只需加注解即可實現(xiàn)防抖,無需寫重復(fù)代碼 —— 這是八年開發(fā)的 “偷懶技巧”:一次封裝,處處復(fù)用。

進(jìn)階封裝:支持多場景切換

// 增強AntiDuplicateSubmit注解,支持選擇防抖方式
public @interface AntiDuplicateSubmit {
    // 防抖方式:REDIS/Local_CACHE/TOKEN
    Mode mode() default Mode.REDIS;
    long timeout() default 1;
    TimeUnit unit() default TimeUnit.SECONDS;
    String message() default "操作過于頻繁,請稍后再試!";
    enum Mode {
        REDIS, LOCAL_CACHE, TOKEN
    }
}

改造切面:根據(jù)注解模式選擇防抖方案

@Around("@annotation(antiDuplicateSubmit)")
public Object around(ProceedingJoinPoint joinPoint, AntiDuplicateSubmit antiDuplicateSubmit) throws Throwable {
    String requestKey = generateRequestKey(joinPoint, antiDuplicateSubmit.method());
    AntiDuplicateSubmit.Mode mode = antiDuplicateSubmit.mode();
    // 根據(jù)模式選擇不同方案
    if (mode == AntiDuplicateSubmit.Mode.REDIS) {
        // Redis+Lua方案
        Long result = stringRedisTemplate.execute(antiDuplicateScript, Collections.singletonList(requestKey), String.valueOf(timeout));
        if (result != null && result == 1) {
            throw new RuntimeException(antiDuplicateSubmit.message());
        }
    } else if (mode == AntiDuplicateSubmit.Mode.LOCAL_CACHE) {
        // 本地緩存方案
        if (checkLocalCache(requestKey)) {
            throw new RuntimeException(antiDuplicateSubmit.message());
        }
    } else if (mode == AntiDuplicateSubmit.Mode.TOKEN) {
        // Token方案
        validateToken(request);
    }
    return joinPoint.proceed();
}

接口使用示例(按需選擇模式)

// 支付接口:用TOKEN模式(最安全)
@AntiDuplicateSubmit(mode = AntiDuplicateSubmit.Mode.TOKEN, message = "支付請求已提交,請勿重復(fù)操作!")
@PostMapping("/api/pay")
public String pay(@RequestBody PayDTO payDTO) { ... }
// 下單接口:用REDIS模式(分布式高并發(fā))
@AntiDuplicateSubmit(mode = AntiDuplicateSubmit.Mode.REDIS, timeout = 2)
@PostMapping("/api/order/create")
public String createOrder(@RequestBody OrderDTO orderDTO) { ... }
// 評論接口:用LOCAL_CACHE模式(單機部署)
@AntiDuplicateSubmit(mode = AntiDuplicateSubmit.Mode.LOCAL_CACHE)
@PostMapping("/api/comment/add")
public String addComment(@RequestBody CommentDTO commentDTO) { ... }

適用場景:全場景復(fù)用,大型項目推薦(減少重復(fù)開發(fā))

三、八年踩坑總結(jié):3 個致命錯誤別犯!

  1. 只做前端防抖,不做后端防護(hù):前端按鈕禁用能防 “手抖”,但防不住爬蟲、Postman 直接調(diào)用 —— 后端必須加防護(hù);
  2. 忽略冪等性設(shè)計:防抖是 “阻止調(diào)用”,防重是 “保證結(jié)果一致”,比如支付接口,即使防抖失效,重復(fù)調(diào)用也不能扣兩次錢;
  3. Redis 過期時間設(shè)置不合理:太短導(dǎo)致正常請求被誤判,太長導(dǎo)致用戶無法重試 —— 建議根據(jù)業(yè)務(wù)調(diào)整,一般 1-5 秒。

四、選型指南:一張表選對方案

方案適用場景優(yōu)點缺點
Redis+Lua分布式、高并發(fā)性能高、支持分布式需部署 Redis
Token 令牌敏感接口(支付 / 退款)最安全、防惡意刷接口前后端聯(lián)動成本高
本地緩存(Caffeine)單機部署、高并發(fā)響應(yīng)快、無網(wǎng)絡(luò)開銷不支持分布式
數(shù)據(jù)庫唯一索引核心業(yè)務(wù)兜底最可靠、物理防護(hù)影響插入性能
AOP + 自定義注解大型項目、多場景復(fù)用性強、優(yōu)雅簡潔需提前封裝

一句話口訣:分布式用 Redis,敏感接口用 Token,單機用 Caffeine,核心業(yè)務(wù)加索引。

五、總結(jié)

八年開發(fā)經(jīng)驗告訴我:接口防抖不是 “炫技”,而是 “底線思維”。一套完善的防抖方案,應(yīng)該是 “前端按鈕禁用 + 后端多重防護(hù) + 數(shù)據(jù)庫兜底” 的組合拳 —— 前端防普通用戶,后端防惡意攻擊,數(shù)據(jù)庫防所有漏網(wǎng)之魚。

本文的 5 種方案,從單機到分布式,從臨時防護(hù)到長期復(fù)用,覆蓋了所有場景,代碼都經(jīng)過實際項目驗證,可直接復(fù)制使用。如果你的項目還在被重復(fù)提交困擾,不妨根據(jù)業(yè)務(wù)場景選擇合適的方案,早日實現(xiàn) “接口防抖自由”。

到此這篇關(guān)于SpringBoot接口防抖實戰(zhàn)之防重復(fù)提交的5種高級方案的文章就介紹到這了,更多相關(guān)SpringBoot接口防重復(fù)提交內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Activiti7與Spring以及Spring Boot整合開發(fā)

    Activiti7與Spring以及Spring Boot整合開發(fā)

    這篇文章主要介紹了Activiti7與Spring以及Spring Boot整合開發(fā),在Activiti中核心類的是ProcessEngine流程引擎,與Spring整合就是讓Spring來管理ProcessEngine,有感興趣的同學(xué)可以參考閱讀
    2023-03-03
  • SpringBoot集成slf4j2日志配置的實現(xiàn)示例

    SpringBoot集成slf4j2日志配置的實現(xiàn)示例

    本文主要介紹了SpringBoot集成slf4j2日志配置的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • eclipse創(chuàng)建一個基于maven的web項目詳細(xì)步驟

    eclipse創(chuàng)建一個基于maven的web項目詳細(xì)步驟

    開始學(xué)習(xí)maven,并用maven創(chuàng)建了第一個屬于自己的web項目,下面這篇文章主要給大家介紹了關(guān)于eclipse創(chuàng)建一個基于maven的web項目的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • JAVA之讀取properties時路徑的注意問題

    JAVA之讀取properties時路徑的注意問題

    這篇文章主要介紹了JAVA之讀取properties時路徑的注意問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • SpringBoot項目中使用WebSocket實現(xiàn)實時通信功能

    SpringBoot項目中使用WebSocket實現(xiàn)實時通信功能

    在傳統(tǒng)的 HTTP 通信中,客戶端發(fā)起請求,服務(wù)器給出響應(yīng),一次通信就此結(jié)束,這種模式對于靜態(tài)頁面展示完全夠用,但對于需要實時推送的場景,就力不從心了,因此本文介紹了在SpringBoot項目中使用WebSocket實現(xiàn)實時通信功能,需要的朋友可以參考下
    2026-03-03
  • JAVA雙親委派機制詳解及實際應(yīng)用場景

    JAVA雙親委派機制詳解及實際應(yīng)用場景

    雙親委派機制是Java類加載器加載類時的一種策略,這篇文章主要介紹了JAVA雙親委派機制的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-08-08
  • java協(xié)變返回類型使用示例

    java協(xié)變返回類型使用示例

    在面向?qū)ο蟪绦蛟O(shè)計中,協(xié)變返回類型指的是子類中的成員函數(shù)的返回值類型不必嚴(yán)格等同于父類中被重寫的成員函數(shù)的返回值類型,而可以是更"狹窄"的類型
    2014-02-02
  • Spring Boot 與 Tomcat 錯誤頁面處理機制全面解析

    Spring Boot 與 Tomcat 錯誤頁面處理機制全面解析

    本文給大家介紹Spring Boot 如何與內(nèi)嵌 Tomcat 協(xié)作,實現(xiàn)高效、靈活的錯誤頁面處理機制,通過分析核心源碼,我們將揭示這一機制背后的設(shè)計哲學(xué)和實現(xiàn)細(xì)節(jié),感興趣的朋友跟隨小編一起看看吧
    2024-12-12
  • SpringBoot2 集成log4j2日志框架的實現(xiàn)

    SpringBoot2 集成log4j2日志框架的實現(xiàn)

    這篇文章主要介紹了SpringBoot2 集成log4j2日志框架的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Java Collection集合用法詳解

    Java Collection集合用法詳解

    首先Collection是屬于單列集合的頂層接口,表示為一組對象。其類型為引用數(shù)據(jù)類型,具體創(chuàng)建對象,通過多態(tài)的形式進(jìn)行,本文將給大家詳細(xì)的介紹,需要的朋友可以參考下
    2021-10-10

最新評論

苗栗市| 渝中区| 崇义县| 张掖市| 宾阳县| 凯里市| 正定县| 东明县| 定州市| 松溪县| 广安市| 湘西| 修武县| 涿鹿县| 渝中区| 石柱| 精河县| 柳州市| 赤水市| 高州市| 古交市| 玛纳斯县| 噶尔县| 灵武市| 天镇县| 乾安县| 保亭| 日土县| 红河县| 汪清县| 高阳县| 南木林县| 始兴县| 黑龙江省| 清徐县| 神农架林区| 桐柏县| 乌拉特前旗| 中方县| 临夏县| 汤阴县|