Skip to content

Commit 98aef34

Browse files
yuanqixun袁启勋
andauthored
🎨 #1542 小程序模块配置类增加Redisson的实现,解决分布式锁问题
* 增加Redisson的实现,解决分布式锁问题 * key值重复添加了appid。 Co-authored-by: 袁启勋 <[email protected]>
1 parent 424a835 commit 98aef34

File tree

3 files changed

+229
-0
lines changed

3 files changed

+229
-0
lines changed

weixin-java-miniapp/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@
8080
<groupId>org.projectlombok</groupId>
8181
<artifactId>lombok</artifactId>
8282
</dependency>
83+
<dependency>
84+
<groupId>org.redisson</groupId>
85+
<artifactId>redisson</artifactId>
86+
</dependency>
8387
<dependency>
8488
<groupId>com.github.jedis-lock</groupId>
8589
<artifactId>jedis-lock</artifactId>
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package cn.binarywang.wx.miniapp.config.impl;
2+
3+
import lombok.NonNull;
4+
import me.chanjar.weixin.common.bean.WxAccessToken;
5+
import me.chanjar.weixin.common.redis.RedissonWxRedisOps;
6+
import me.chanjar.weixin.common.redis.WxRedisOps;
7+
import org.apache.commons.lang3.StringUtils;
8+
import org.redisson.api.RedissonClient;
9+
10+
import java.util.concurrent.TimeUnit;
11+
import java.util.concurrent.locks.Lock;
12+
13+
/**
14+
* 基于Redisson的实现
15+
*
16+
* @author yuanqixun
17+
* @date 2020/5/3
18+
*/
19+
public class WxMaRedissonConfigImpl extends WxMaDefaultConfigImpl {
20+
21+
protected final static String LOCK_KEY = "wechat_ma_lock:";
22+
protected final static String MA_ACCESS_TOKEN_KEY = "wechat_ma_access_token_key:";
23+
protected final static String MA_JSAPI_TICKET_KEY = "wechat_ma_jsapi_ticket_key:";
24+
protected final static String MA_CARD_API_TICKET_KEY = "wechat_ma_card_api_ticket_key:";
25+
26+
/**
27+
* redis 存储的 key 的前缀,可为空
28+
*/
29+
/**
30+
* redis 存储的 key 的前缀,可为空
31+
*/
32+
protected String keyPrefix;
33+
protected String accessTokenKey;
34+
protected String jsapiTicketKey;
35+
protected String cardApiTicketKey;
36+
protected String lockKey;
37+
38+
private final WxRedisOps redisOps;
39+
40+
public WxMaRedissonConfigImpl(@NonNull RedissonClient redissonClient, String keyPrefix) {
41+
this(new RedissonWxRedisOps(redissonClient), keyPrefix);
42+
}
43+
44+
public WxMaRedissonConfigImpl(@NonNull RedissonClient redissonClient) {
45+
this(redissonClient, null);
46+
}
47+
48+
private WxMaRedissonConfigImpl(@NonNull WxRedisOps redisOps, String keyPrefix) {
49+
this.redisOps = redisOps;
50+
this.keyPrefix = keyPrefix;
51+
}
52+
53+
@Override
54+
public void setAppid(String appid) {
55+
super.setAppid(appid);
56+
String prefix = StringUtils.isBlank(keyPrefix) ? "" :
57+
(StringUtils.endsWith(keyPrefix, ":") ? keyPrefix : (keyPrefix + ":"));
58+
lockKey = prefix + LOCK_KEY.concat(appid);
59+
accessTokenKey = prefix + MA_ACCESS_TOKEN_KEY.concat(appid);
60+
jsapiTicketKey = prefix + MA_JSAPI_TICKET_KEY.concat(appid);
61+
cardApiTicketKey = prefix + MA_CARD_API_TICKET_KEY.concat(appid);
62+
}
63+
64+
protected Lock getLockByKey(String key) {
65+
return redisOps.getLock(key);
66+
}
67+
68+
@Override
69+
public Lock getAccessTokenLock() {
70+
return getLockByKey(this.lockKey.concat(":").concat("accessToken"));
71+
}
72+
73+
@Override
74+
public Lock getCardApiTicketLock() {
75+
return getLockByKey(this.lockKey.concat(":").concat("cardApiTicket"));
76+
77+
}
78+
79+
@Override
80+
public Lock getJsapiTicketLock() {
81+
return getLockByKey(this.lockKey.concat(":").concat("jsapiTicket"));
82+
}
83+
84+
@Override
85+
public String getAccessToken() {
86+
return redisOps.getValue(this.accessTokenKey);
87+
}
88+
89+
@Override
90+
public boolean isAccessTokenExpired() {
91+
Long expire = redisOps.getExpire(this.accessTokenKey);
92+
return expire == null || expire < 2;
93+
}
94+
95+
@Override
96+
public void updateAccessToken(WxAccessToken accessToken) {
97+
redisOps.setValue(this.accessTokenKey, accessToken.getAccessToken(), accessToken.getExpiresIn(), TimeUnit.SECONDS);
98+
}
99+
100+
@Override
101+
public void updateAccessToken(String accessToken, int expiresInSeconds) {
102+
redisOps.setValue(this.accessTokenKey, accessToken, expiresInSeconds, TimeUnit.SECONDS);
103+
}
104+
105+
@Override
106+
public String getJsapiTicket() {
107+
return redisOps.getValue(this.jsapiTicketKey);
108+
}
109+
110+
@Override
111+
public boolean isJsapiTicketExpired() {
112+
Long expire = redisOps.getExpire(this.jsapiTicketKey);
113+
return expire == null || expire < 2;
114+
}
115+
116+
@Override
117+
public void expireJsapiTicket() {
118+
redisOps.expire(this.jsapiTicketKey, 0, TimeUnit.SECONDS);
119+
}
120+
121+
@Override
122+
public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
123+
redisOps.setValue(this.jsapiTicketKey, jsapiTicket, expiresInSeconds, TimeUnit.SECONDS);
124+
125+
}
126+
127+
@Override
128+
public String getCardApiTicket() {
129+
return redisOps.getValue(cardApiTicketKey);
130+
}
131+
132+
@Override
133+
public boolean isCardApiTicketExpired() {
134+
Long expire = redisOps.getExpire(this.cardApiTicketKey);
135+
return expire == null || expire < 2;
136+
}
137+
138+
@Override
139+
public void expireCardApiTicket() {
140+
redisOps.expire(this.cardApiTicketKey, 0, TimeUnit.SECONDS);
141+
}
142+
143+
@Override
144+
public void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) {
145+
redisOps.setValue(this.cardApiTicketKey, cardApiTicket, expiresInSeconds, TimeUnit.SECONDS);
146+
}
147+
148+
@Override
149+
public void expireAccessToken() {
150+
redisOps.expire(this.accessTokenKey, 0, TimeUnit.SECONDS);
151+
}
152+
153+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package cn.binarywang.wx.miniapp.config.impl;
2+
3+
import cn.binarywang.wx.miniapp.config.WxMaConfig;
4+
import lombok.SneakyThrows;
5+
import org.redisson.Redisson;
6+
import org.redisson.api.RedissonClient;
7+
import org.redisson.config.Config;
8+
import org.redisson.config.TransportMode;
9+
import org.testng.Assert;
10+
import org.testng.annotations.AfterMethod;
11+
import org.testng.annotations.BeforeMethod;
12+
import org.testng.annotations.Test;
13+
14+
/**
15+
* @author yqx
16+
* @date 2020/5/3
17+
*/
18+
public class WxMaRedissonConfigImplTest {
19+
20+
WxMaDefaultConfigImpl wxMaConfig;
21+
22+
@BeforeMethod
23+
public void setUp() {
24+
Config config = new Config();
25+
config.useSingleServer().setAddress("redis://127.0.0.1:6379")
26+
.setDatabase(0);
27+
config.setTransportMode(TransportMode.NIO);
28+
RedissonClient redisson = Redisson.create(config);
29+
wxMaConfig = new WxMaRedissonConfigImpl(redisson);
30+
wxMaConfig.setAppid("appid12345678");
31+
wxMaConfig.updateAccessToken("accessToken", 5); //有效期5秒
32+
wxMaConfig.updateJsapiTicket("jsapiTicket", 5);
33+
wxMaConfig.updateCardApiTicket("cardApiTicket", 5);
34+
}
35+
36+
@SneakyThrows
37+
@Test
38+
public void testGetAccessToken() {
39+
String accessToken = wxMaConfig.getAccessToken();
40+
Assert.assertEquals(accessToken, "accessToken");
41+
Assert.assertFalse(wxMaConfig.isAccessTokenExpired());
42+
Thread.sleep(6000);//休眠6s
43+
Assert.assertTrue(wxMaConfig.isAccessTokenExpired());
44+
}
45+
46+
@SneakyThrows
47+
@Test
48+
public void testGetJsapiTicket() {
49+
String jsapiTicket = wxMaConfig.getJsapiTicket();
50+
Assert.assertEquals(jsapiTicket, "jsapiTicket");
51+
Assert.assertFalse(wxMaConfig.isJsapiTicketExpired());
52+
Thread.sleep(6000);//休眠6s
53+
Assert.assertTrue(wxMaConfig.isJsapiTicketExpired());
54+
}
55+
56+
@SneakyThrows
57+
@Test
58+
public void testGetCardApiTicket() {
59+
String cardApiTicket = wxMaConfig.getCardApiTicket();
60+
Assert.assertEquals(cardApiTicket, "cardApiTicket");
61+
Assert.assertFalse(wxMaConfig.isCardApiTicketExpired());
62+
Thread.sleep(6000);//休眠6s
63+
Assert.assertTrue(wxMaConfig.isCardApiTicketExpired());
64+
}
65+
66+
@Test
67+
public void testIsAccessTokenExpired() {
68+
Assert.assertFalse(wxMaConfig.isAccessTokenExpired());
69+
wxMaConfig.expireAccessToken();
70+
Assert.assertTrue(wxMaConfig.isAccessTokenExpired());
71+
}
72+
}

0 commit comments

Comments
 (0)