mirror of
				https://gitee.com/binary/weixin-java-tools.git
				synced 2025-10-30 18:19:04 +08:00 
			
		
		
		
	🎨 #1542 小程序模块配置类增加Redisson的实现,解决分布式锁问题
* 增加Redisson的实现,解决分布式锁问题 * key值重复添加了appid。 Co-authored-by: 袁启勋 <xun.yuan@infoship.cn>
This commit is contained in:
		| @ -80,6 +80,10 @@ | |||||||
|       <groupId>org.projectlombok</groupId> |       <groupId>org.projectlombok</groupId> | ||||||
|       <artifactId>lombok</artifactId> |       <artifactId>lombok</artifactId> | ||||||
|     </dependency> |     </dependency> | ||||||
|  |     <dependency> | ||||||
|  |       <groupId>org.redisson</groupId> | ||||||
|  |       <artifactId>redisson</artifactId> | ||||||
|  |     </dependency> | ||||||
|     <dependency> |     <dependency> | ||||||
|       <groupId>com.github.jedis-lock</groupId> |       <groupId>com.github.jedis-lock</groupId> | ||||||
|       <artifactId>jedis-lock</artifactId> |       <artifactId>jedis-lock</artifactId> | ||||||
|  | |||||||
| @ -0,0 +1,153 @@ | |||||||
|  | package cn.binarywang.wx.miniapp.config.impl; | ||||||
|  |  | ||||||
|  | import lombok.NonNull; | ||||||
|  | import me.chanjar.weixin.common.bean.WxAccessToken; | ||||||
|  | import me.chanjar.weixin.common.redis.RedissonWxRedisOps; | ||||||
|  | import me.chanjar.weixin.common.redis.WxRedisOps; | ||||||
|  | import org.apache.commons.lang3.StringUtils; | ||||||
|  | import org.redisson.api.RedissonClient; | ||||||
|  |  | ||||||
|  | import java.util.concurrent.TimeUnit; | ||||||
|  | import java.util.concurrent.locks.Lock; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 基于Redisson的实现 | ||||||
|  |  * | ||||||
|  |  * @author yuanqixun | ||||||
|  |  * @date 2020/5/3 | ||||||
|  |  */ | ||||||
|  | public class WxMaRedissonConfigImpl extends WxMaDefaultConfigImpl { | ||||||
|  |  | ||||||
|  |   protected final static String LOCK_KEY = "wechat_ma_lock:"; | ||||||
|  |   protected final static String MA_ACCESS_TOKEN_KEY = "wechat_ma_access_token_key:"; | ||||||
|  |   protected final static String MA_JSAPI_TICKET_KEY = "wechat_ma_jsapi_ticket_key:"; | ||||||
|  |   protected final static String MA_CARD_API_TICKET_KEY = "wechat_ma_card_api_ticket_key:"; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * redis 存储的 key 的前缀,可为空 | ||||||
|  |    */ | ||||||
|  |   /** | ||||||
|  |    * redis 存储的 key 的前缀,可为空 | ||||||
|  |    */ | ||||||
|  |   protected String keyPrefix; | ||||||
|  |   protected String accessTokenKey; | ||||||
|  |   protected String jsapiTicketKey; | ||||||
|  |   protected String cardApiTicketKey; | ||||||
|  |   protected String lockKey; | ||||||
|  |  | ||||||
|  |   private final WxRedisOps redisOps; | ||||||
|  |  | ||||||
|  |   public WxMaRedissonConfigImpl(@NonNull RedissonClient redissonClient, String keyPrefix) { | ||||||
|  |     this(new RedissonWxRedisOps(redissonClient), keyPrefix); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public WxMaRedissonConfigImpl(@NonNull RedissonClient redissonClient) { | ||||||
|  |     this(redissonClient, null); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private WxMaRedissonConfigImpl(@NonNull WxRedisOps redisOps, String keyPrefix) { | ||||||
|  |     this.redisOps = redisOps; | ||||||
|  |     this.keyPrefix = keyPrefix; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public void setAppid(String appid) { | ||||||
|  |     super.setAppid(appid); | ||||||
|  |     String prefix = StringUtils.isBlank(keyPrefix) ? "" : | ||||||
|  |       (StringUtils.endsWith(keyPrefix, ":") ? keyPrefix : (keyPrefix + ":")); | ||||||
|  |     lockKey = prefix + LOCK_KEY.concat(appid); | ||||||
|  |     accessTokenKey = prefix + MA_ACCESS_TOKEN_KEY.concat(appid); | ||||||
|  |     jsapiTicketKey = prefix + MA_JSAPI_TICKET_KEY.concat(appid); | ||||||
|  |     cardApiTicketKey = prefix + MA_CARD_API_TICKET_KEY.concat(appid); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected Lock getLockByKey(String key) { | ||||||
|  |     return redisOps.getLock(key); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public Lock getAccessTokenLock() { | ||||||
|  |     return getLockByKey(this.lockKey.concat(":").concat("accessToken")); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public Lock getCardApiTicketLock() { | ||||||
|  |     return getLockByKey(this.lockKey.concat(":").concat("cardApiTicket")); | ||||||
|  |  | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public Lock getJsapiTicketLock() { | ||||||
|  |     return getLockByKey(this.lockKey.concat(":").concat("jsapiTicket")); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public String getAccessToken() { | ||||||
|  |     return redisOps.getValue(this.accessTokenKey); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public boolean isAccessTokenExpired() { | ||||||
|  |     Long expire = redisOps.getExpire(this.accessTokenKey); | ||||||
|  |     return expire == null || expire < 2; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public void updateAccessToken(WxAccessToken accessToken) { | ||||||
|  |     redisOps.setValue(this.accessTokenKey, accessToken.getAccessToken(), accessToken.getExpiresIn(), TimeUnit.SECONDS); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public void updateAccessToken(String accessToken, int expiresInSeconds) { | ||||||
|  |     redisOps.setValue(this.accessTokenKey, accessToken, expiresInSeconds, TimeUnit.SECONDS); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public String getJsapiTicket() { | ||||||
|  |     return redisOps.getValue(this.jsapiTicketKey); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public boolean isJsapiTicketExpired() { | ||||||
|  |     Long expire = redisOps.getExpire(this.jsapiTicketKey); | ||||||
|  |     return expire == null || expire < 2; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public void expireJsapiTicket() { | ||||||
|  |     redisOps.expire(this.jsapiTicketKey, 0, TimeUnit.SECONDS); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { | ||||||
|  |     redisOps.setValue(this.jsapiTicketKey, jsapiTicket, expiresInSeconds, TimeUnit.SECONDS); | ||||||
|  |  | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public String getCardApiTicket() { | ||||||
|  |     return redisOps.getValue(cardApiTicketKey); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public boolean isCardApiTicketExpired() { | ||||||
|  |     Long expire = redisOps.getExpire(this.cardApiTicketKey); | ||||||
|  |     return expire == null || expire < 2; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public void expireCardApiTicket() { | ||||||
|  |     redisOps.expire(this.cardApiTicketKey, 0, TimeUnit.SECONDS); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) { | ||||||
|  |     redisOps.setValue(this.cardApiTicketKey, cardApiTicket, expiresInSeconds, TimeUnit.SECONDS); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public void expireAccessToken() { | ||||||
|  |     redisOps.expire(this.accessTokenKey, 0, TimeUnit.SECONDS); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,72 @@ | |||||||
|  | package cn.binarywang.wx.miniapp.config.impl; | ||||||
|  |  | ||||||
|  | import cn.binarywang.wx.miniapp.config.WxMaConfig; | ||||||
|  | import lombok.SneakyThrows; | ||||||
|  | import org.redisson.Redisson; | ||||||
|  | import org.redisson.api.RedissonClient; | ||||||
|  | import org.redisson.config.Config; | ||||||
|  | import org.redisson.config.TransportMode; | ||||||
|  | import org.testng.Assert; | ||||||
|  | import org.testng.annotations.AfterMethod; | ||||||
|  | import org.testng.annotations.BeforeMethod; | ||||||
|  | import org.testng.annotations.Test; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author yqx | ||||||
|  |  * @date 2020/5/3 | ||||||
|  |  */ | ||||||
|  | public class WxMaRedissonConfigImplTest { | ||||||
|  |  | ||||||
|  |   WxMaDefaultConfigImpl wxMaConfig; | ||||||
|  |  | ||||||
|  |   @BeforeMethod | ||||||
|  |   public void setUp() { | ||||||
|  |     Config config = new Config(); | ||||||
|  |     config.useSingleServer().setAddress("redis://127.0.0.1:6379") | ||||||
|  |       .setDatabase(0); | ||||||
|  |     config.setTransportMode(TransportMode.NIO); | ||||||
|  |     RedissonClient redisson = Redisson.create(config); | ||||||
|  |     wxMaConfig = new WxMaRedissonConfigImpl(redisson); | ||||||
|  |     wxMaConfig.setAppid("appid12345678"); | ||||||
|  |     wxMaConfig.updateAccessToken("accessToken", 5); //有效期5秒 | ||||||
|  |     wxMaConfig.updateJsapiTicket("jsapiTicket", 5); | ||||||
|  |     wxMaConfig.updateCardApiTicket("cardApiTicket", 5); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @SneakyThrows | ||||||
|  |   @Test | ||||||
|  |   public void testGetAccessToken() { | ||||||
|  |     String accessToken = wxMaConfig.getAccessToken(); | ||||||
|  |     Assert.assertEquals(accessToken, "accessToken"); | ||||||
|  |     Assert.assertFalse(wxMaConfig.isAccessTokenExpired()); | ||||||
|  |     Thread.sleep(6000);//休眠6s | ||||||
|  |     Assert.assertTrue(wxMaConfig.isAccessTokenExpired()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @SneakyThrows | ||||||
|  |   @Test | ||||||
|  |   public void testGetJsapiTicket() { | ||||||
|  |     String jsapiTicket = wxMaConfig.getJsapiTicket(); | ||||||
|  |     Assert.assertEquals(jsapiTicket, "jsapiTicket"); | ||||||
|  |     Assert.assertFalse(wxMaConfig.isJsapiTicketExpired()); | ||||||
|  |     Thread.sleep(6000);//休眠6s | ||||||
|  |     Assert.assertTrue(wxMaConfig.isJsapiTicketExpired()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @SneakyThrows | ||||||
|  |   @Test | ||||||
|  |   public void testGetCardApiTicket() { | ||||||
|  |     String cardApiTicket = wxMaConfig.getCardApiTicket(); | ||||||
|  |     Assert.assertEquals(cardApiTicket, "cardApiTicket"); | ||||||
|  |     Assert.assertFalse(wxMaConfig.isCardApiTicketExpired()); | ||||||
|  |     Thread.sleep(6000);//休眠6s | ||||||
|  |     Assert.assertTrue(wxMaConfig.isCardApiTicketExpired()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void testIsAccessTokenExpired() { | ||||||
|  |     Assert.assertFalse(wxMaConfig.isAccessTokenExpired()); | ||||||
|  |     wxMaConfig.expireAccessToken(); | ||||||
|  |     Assert.assertTrue(wxMaConfig.isAccessTokenExpired()); | ||||||
|  |   } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 yuanqixun
					yuanqixun