当前位置: 首页 > wzjs >正文

徐州建站义乌城市建设规划网站

徐州建站,义乌城市建设规划网站,我们网站的优势,苏州网上挂号预约平台12320说明 实现幂等性的方法有很多种&#xff0c;本次仅基于redisson锁进行处理 本次开发基于自行封装的redis开发组件&#xff0c;有兴趣的可以看下redis组件 代码编写 pom.xml引入redisson <dependency><groupId>org.redisson</groupId><artifactId>r…

说明

实现幂等性的方法有很多种,本次仅基于redisson锁进行处理
本次开发基于自行封装的redis开发组件,有兴趣的可以看下redis组件

代码编写

pom.xml引入redisson

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.39.0</version>
</dependency>

redisson相关配置

  • CusRedissonConfiguration(此次仅单体)
@Configuration
public class CusRedissonConfiguration {private final static String REDIS_ADDRESS_PATTERN = "%s://%s:%s";@Beanpublic RedissonClient singleRedissonClient(SingleProperties singleProperties) {Config config = new Config();config.useSingleServer().setAddress(String.format(REDIS_ADDRESS_PATTERN,BooleanUtils.isTrue(singleProperties.getEncryptEnabled()) ?RedisConstants.redisProtocol.ENCRYPT_REDIS : RedisConstants.redisProtocol.REDIS,singleProperties.getHost(), singleProperties.getPort())).setUsername(singleProperties.getUsername()).setPassword(singleProperties.getPassword());return Redisson.create(config);}@Bean@ConditionalOnProperty(prefix = "cus.redisson", name = "idempotent-default", havingValue = "true", matchIfMissing = true)public Idempotent idempotent(){return new DefaultIdempotentUtil();}}
  • CusRedissonConfiguration
@Configuration
public class CusRedissonConfiguration {private final static String REDIS_ADDRESS_PATTERN = "%s://%s:%s";@Beanpublic RedissonClient singleRedissonClient(SingleProperties singleProperties) {Config config = new Config();config.useSingleServer().setAddress(String.format(REDIS_ADDRESS_PATTERN,BooleanUtils.isTrue(singleProperties.getEncryptEnabled()) ?RedisConstants.redisProtocol.ENCRYPT_REDIS : RedisConstants.redisProtocol.REDIS,singleProperties.getHost(), singleProperties.getPort())).setUsername(singleProperties.getUsername()).setPassword(singleProperties.getPassword());return Redisson.create(config);}@Bean@ConditionalOnProperty(prefix = "cus.redisson", name = "idempotent-default", havingValue = "true", matchIfMissing = true)public Idempotent idempotent(){return new DefaultIdempotentUtil();}}
  • SingleProperties
@Component
@ConfigurationProperties(prefix = "cus.redisson.single-properties")
public class SingleProperties {private String host = RedisConstants.defaultRedisInfo.DEFAULT_IP;private String port = RedisConstants.defaultRedisInfo.DEFAULT_PORT;private String username;private String password;private Integer database = RedisConstants.defaultRedisInfo.DEFAULT_DATABASE;private Boolean encryptEnabled = false;public String getHost() {return host;}public void setHost(String host) {this.host = host;}public String getPort() {return port;}public void setPort(String port) {this.port = port;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Boolean getEncryptEnabled() {return encryptEnabled;}public void setEncryptEnabled(Boolean encryptEnabled) {this.encryptEnabled = encryptEnabled;}public Integer getDatabase() {return database;}public void setDatabase(Integer database) {this.database = database;}
}

lock代码编写

  • Lock
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Lock {//锁键String lockKey();//等待时间long waitTime() default 60L;//自动释放时间long leaseTime();//时间单位TimeUnit timeUnit() default TimeUnit.SECONDS;//锁类型String lockType() default "FAIR";//校验lockKey是否存在boolean lockKeyExistFlag() default false;
}
  • LockAspect
    此处为核心处理代码,如果需要检验lockKey是否是被伪造的,可以将lockKeyExistFlag设置为true,由idempotent执行相关校验逻辑
    getLockKey可以视为通用方法,后续考虑放到core中
@Aspect
@Component
public class LockAspect {private final static Logger LOGGER = LoggerFactory.getLogger(LockAspect.class);private LockServiceFactory lockServiceFactory;private Idempotent idempotent;@Autowiredpublic void setLockServiceFactory(LockServiceFactory lockServiceFactory) {this.lockServiceFactory = lockServiceFactory;}@Autowiredpublic void setIdempotent(Idempotent idempotent) {this.idempotent = idempotent;}@Around("@annotation(lock)")public Object around(ProceedingJoinPoint joinPoint, Lock lock) throws Throwable {String lockKey = this.getLockKey(joinPoint, lock);if (StringUtils.isEmpty(lockKey)) {LOGGER.error("lockKey is empty");return null;}//校验lockKey是否是被伪造的,lockKey的生成和校验逻辑可以自定义if (lock.lockKeyExistFlag() && !idempotent.lockKeyExist(lockKey)) {LOGGER.error("the lockKey was forged");return null;}LockService lockService = lockServiceFactory.getLockServiceByType(lock.lockType());CusLockInfo cusLockInfo = new CusLockInfo();cusLockInfo.setLockKey(lockKey);cusLockInfo.setWaitTime(lock.waitTime());cusLockInfo.setLeaseTime(lock.leaseTime());cusLockInfo.setTimeUnit(lock.timeUnit());try {lockService.lock(cusLockInfo);if (!lockService.lock(cusLockInfo)) {throw new RuntimeException("Failed to acquire lock");}return joinPoint.proceed();} finally {//开启了伪造校验,结束后需进行清除if (lock.lockKeyExistFlag() && !idempotent.clear(lockKey)) {LOGGER.error("Verification resource lockKey clearance failed, lockKey value is{}", lockKey);}lockService.unLock(cusLockInfo);}}/*** 结合el表达式解析lockKey** @param joinPoint 切点* @param lock      锁信息* @return lockKey*/private String getLockKey(ProceedingJoinPoint joinPoint, Lock lock) {// 获取方法签名MethodSignature signature = (MethodSignature) joinPoint.getSignature();// 创建表达式解析器ExpressionParser parser = new SpelExpressionParser();// 创建评估上下文EvaluationContext context = new StandardEvaluationContext();// 将方法参数绑定到上下文中String[] paramNames = signature.getParameterNames();Object[] paramValues = joinPoint.getArgs();for (int i = 0; i < paramNames.length; i++) {context.setVariable(paramNames[i], paramValues[i]);}// 解析lockKey的值return parser.parseExpression(lock.lockKey()).getValue(context, String.class);}
}

lockKey相关逻辑

  • Idempotent
    实现类可自定义,yml中指定idempotent-default为false,自行注册Idempotent的自定义实现类即可
public interface Idempotent {/*** 创建唯一性lockKey** @param args 构建lockKey的参数* @return lockKey*/String createUniqueLockKey(String... args);/*** 校验lockKey是否存在(是否是伪造的)** @param lockKey lockKey* @return lockKey是否存在*/Boolean lockKeyExist(String lockKey);/*** 清除校验数据* @param lockKey lockKey* @return 是否清除成功*/Boolean clear(String lockKey);
}
  • DefaultIdempotentUtil
@Component
public class DefaultIdempotentUtil implements Idempotent {private final static Logger logger = LoggerFactory.getLogger(DefaultIdempotentUtil.class);private final static String PREFIX = "token_%s_%s";public final static String DEFAULT_SERVERNAME = "default";public final static String UNIQUE_FLAG = "true";public RedisHelper redisHelper;@Autowiredpublic void setRedisHelper(RedisHelper redisHelper) {this.redisHelper = redisHelper;}/*** 获取token的接口需要防止疯狂获取导致redis暴库** @param serverName 服务名* @return token*/public String createUniqueTokenWithServerName(String serverName) {serverName = Optional.ofNullable(serverName).orElse(DEFAULT_SERVERNAME);String uuid = UUID.randomUUID().toString();String uniqueToken = String.format(PREFIX, serverName, uuid);logger.debug("{} generate unique_token {}", serverName, uniqueToken);redisHelper.strSet(uniqueToken, UNIQUE_FLAG);return uniqueToken;}@Overridepublic String createUniqueLockKey(String... args) {// 确保至少有一个参数被提供if (args == null || args.length == 0) {throw new IllegalArgumentException("At least one argument is required.");}// 使用第一个参数作为serverNamereturn createUniqueTokenWithServerName(args[0]);}@Overridepublic Boolean lockKeyExist(String lockKey){return StringUtils.isNotEmpty(redisHelper.strGet(lockKey));}@Overridepublic Boolean clear(String lockKey) {return redisHelper.del(lockKey);}
}

yml相关配置

spring:redis:host: ipport: portdatabase: 1username: rootpassword: rootjedis:pool:# 资源池中最大连接数# 默认8,-1表示无限制;可根据服务并发redis情况及服务端的支持上限调整max-active: ${SPRING_REDIS_POOL_MAX_ACTIVE:50}# 资源池运行最大空闲的连接数# 默认8,-1表示无限制;可根据服务并发redis情况及服务端的支持上限调整,一般建议和max-active保持一致,避免资源伸缩带来的开销max-idle: ${SPRING_REDIS_POOL_MAX_IDLE:50}# 当资源池连接用尽后,调用者的最大等待时间(单位为毫秒)# 默认 -1 表示永不超时,设置5秒max-wait: ${SPRING_REDIS_POOL_MAX_WAIT:5000}
cus:redisson:single-properties:host: ipport: portusername: rootpassword: rootidempotent-default: true

参考资料

[1].redis代码


文章转载自:

http://8hTQLs3e.nrqnj.cn
http://7xODCC1z.nrqnj.cn
http://tnRePy9V.nrqnj.cn
http://wTxVReI5.nrqnj.cn
http://O1ZWVZRJ.nrqnj.cn
http://uFbytDIO.nrqnj.cn
http://mns6d6TX.nrqnj.cn
http://dGX1Oh2L.nrqnj.cn
http://fAcJLEpx.nrqnj.cn
http://MCRcdg6F.nrqnj.cn
http://Ek2Sl9kZ.nrqnj.cn
http://OZwhPGc9.nrqnj.cn
http://RRB51n0N.nrqnj.cn
http://1QDphOP7.nrqnj.cn
http://1p3dutGk.nrqnj.cn
http://DZwjTD3C.nrqnj.cn
http://T7Cu20OH.nrqnj.cn
http://U4LKJ9vx.nrqnj.cn
http://5kDHfyaM.nrqnj.cn
http://MQnfZcVT.nrqnj.cn
http://SGCjyvCf.nrqnj.cn
http://6Repeoid.nrqnj.cn
http://dYg12UVb.nrqnj.cn
http://bJFIEhgo.nrqnj.cn
http://MWBKY67m.nrqnj.cn
http://8nypSoi5.nrqnj.cn
http://b5OFzk3e.nrqnj.cn
http://h6FN8Axh.nrqnj.cn
http://cB5r35iY.nrqnj.cn
http://13vCLXca.nrqnj.cn
http://www.dtcms.com/wzjs/627690.html

相关文章:

  • 适合vue做的网站类型jfinal怎么做网站
  • 南宁世尊商贸网站建设谷歌seo培训
  • 模板网站定制网站html导入wordpress
  • 乐清柳市网站建设公司网站建设预付款如何付
  • 内网网站搭建教程网站用户后台是怎么做的
  • 河南大学学科建设处网站中国有什么网站做跨境零售
  • 免网站域名注册百度一下就知道官方网站
  • 集团网站群建设方案展示类网站管理员
  • 网站后台管理员做链接wordpress商品主图
  • 建设网站纳什么税软件快速开发平台
  • pc端和移动端的网站青岛手工活外发加工网
  • 网站建设助手 西部数码网站扩展名
  • 开封网站建设zducm网站搜索算法
  • 企业网站建设要素可以上传网站的免费空间
  • 网站建设优化佛山2018 84号建设厅网站
  • 个人建设什么网站好桂林生活网二手房市场
  • 深圳高端网站定制wordpress开启子目录多站点模式
  • 阿里云网站建设套餐湛江海田网站建设招聘
  • 网站开发手机自适应百度开发者中心
  • 凡客手机网站怎么建设白山seo
  • 自己搭建视频播放网站学校招聘教师网站建设
  • access做网站服务器电商网站变化
  • 企业网站改版seo深圳网页设计培训中心
  • 做彩票网站服务器做网站可以赚钱吗知乎
  • 购物网站难做吗怎么做电力设计公司网站
  • 关于文明网站建设存在的问题ps做网站首页效果特效
  • 兴义市建设局网站首页seo外链自动群发工具
  • 被墙的网站有哪些山西省智慧建筑信息平台
  • linux视频播放网站WordPress自动发英文文章
  • 一个公司为什么要做网站新能源 东莞网站建设