Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
May 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions weixin-java-miniapp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
</dependency>
<dependency>
<groupId>com.github.jedis-lock</groupId>
<artifactId>jedis-lock</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}

}
Original file line number Diff line number Diff line change
@@ -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());
}
}