这篇“springboot如何实现接口自动幂等”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“springboot如何实现接口自动幂等”文章吧。
1.概念: 任意多次执行所产生的影响均与一次执行的影响相同。
按照这个含义,最终的含义就是 对数据库的影响只能是一次性的,不能重复处理。如何保证其幂等性,通常有以下手段:
1: 数据库建立唯一性索引,可以保证最终插入数据库的只有一条数据
2: token 机制,每次接口请求前先获取一个 token,然后再下次请求的时候在请求的 header 体中加上这个 token,后台进行验证,如果验证通过删除 token,下次请求再次判断 token
3: 悲观锁或者乐观锁,悲观锁可以保证每次 for update 的时候其他 sql 无法 update 数据 (在数据库引擎是 innodb 的时候, select 的条件必须是唯一索引, 防止锁全表)
4: 先查询后判断,首先通过查询数据库是否存在数据,如果存在证明已经请求过了,直接拒绝该请求,如果没有存在,就证明是第一次进来,直接放行。
redis 实现自动幂等的原理图:
1: 首先是搭建 redis 服务器。
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; } }
自定义一个注解,定义此注解的主要目的是把它添加在需要实现幂等的方法上,凡是某个方法注解了它,都会实现自动幂等。后台利用反射如果扫描到这个注解,就会处理这个方法实现自动幂等,使用元注解 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 服务,里面主要是两个方法,一个用来创建 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; }
token 引用了 redis 服务,创建 token 采用随机算法工具类生成随机 uuid 字符串, 然后放入到 redis 中 (为了防止数据的冗余保留, 这里设置过期时间为 10000 秒, 具体可视业务而定),如果放入成功,最后返回这个 token 值。checkToken 方法就是从 header 中获取 token 到值 (如果 header 中拿不到,就从 paramter 中获取),如若不存在, 直接抛出异常。这个异常信息可以被拦截器捕捉到,然后返回给前端。
以上就是关于“springboot如何实现接口自动幂等”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。