Browse Source

:art: #1542 小程序模块配置类增加Redisson的实现,解决分布式锁问题

* 增加Redisson的实现,解决分布式锁问题

* key值重复添加了appid。

Co-authored-by: 袁启勋 <xun.yuan@infoship.cn>
yuanqixun 5 years ago
parent
commit
98aef34fdb

+ 4 - 0
weixin-java-miniapp/pom.xml

@@ -81,6 +81,10 @@
       <artifactId>lombok</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.redisson</groupId>
+      <artifactId>redisson</artifactId>
+    </dependency>
+    <dependency>
       <groupId>com.github.jedis-lock</groupId>
       <artifactId>jedis-lock</artifactId>
       <version>1.0.0</version>

+ 153 - 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/impl/WxMaRedissonConfigImpl.java

@@ -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);
+  }
+
+}

+ 72 - 0
weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/config/impl/WxMaRedissonConfigImplTest.java

@@ -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());
+  }
+}