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

微信公众号模块提取redis抽象层、支持key前缀设置 #1503

Merged
merged 3 commits into from
Apr 13, 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
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package me.chanjar.weixin.mp.config.impl;

import me.chanjar.weixin.common.util.locks.JedisDistributedLock;
import com.sun.istack.internal.NotNull;
import me.chanjar.weixin.mp.config.redis.JedisWxMpRedisOps;
import me.chanjar.weixin.mp.config.redis.WxMpRedisOps;
import me.chanjar.weixin.mp.enums.TicketType;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;

/**
* 基于Redis的微信配置provider.
Expand All @@ -20,19 +20,23 @@
*/
@SuppressWarnings("hiding")
public class WxMpRedisConfigImpl extends WxMpDefaultConfigImpl {
private static final String ACCESS_TOKEN_KEY = "wx:access_token:";
private static final String LOCK_KEY = "wx:lock:";
private static final String ACCESS_TOKEN_KEY_TPL = "%s:access_token:%s";
private static final String TICKET_KEY_TPL = "%s:ticket:key:%s:%s";
private static final String LOCK_KEY_TPL = "%s:lock:%s:";

/**
* 使用连接池保证线程安全.
*/
private final JedisPool jedisPool;
private final WxMpRedisOps redisOps;
private final String keyPrefix;

private String accessTokenKey;
private String lockKey;

public WxMpRedisConfigImpl(JedisPool jedisPool) {
this.jedisPool = jedisPool;
public WxMpRedisConfigImpl(@NotNull JedisPool jedisPool) {
this(new JedisWxMpRedisOps(jedisPool), "wx");
}

public WxMpRedisConfigImpl(@NotNull WxMpRedisOps redisOps, @NotNull String keyPrefix) {
this.redisOps = redisOps;
this.keyPrefix = keyPrefix;
}

/**
Expand All @@ -41,72 +45,57 @@ public WxMpRedisConfigImpl(JedisPool jedisPool) {
@Override
public void setAppId(String appId) {
super.setAppId(appId);
this.accessTokenKey = ACCESS_TOKEN_KEY.concat(appId);
this.lockKey = ACCESS_TOKEN_KEY.concat(appId).concat(":");
accessTokenLock = new JedisDistributedLock(jedisPool, lockKey.concat("accessTokenLock"));
jsapiTicketLock = new JedisDistributedLock(jedisPool, lockKey.concat("jsapiTicketLock"));
sdkTicketLock = new JedisDistributedLock(jedisPool, lockKey.concat("sdkTicketLock"));
cardApiTicketLock = new JedisDistributedLock(jedisPool, lockKey.concat("cardApiTicketLock"));
this.accessTokenKey = String.format(ACCESS_TOKEN_KEY_TPL, this.keyPrefix, appId);
this.lockKey = String.format(LOCK_KEY_TPL, this.keyPrefix, appId);
accessTokenLock = this.redisOps.getLock(lockKey.concat("accessTokenLock"));
jsapiTicketLock = this.redisOps.getLock(lockKey.concat("jsapiTicketLock"));
sdkTicketLock = this.redisOps.getLock(lockKey.concat("sdkTicketLock"));
cardApiTicketLock = this.redisOps.getLock(lockKey.concat("cardApiTicketLock"));
}

private String getTicketRedisKey(TicketType type) {
return String.format("wx:ticket:key:%s:%s", this.appId, type.getCode());
return String.format(TICKET_KEY_TPL, this.keyPrefix, appId, type.getCode());
}

@Override
public String getAccessToken() {
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.get(this.accessTokenKey);
}
return redisOps.getValue(this.accessTokenKey);
}

@Override
public boolean isAccessTokenExpired() {
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.ttl(accessTokenKey) < 2;
}
Long expire = redisOps.getExpire(this.accessTokenKey);
return expire == null || expire < 2;
}

@Override
public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.setex(this.accessTokenKey, expiresInSeconds - 200, accessToken);
}
redisOps.setValue(this.accessTokenKey, accessToken, expiresInSeconds - 200, TimeUnit.SECONDS);
}

@Override
public void expireAccessToken() {
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.expire(this.accessTokenKey, 0);
}
redisOps.expire(this.accessTokenKey, 0, TimeUnit.SECONDS);
}

@Override
public String getTicket(TicketType type) {
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.get(this.getTicketRedisKey(type));
}
return redisOps.getValue(this.getTicketRedisKey(type));
}

@Override
public boolean isTicketExpired(TicketType type) {
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.ttl(this.getTicketRedisKey(type)) < 2;
}
return redisOps.getExpire(this.getTicketRedisKey(type)) < 2;
}

@Override
public synchronized void updateTicket(TicketType type, String jsapiTicket, int expiresInSeconds) {
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.setex(this.getTicketRedisKey(type), expiresInSeconds - 200, jsapiTicket);
}
redisOps.setValue(this.getTicketRedisKey(type), jsapiTicket, expiresInSeconds - 200, TimeUnit.SECONDS);
}

@Override
public void expireTicket(TicketType type) {
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.expire(this.getTicketRedisKey(type), 0);
}
redisOps.expire(this.getTicketRedisKey(type), 0, TimeUnit.SECONDS);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package me.chanjar.weixin.mp.config.redis;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
* 微信公众号redis操作基本类
* <p>
* 非内置实现redis相关操作, 请实现该类
*/
public class BaseWxMpRedisOps implements WxMpRedisOps {

@Override
public String getValue(String key) {
throw new UnsupportedOperationException();
}

@Override
public void setValue(String key, String value, int expire, TimeUnit timeUnit) {
throw new UnsupportedOperationException();
}

@Override
public Long getExpire(String key) {
throw new UnsupportedOperationException();
}

@Override
public void expire(String key, int expire, TimeUnit timeUnit) {
throw new UnsupportedOperationException();
}

@Override
public Lock getLock(String key) {
throw new UnsupportedOperationException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package me.chanjar.weixin.mp.config.redis;

import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.util.locks.JedisDistributedLock;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
* Jedis实现相关操作
*/
@AllArgsConstructor
public class JedisWxMpRedisOps implements WxMpRedisOps {

private JedisPool jedisPool;

@Override
public String getValue(String key) {
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.get(key);
}
}

@Override
public void setValue(String key, String value, int expire, TimeUnit timeUnit) {
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.psetex(key, timeUnit.toMillis(expire), value);
}
}

@Override
public Long getExpire(String key) {
try (Jedis jedis = this.jedisPool.getResource()) {
return jedis.ttl(key);
}
}

@Override
public void expire(String key, int expire, TimeUnit timeUnit) {
try (Jedis jedis = this.jedisPool.getResource()) {
jedis.pexpire(key, timeUnit.toMillis(expire));
}
}

@Override
public Lock getLock(String key) {
return new JedisDistributedLock(jedisPool, key);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package me.chanjar.weixin.mp.config.redis;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
* 微信公众号Redis相关操作
* <p>
* 该接口不承诺稳定, 外部实现请继承{@link BaseWxMpRedisOps}
*
* @see BaseWxMpRedisOps 实现需要继承该类
* @see JedisWxMpRedisOps jedis实现
*/
public interface WxMpRedisOps {

String getValue(String key);

void setValue(String key, String value, int expire, TimeUnit timeUnit);

Long getExpire(String key);

void expire(String key, int expire, TimeUnit timeUnit);

Lock getLock(String key);
}