我们以评论系统为例: 要实现这个需求,你可以按照以下步骤来完成。我们将实现一个自定义注解、一个拦截器、以及在Redis中存储和更新幂等性计数。
步骤1:添加必要的依赖
确保在你的 pom.xml 文件中包含 Spring Boot 和 Redis 的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
步骤2:定义自定义注解
创建一个自定义注解,用于标记需要进行幂等性检查的Controller方法:
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 Idempotent {
long expireTime() default 60; // 默认过期时间,单位:秒
}
步骤3:创建幂等性检查的拦截器
创建一个拦截器,拦截带有 @Idempotent 注解的方法,并进行幂等性检查:
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
@Component
public class IdempotencyInterceptor implements HandlerInterceptor {
@Autowired
private StringRedisTemplate 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();
Idempotent idempotent = method.getAnnotation(Idempotent.class);
if (idempotent != null) {
// 获取当前用户ID
Principal principal = request.getUserPrincipal();
String username = principal.getName(); // 或从SecurityContext中获取
String comment = request.getParameter("comment");
// 生成Redis的Key
String key = "idempotent:" + username + ":" + comment;
Long expireTime = idempotent.expireTime();
// 检查Redis中是否存在
String value = redisTemplate.opsForValue().get(key);
if (value == null) {
// 不存在,存入Redis
redisTemplate.opsForValue().set(key, "1", expireTime, TimeUnit.SECONDS);
} else {
// 存在,进行计数
int count = Integer.parseInt(value);
if (count >= 3) {
// 超过次数限制
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.getWriter().write("重复评论已达到上限");
return false;
} else {
redisTemplate.opsForValue().increment(key);
}
}
}
}
return true;
}
}
步骤4:注册拦截器
在配置类中注册这个拦截器:
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 IdempotencyInterceptor idempotencyInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(idempotencyInterceptor).addPathPatterns("/**");
}
}
步骤5:在Controller方法上使用自定义注解
最后,在需要幂等性检查的方法上使用 @Idempotent 注解:
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/comments")
public class CommentController {
@PostMapping
@Idempotent(expireTime = 60)
public String addComment(@RequestBody CommentRequest commentRequest) {
// 处理添加评论的逻辑
return "评论添加成功";
}
}
总结
通过上述步骤,我们创建了一个自定义注解 @Idempotent,一个拦截器 IdempotencyInterceptor,并在拦截器中使用Redis进行幂等性检查。最后在需要检查幂等性的Controller方法上添加该注解即可实现功能。

2377

被折叠的 条评论
为什么被折叠?



