在Spring Boot项目中,通过Redis实现接口的幂等性通常是通过在Redis中存储唯一标识符(token、UUID等)的方式来实现。当接口第一次被调用时,生成并存储一个唯一标识符到Redis,然后将该标识符返回给客户端。客户端在后续的请求中携带该标识符,服务端在处理请求之前检查Redis中是否存在该标识符,如果存在,则认为是重复请求,直接返回之前的结果,如果不存在,则继续处理请求并存储标识符。
- 添加依赖
确保在pom.xml
中添加Redis依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置Redis连接信息
在application.properties
或application.yml
中配置Redis连接信息:
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.database=0
- 编写幂等性工具类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class IdempotenceUtil {
private static final String IDEMPOTENCE_KEY_PREFIX = "idempotence:";
@Autowired
private StringRedisTemplate redisTemplate;
public boolean isRequestProcessed(String requestId) {
return redisTemplate.hasKey(idempotenceKey(requestId));
}
public void markRequestProcessed(String requestId, long timeoutSeconds) {
redisTemplate.opsForValue().set(idempotenceKey(requestId), "processed", timeoutSeconds, TimeUnit.SECONDS);
}
private String idempotenceKey(String requestId) {
return IDEMPOTENCE_KEY_PREFIX + requestId;
}
}
- 实现幂等性的Controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class IdempotentController {
@Autowired
private IdempotenceUtil idempotenceUtil;
@PostMapping("/idempotent-operation")
public ResponseEntity<String> idempotentOperation(@RequestHeader("request-id") String requestId) {
// 检查是否已处理过该请求
if (idempotenceUtil.isRequestProcessed(requestId)) {
return ResponseEntity.ok("Operation already processed");
}
// 处理业务逻辑...
// 标记请求已处理
idempotenceUtil.markRequestProcessed(requestId, 60);
return ResponseEntity.ok("Operation processed successfully");
}
}
在上述示例中,IdempotenceUtil
类封装了检查和标记请求是否已处理的逻辑。IdempotentController
中的idempotentOperation
方法通过@RequestHeader
注解获取请求头中的唯一标识符(request-id),然后检查Redis中是否已处理过该请求,如果已处理,则返回结果,否则执行业务逻辑,标记请求已处理,并返回结果。