使用SpringBoot、Redis和拦截器实现接口自动幂等
74 浏览量
更新于2024-09-01
1
收藏 323KB PDF 举报
SpringBoot+Redis+Interceptor+自定义Annotation实现接口自动幂等
在实际的开发项目中,一个对外暴露的接口往往会面临很多次请求,这种情况下,如何保证接口的幂等性成为一个非常重要的问题。幂等性是指任意多次执行所产生的影响均与一次执行的影响相同。在本篇文章中,我们将介绍使用 SpringBoot 和 Redis 实现接口自动幂等的方法。
首先, lets 回顾一下幂等性的概念。幂等性是指任意多次执行所产生的影响均与一次执行的影响相同。这意味着,对数据库的影响只能是一次性的,不能重复处理。那么,如何保证幂等性呢?通常有以下几种方法:
1. 数据库建立唯一性索引,可以保证最终插入数据库的只有一条数据。
2. Token 机制,每次接口请求前先获取一个 Token,然后再下次请求的时候在请求的 Header 体中加上这个 Token,后台进行验证,如果验证通过删除 Token,下次请求再次判断 Token。
3. 悲观锁或者乐观锁,悲观锁可以保证每次 for update 的时候其他 SQL 无法 update 数据(在数据库引擎是 InnoDB 的时候,select 的条件必须是唯一索引,防止锁全表)。
4. 先查询后判断,首先通过查询数据库是否存在数据,如果存在证明已经请求过了,直接拒绝该请求,如果没有存在,就证明是第一次进来,直接放行。
下面,我们将介绍使用 SpringBoot 和 Redis 实现接口自动幂等的方法。
使用 Redis 实现自动幂等的原理图:
目录
一、搭建 Redis 的服务 API
首先,我们需要搭建 Redis 服务器,这个之前搭过了,就不赘述了。详情可参考:https://www.cnblogs.com/wyq178/p/10340234.html
引入 SpringBoot 中的 Redis 的 starter,或者 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, final String value) {
return redisTemplate.opsForValue().set(key, value);
}
// ...
Interceptor 的实现
使用自定义的 Annotation,我们可以实现接口自动幂等的功能。首先,我们需要定义一个 Annotation:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {
String value();
}
然后,我们需要实现一个 Interceptor,用于拦截接口的请求:
@Component
public class IdempotentInterceptor implements HandlerInterceptor {
@Autowired
private RedisService redisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取 Token
String token = request.getHeader("token");
if (token == null) {
throw new RuntimeException("Token 不能为空");
}
// 检查 Token 是否存在
if (redisService.exists(token)) {
// 如果 Token 存在,证明已经请求过了,直接拒绝该请求
throw new RuntimeException("已经请求过了");
} else {
// 如果 Token 不存在,证明是第一次进来,直接放行
redisService.set(token, "1");
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 删除 Token
String token = request.getHeader("token");
redisService.delete(token);
}
}
使用上述实现,我们可以在 Controller 中使用 @Idempotent 注解来标记需要幂等的接口:
@Idempotent("token")
@RequestMapping("/api/test")
public String test() {
// ...
}
这样,我们就可以使用 SpringBoot 和 Redis 实现接口自动幂等的功能。
2020-08-25 上传
2019-04-14 上传
2019-01-17 上传
149 浏览量
2020-08-31 上传
2024-05-17 上传
2024-05-04 上传
2024-09-19 上传
weixin_38551187
- 粉丝: 3
- 资源: 908
最新资源
- 毕业设计&课设-仿真工具箱(MATLAB).zip
- flutter.widgets
- Greentask-crx插件
- Wrappit:用于在PacketWrapper中生成数据包类的程序
- matlab求导代码-rsHRF:从BOLD-fMRI信号估计静止状态HRF
- FakeSunCompany-Website
- 基于halcon的旋转中心仿真测试.rar
- NeoClient:Neo4j的轻量级OGM,支持事务和BOLT协议
- 毕业设计&课设-根据系统要求配置FMCW波形。然后定义目标的范围和速度,并模拟其位移….zip
- PythonKit:与 Python 交互的 Swift 框架
- react-weather-app:SheCodes React最终项目
- Divi Builder guide-crx插件
- 小游戏-天天消消乐(附带源码)
- junior-programming:我的初中生及其项目的资料库
- gateway-nacos-sleuth.7z
- design-pattern:Java设计模式,和简书的https