Spring Boot 結(jié)合 Google Guava 緩存機(jī)制實(shí)現(xiàn)防重復(fù)提交策略
在Web應(yīng)用中,防重復(fù)提交是一個(gè)常見的需求,特別是在表單提交和訂單處理中。如果前端沒(méi)有進(jìn)行防重復(fù)提交的處理,用戶可能會(huì)因?yàn)榫W(wǎng)絡(luò)延遲或誤操作導(dǎo)致多次提交,從而生成重復(fù)的數(shù)據(jù)記錄。為了解決這個(gè)問(wèn)題,可以在后端實(shí)現(xiàn)防重復(fù)提交的機(jī)制。本文將介紹如何在Spring Boot應(yīng)用中使用Google Guava緩存來(lái)實(shí)現(xiàn)這一功能。
1. 添加Google Guava依賴
首先,需要在Spring Boot項(xiàng)目的pom.xml文件中添加Google Guava的依賴。Google Guava是一個(gè)強(qiáng)大的Java庫(kù),提供了豐富的集合類、緩存機(jī)制、原生類型支持等特性。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
2. 創(chuàng)建緩存配置類
接下來(lái),需要?jiǎng)?chuàng)建一個(gè)配置類來(lái)初始化Guava緩存。在這個(gè)配置類中,定義一個(gè)Bean來(lái)創(chuàng)建并配置緩存。
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
public class CacheConfig {
@Bean
public Cache<String, String> requestCache() {
return CacheBuilder.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES) // 設(shè)置緩存過(guò)期時(shí)間
.build();
}
}
3. 創(chuàng)建防重復(fù)提交攔截器
然后,創(chuàng)建一個(gè)攔截器來(lái)檢查請(qǐng)求是否重復(fù)。這個(gè)攔截器會(huì)實(shí)現(xiàn)HandlerInterceptor接口,并在preHandle方法中判斷請(qǐng)求是否已經(jīng)被緩存。
import com.google.common.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class DuplicateSubmissionInterceptor implements HandlerInterceptor {
@Autowired
private Cache<String, String> requestCache;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String key = generateKey(request);
if (key != null && requestCache.getIfPresent(key) != null) {
response.setStatus(HttpServletResponse.SC_CONFLICT); // 409 Conflict
return false;
} else {
requestCache.put(key, "");
return true;
}
}
private String generateKey(HttpServletRequest request) {
// 根據(jù)請(qǐng)求生成唯一鍵,例如可以根據(jù)URL和參數(shù)生成MD5值
String url = request.getRequestURI();
String queryString = request.getQueryString();
return url + (queryString != null ? "?" + queryString : "");
}
}
4. 注冊(cè)攔截器
最后,需要將攔截器注冊(cè)到Spring MVC中。在配置類中實(shí)現(xiàn)WebMvcConfigurer接口,并在addInterceptors方法中將攔截器添加到攔截器注冊(cè)表中。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private DuplicateSubmissionInterceptor duplicateSubmissionInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(duplicateSubmissionInterceptor).addPathPatterns("/**"); // 對(duì)所有請(qǐng)求進(jìn)行攔截
}
}
總結(jié)
通過(guò)以上步驟,已經(jīng)成功實(shí)現(xiàn)了一個(gè)基于Google Guava緩存的防重復(fù)提交功能。利用Guava緩存的高效性和簡(jiǎn)潔性,能夠有效地防止短時(shí)間內(nèi)的重復(fù)請(qǐng)求。你可以根據(jù)實(shí)際需求調(diào)整緩存的過(guò)期時(shí)間和生成唯一鍵的邏輯。
這種方法不僅適用于表單提交,還可以用于任何需要防重復(fù)請(qǐng)求的場(chǎng)景。同時(shí),由于Guava緩存是內(nèi)存級(jí)別的緩存,性能較高,適用于單節(jié)點(diǎn)應(yīng)用。如果需要分布式部署,可以考慮使用Redis等分布式緩存來(lái)實(shí)現(xiàn)。