开源软件名称:formula-distribution
开源软件地址:https://gitee.com/small_brick_team/formula-distribution
开源软件介绍:
分布式策略1.分布式缓存- 由于spring cache 缓存框架只能设置默认的缓存失效时间,不灵活所以 增加@cacheExpireTime 注解来为每个缓存 增加失效时间 <目前只适用于采用redis缓存的时候>
- @CacheExpireTime 注解
2.1 作用域 2.1.1 类上 为当前类下的所有使用@Cacheable注解的缓存方法,但是未使用@CacheExpireTime注解的方法增加默认的失效注解。
2.1.2 方法上 为当前方法设置失效时间
2.2 使用:
2.2.1 value 值 默认为0L, 可以用来设置固定的失效时间,当为默认值的时候,此注解不生效
2.2.2 @Random 注解设置随机值 为了防止缓存大批量的失效,一般想将缓存的失效时间设置为随机值,min 为最小值,max为最大值,min,max值不能小于0,max值必须大于0,且大于min值
3.使用
@Bean CacheManager cacheManager(RedisConnectionFactory connectionFactory) { //初始化一个RedisCacheWriter RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig(); //设置默认超过期时间 RedisCacheConfiguration configuration = defaultCacheConfig.entryTtl(Duration.ofSeconds(100000)); FormulaCacheManager cacheManager = new FormulaCacheManager(redisCacheWriter, configuration); return cacheManager; } 2. 分布式锁 @Override @Lock(keys = {"#params"}, waitTime = 10, leaseTime = 10) public String getValue(String params) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } return "success"; } @Override @Lock(keys = {"#id"}) public String getValue(Integer id, @LockParam String username) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } return "success"; } @Override @Lock(keys = {"#user.name", "#user.id"}) public String getValue(User user) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } return "success"; } 3. 分布式限流3.1 使用@EnableRateLimit 开启限流开关在方法上使用 @RateLimit 注解进行限流
3.2 默认使用计数器算法, 想切换使用令牌桶算法的使用,在配置文件中加入:rateLimit.algorithm= token另外关注 @RateLimit中的两个属性
/** * 向令牌桶中添加数据的时间间隔,以秒为单位。默认值10秒 */ public long tokenBucketTimeInterval() default 10; /** * 每次为令牌桶中添加的令牌数量。默认值5个 */ public long tokenBucketStepNum() default 5; 示例: @GetMapping("find/id2") @RateLimit(limit = 20) public User findById2(@RequestParam("id") Integer id) { return userService.findById2(id); } 4. 防重复提交保证接口的幂等性(用户对于统一操作发起的一次请求或者多次请求的结果是一致的) token机制 请求时首先获取token @PostMapping("get/token") public String getToken() { log.info("获取TOKEN"); String token = KEY_NAME + System.currentTimeMillis(); stringRedisTemplate.opsForValue().set(token, token, TIME_OUT, TimeUnit.SECONDS); return null; } 再请求业务接口 @PostMapping("idempotent") @ExtApiIdempotent(Constants.HEAD) public String idempotent() { log.info("接口幂等性测试"); return null; } 5.短链接生成6. 请求返回加密6.1 启用@SpringBootApplication@EnableEncryptpublic class FormulaDistributionExampleApplication { public static void main(String[] args) { SpringApplication.run(FormulaDistributionExampleApplication.class, args);} } 6.2 增加加密的keyspring.formula.encrypt.key=abcdef0123456789spring.formula.encrypt.debug=false spring.formula.encrypt.key:加密key,必须是16位spring.formula.encrypt.debug:是否开启调试模式,默认为false,如果为true则不启用加解密操作
6.3 响应结果加密 @PostMapping("Encrypt") @Encrypt public String Encrypt(@RequestBody User user) { return JSON.toJSONString(user); } 6.4 请求内容解密 @PostMapping("Decrypt") @Decrypt public String Decrypt(@RequestBody User user) { return JSON.toJSONString(user); } 6.5 axios 实现 ``` var key = CryptoJS.enc.Latin1.parse('abcdef0123456789'); var iv = CryptoJS.enc.Latin1.parse('abcdef0123456789'); // 加密 function EncryptData(data) { var srcs = CryptoJS.enc.Utf8.parse(data); var encrypted = CryptoJS.AES.encrypt(srcs, key, { mode : CryptoJS.mode.ECB, padding : CryptoJS.pad.Pkcs7 }); return encrypted.toString(); } // 解密 function DecryptData(data) { var stime = new Date().getTime(); var decrypt = CryptoJS.AES.decrypt(data, key, { mode : CryptoJS.mode.ECB, padding : CryptoJS.pad.Pkcs7 }); var result = JSON.parse(CryptoJS.enc.Utf8.stringify(decrypt).toString()); var etime = new Date().getTime(); console.log("DecryptData Time:" + (etime - stime)); return result; } // 添加请求拦截器 axios.interceptors.request.use(function (config) { // 对所有POST请加密,必须是json数据提交,不支持表单 if (config.method == "post") { config.data = EncryptData(JSON.stringify(config.data)); } return config; }, function (error) { return Promise.reject(error); }); // 添加响应拦截器 axios.interceptors.response.use(function (response) { // 后端返回字符串表示需要解密操作 if(typeof(response.data) == "string"){ response.data = DecryptData(response.data); } return response; }, function (error) { return Promise.reject(error); }); ``` |
请发表评论