springboot+redis+Interceptor+自定义annotation实现接口自动幂等
2021/7/20 19:37:26
本文主要是介绍springboot+redis+Interceptor+自定义annotation实现接口自动幂等,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
幂等
1.概念: 任意多次执行所产生的影响均与一次执行的影响相同。
按照这个含义,最终的含义就是 对数据库的影响只能是一次性的,不能重复处理。如何保证其幂等性,通常有以下手段:
1: 数据库建立唯一性索引,可以保证最终插入数据库的只有一条数据
2: token 机制,每次接口请求前先获取一个 token,然后再下次请求的时候在请求的 header 体中加上这个 token,后台进行验证,如果验证通过删除 token,下次请求再次判断 token
3: 悲观锁或者乐观锁,悲观锁可以保证每次 for update 的时候其他 sql 无法 update 数据 (在数据库引擎是 innodb 的时候, select 的条件必须是唯一索引, 防止锁全表)
4: 先查询后判断,首先通过查询数据库是否存在数据,如果存在证明已经请求过了,直接拒绝该请求,如果没有存在,就证明是第一次进来,直接放行。
redis 实现自动幂等的原理图:
一. 搭建redis的服务Api
1: 首先是搭建 redis 服务器。详情可参考:https://www.cnblogs.com/wyq178/p/10340234.html
2: 引入 springboot 中到的 redis 的 stater,或者 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,Object value){ boolean result = false; try { ValueOperations<Serializable,Object> operations = redisTemplate.opsForValue(); operations.set(key,value); result = true; }catch (Exception e){ result = false; e.printStackTrace(); } return result; } /** * 写入缓存有效期 * @return */ public boolean setEx(final String key ,Object value,Long expireTime){ boolean result = false; try { ValueOperations<Serializable,Object> operations = redisTemplate.opsForValue(); operations.set(key,value); redisTemplate.expire(key,expireTime, TimeUnit.SECONDS);//有效期 result = true; }catch (Exception e){ result = false; e.printStackTrace(); } return result; } /** * 判断缓存中是否有对应的value * @param key * @return */ public boolean exists(final String key){ return redisTemplate.hasKey(key); } /** * 读取缓存 * @param key * @return */ public Object get(final String key){ Object obj = null; ValueOperations<Serializable,Object> operations= redisTemplate.opsForValue(); obj = operations.get(key); return obj; } /** * 删除对应的value * @param key * @return */ public boolean remvoe(final String key){ if(exists(key)){ Boolean delete = redisTemplate.delete(key); return delete; } return false; } }
二.自定义 AutoIdempotent
自定义一个注解,定义此注解的主要目的是把它添加在需要实现幂等的方法上,凡是某个方法注解了它,都会实现自动幂等。后台利用反射如果扫描到这个注解,就会处理这个方法实现自动幂等,使用元注解 ElementType.METHOD 表示它只能放在方法上,etentionPolicy.RUNTIME 表示它在运行时
package com.yxkj.springboot_redis_interceptor.annotion; 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 AutoIdempotent { }
三. token 创建和检验
1.token服务接口
我们新建一个接口,创建 token 服务,里面主要是两个方法,一个用来创建 token,一个用来验证 token。创建 token 主要产生的是一个字符串,检验 token 的话主要是传达 request 对象,为什么要传 request 对象呢?主要作用就是获取 header 里面的 token, 然后检验,通过抛出的 Exception 来获取具体的报错信息返回给前端
public interface TokenService { /** * 创建token * @return */ String createToken(); /** * 检验token的合法性 * @param request * @return * @throws Exception */ boolean checkToken(HttpServletRequest request) throws Exception; }
2.token 的服务实现类
token 引用了 redis 服务,创建 token 采用随机算法工具类生成随机 uuid 字符串, 然后放入到 redis 中 (为了防止数据的冗余保留, 这里设置过期时间为 10000 秒, 具体可视业务而定),如果放入成功,最后返回这个 token 值。checkToken 方法就是从 header 中获取 token 到值 (如果 header 中拿不到,就从 paramter 中获取),如若不存在, 直接抛出异常。这个异常信息可以被拦截器捕捉到,然后返回给前端。
这篇关于springboot+redis+Interceptor+自定义annotation实现接口自动幂等的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-19Java前端后端分离学习指南
- 2024-11-19Java全栈学习:从入门到实践
- 2024-11-19Java微服务系统学习入门指南
- 2024-11-19Java微服务学习:入门与实践指南
- 2024-11-19Java学习:初学者必备指南
- 2024-11-19Java医疗系统学习:从入门到初级实战教程
- 2024-11-19SpringCloud Alibaba入门教程:轻松搭建微服务架构
- 2024-11-19SSM框架入门教程:轻松搭建Java企业级应用
- 2024-11-19订单系统学习:新手入门指南
- 2024-11-19读写分离学习:轻松入门与实战指南