@@ -0,0 +1,280 @@ | |||||
package cn.binarywang.wx.miniapp.config.impl; | |||||
import com.github.jedis.lock.JedisLock; | |||||
import redis.clients.jedis.Jedis; | |||||
import java.io.File; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
import java.util.concurrent.TimeUnit; | |||||
import java.util.concurrent.locks.Condition; | |||||
import java.util.concurrent.locks.Lock; | |||||
/** | |||||
* @author <a href="https://github.com/winter4666">winter</a> | |||||
*/ | |||||
public abstract class AbstractWxMaRedisConfig extends WxMaDefaultConfigImpl { | |||||
public interface JedisConfig { | |||||
Jedis config(Jedis jedis); | |||||
} | |||||
private static final String ACCESS_TOKEN = "accessToken"; | |||||
private static final String JSAPI_TICKET = "jsapiTicket"; | |||||
private static final String CARD_API_TICKET = "cardApiTicket"; | |||||
private static final String HASH_VALUE_FIELD = "value"; | |||||
private static final String HASH_EXPIRE_FIELD = "expire"; | |||||
/** | |||||
* Redis Key 的前缀,默认为 maConfig | |||||
*/ | |||||
private String redisKeyPrefix = "maConfig"; | |||||
/** | |||||
* 微信小程序唯一id,用于拼接存储到redis时的key,防止key重复. | |||||
*/ | |||||
private String maId; | |||||
private Lock accessTokenLock; | |||||
private Lock jsapiTicketLock; | |||||
private Lock cardApiTicketLock; | |||||
/** | |||||
* 临时文件目录. | |||||
*/ | |||||
protected volatile File tmpDirFile; | |||||
/** | |||||
* 对从 JedisPool.getResource() 获取到的每个 Jedis 实例进行配置 | |||||
*/ | |||||
private JedisConfig jedisConfig; | |||||
protected abstract Jedis getJedis(); | |||||
private Jedis getConfiguredJedis() { | |||||
Jedis jedis = getJedis(); | |||||
if (jedisConfig != null) { | |||||
return jedisConfig.config(jedis); | |||||
} else { | |||||
return jedis; | |||||
} | |||||
} | |||||
private String getRedisKey(String key) { | |||||
StringBuilder redisKey = new StringBuilder(redisKeyPrefix).append(":"); | |||||
if (maId == null) { | |||||
return redisKey.append(key).toString(); | |||||
} else { | |||||
return redisKey.append(maId).append(":").append(key).toString(); | |||||
} | |||||
} | |||||
private String getValueFromRedis(String key) { | |||||
try (Jedis jedis = getConfiguredJedis()) { | |||||
return jedis.hget(getRedisKey(key), HASH_VALUE_FIELD); | |||||
} | |||||
} | |||||
private void setValueToRedis(String key, long expiresTime, String value) { | |||||
try (Jedis jedis = getConfiguredJedis()) { | |||||
Map<String, String> hash = new HashMap<String, String>(); | |||||
hash.put(HASH_VALUE_FIELD, value); | |||||
hash.put(HASH_EXPIRE_FIELD, String.valueOf(expiresTime)); | |||||
jedis.hmset(getRedisKey(key), hash); | |||||
} | |||||
} | |||||
private long getExpireFromRedis(String key) { | |||||
try (Jedis jedis = getConfiguredJedis()) { | |||||
String expire = jedis.hget(getRedisKey(key), HASH_EXPIRE_FIELD); | |||||
return expire == null ? 0 : Long.parseLong(expire); | |||||
} | |||||
} | |||||
private void setExpire(String key, long expiresTime) { | |||||
try (Jedis jedis = getConfiguredJedis()) { | |||||
jedis.hset(getRedisKey(key), HASH_EXPIRE_FIELD, String.valueOf(expiresTime)); | |||||
} | |||||
} | |||||
public void setRedisKeyPrefix(String redisKeyPrefix) { | |||||
this.redisKeyPrefix = redisKeyPrefix; | |||||
} | |||||
public void setJedisConfig(JedisConfig jedisConfig) { | |||||
this.jedisConfig = jedisConfig; | |||||
} | |||||
public void setMaId(String maId) { | |||||
this.maId = maId; | |||||
} | |||||
@Override | |||||
public String getAccessToken() { | |||||
return getValueFromRedis(ACCESS_TOKEN); | |||||
} | |||||
@Override | |||||
public Lock getAccessTokenLock() { | |||||
if (accessTokenLock == null) { | |||||
synchronized (this) { | |||||
if (accessTokenLock == null) { | |||||
accessTokenLock = new DistributedLock(getRedisKey("accessTokenLock")); | |||||
} | |||||
} | |||||
} | |||||
return accessTokenLock; | |||||
} | |||||
@Override | |||||
public boolean isAccessTokenExpired() { | |||||
return isExpired(getExpireFromRedis(ACCESS_TOKEN)); | |||||
} | |||||
@Override | |||||
public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) { | |||||
setValueToRedis(ACCESS_TOKEN, expiresAheadInMillis(expiresInSeconds), accessToken); | |||||
} | |||||
@Override | |||||
public String getJsapiTicket() { | |||||
return getValueFromRedis(JSAPI_TICKET); | |||||
} | |||||
@Override | |||||
public Lock getJsapiTicketLock() { | |||||
if (jsapiTicketLock == null) { | |||||
synchronized (this) { | |||||
if (jsapiTicketLock == null) { | |||||
jsapiTicketLock = new DistributedLock(getRedisKey("jsapiTicketLock")); | |||||
} | |||||
} | |||||
} | |||||
return jsapiTicketLock; | |||||
} | |||||
@Override | |||||
public boolean isJsapiTicketExpired() { | |||||
return isExpired(getExpireFromRedis(JSAPI_TICKET)); | |||||
} | |||||
@Override | |||||
public void expireJsapiTicket() { | |||||
setExpire(JSAPI_TICKET, 0); | |||||
} | |||||
@Override | |||||
public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { | |||||
setValueToRedis(JSAPI_TICKET, expiresAheadInMillis(expiresInSeconds), jsapiTicket); | |||||
} | |||||
@Override | |||||
public String getCardApiTicket() { | |||||
return getValueFromRedis(CARD_API_TICKET); | |||||
} | |||||
@Override | |||||
public Lock getCardApiTicketLock() { | |||||
if (cardApiTicketLock == null) { | |||||
synchronized (this) { | |||||
if (cardApiTicketLock == null) { | |||||
cardApiTicketLock = new DistributedLock(getRedisKey("cardApiTicketLock")); | |||||
} | |||||
} | |||||
} | |||||
return cardApiTicketLock; | |||||
} | |||||
@Override | |||||
public boolean isCardApiTicketExpired() { | |||||
return isExpired(getExpireFromRedis(CARD_API_TICKET)); | |||||
} | |||||
@Override | |||||
public void expireCardApiTicket() { | |||||
setExpire(CARD_API_TICKET, 0); | |||||
} | |||||
@Override | |||||
public void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) { | |||||
setValueToRedis(CARD_API_TICKET, expiresAheadInMillis(expiresInSeconds), cardApiTicket); | |||||
} | |||||
@Override | |||||
public void expireAccessToken() { | |||||
setExpiresTime(0); | |||||
} | |||||
@Override | |||||
public long getExpiresTime() { | |||||
return getExpireFromRedis(ACCESS_TOKEN); | |||||
} | |||||
@Override | |||||
public void setExpiresTime(long expiresTime) { | |||||
setExpire(ACCESS_TOKEN, expiresTime); | |||||
} | |||||
/** | |||||
* 基于redis的简单分布式锁. | |||||
*/ | |||||
private class DistributedLock implements Lock { | |||||
private JedisLock lock; | |||||
private DistributedLock(String key) { | |||||
this.lock = new JedisLock(getRedisKey(key)); | |||||
} | |||||
@Override | |||||
public void lock() { | |||||
try (Jedis jedis = getConfiguredJedis()) { | |||||
if (!lock.acquire(jedis)) { | |||||
throw new RuntimeException("acquire timeouted"); | |||||
} | |||||
} catch (InterruptedException e) { | |||||
throw new RuntimeException("lock failed", e); | |||||
} | |||||
} | |||||
@Override | |||||
public void lockInterruptibly() throws InterruptedException { | |||||
try (Jedis jedis = getConfiguredJedis()) { | |||||
if (!lock.acquire(jedis)) { | |||||
throw new RuntimeException("acquire timeouted"); | |||||
} | |||||
} | |||||
} | |||||
@Override | |||||
public boolean tryLock() { | |||||
try (Jedis jedis = getConfiguredJedis()) { | |||||
return lock.acquire(jedis); | |||||
} catch (InterruptedException e) { | |||||
throw new RuntimeException("lock failed", e); | |||||
} | |||||
} | |||||
@Override | |||||
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { | |||||
try (Jedis jedis = getConfiguredJedis()) { | |||||
return lock.acquire(jedis); | |||||
} | |||||
} | |||||
@Override | |||||
public void unlock() { | |||||
try (Jedis jedis = getConfiguredJedis()) { | |||||
lock.release(jedis); | |||||
} | |||||
} | |||||
@Override | |||||
public Condition newCondition() { | |||||
throw new RuntimeException("unsupported method"); | |||||
} | |||||
} | |||||
} |
@@ -48,6 +48,20 @@ public class WxMaDefaultConfigImpl implements WxMaConfig { | |||||
private volatile ApacheHttpClientBuilder apacheHttpClientBuilder; | private volatile ApacheHttpClientBuilder apacheHttpClientBuilder; | ||||
/** | |||||
* 会过期的数据提前过期时间,默认预留200秒的时间 | |||||
*/ | |||||
protected long expiresAheadInMillis(int expiresInSeconds) { | |||||
return System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; | |||||
} | |||||
/** | |||||
* 判断 expiresTime 是否已经过期 | |||||
*/ | |||||
protected boolean isExpired(long expiresTime) { | |||||
return System.currentTimeMillis() > expiresTime; | |||||
} | |||||
@Override | @Override | ||||
public String getAccessToken() { | public String getAccessToken() { | ||||
return this.accessToken; | return this.accessToken; | ||||
@@ -68,7 +82,7 @@ public class WxMaDefaultConfigImpl implements WxMaConfig { | |||||
@Override | @Override | ||||
public boolean isAccessTokenExpired() { | public boolean isAccessTokenExpired() { | ||||
return System.currentTimeMillis() > this.expiresTime; | |||||
return isExpired(this.expiresTime); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -78,8 +92,8 @@ public class WxMaDefaultConfigImpl implements WxMaConfig { | |||||
@Override | @Override | ||||
public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) { | public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) { | ||||
this.accessToken = accessToken; | |||||
this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; | |||||
setAccessToken(accessToken); | |||||
setExpiresTime(expiresAheadInMillis(expiresInSeconds)); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -94,7 +108,7 @@ public class WxMaDefaultConfigImpl implements WxMaConfig { | |||||
@Override | @Override | ||||
public boolean isJsapiTicketExpired() { | public boolean isJsapiTicketExpired() { | ||||
return System.currentTimeMillis() > this.jsapiTicketExpiresTime; | |||||
return isExpired(this.jsapiTicketExpiresTime); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -105,8 +119,7 @@ public class WxMaDefaultConfigImpl implements WxMaConfig { | |||||
@Override | @Override | ||||
public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { | public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { | ||||
this.jsapiTicket = jsapiTicket; | this.jsapiTicket = jsapiTicket; | ||||
// 预留200秒的时间 | |||||
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; | |||||
this.jsapiTicketExpiresTime = expiresAheadInMillis(expiresInSeconds); | |||||
} | } | ||||
@@ -122,7 +135,7 @@ public class WxMaDefaultConfigImpl implements WxMaConfig { | |||||
@Override | @Override | ||||
public boolean isCardApiTicketExpired() { | public boolean isCardApiTicketExpired() { | ||||
return System.currentTimeMillis() > this.cardApiTicketExpiresTime; | |||||
return isExpired(this.cardApiTicketExpiresTime); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -133,8 +146,7 @@ public class WxMaDefaultConfigImpl implements WxMaConfig { | |||||
@Override | @Override | ||||
public void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) { | public void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) { | ||||
this.cardApiTicket = cardApiTicket; | this.cardApiTicket = cardApiTicket; | ||||
// 预留200秒的时间 | |||||
this.cardApiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; | |||||
this.cardApiTicketExpiresTime = expiresAheadInMillis(expiresInSeconds); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -1,377 +1,40 @@ | |||||
package cn.binarywang.wx.miniapp.config.impl; | package cn.binarywang.wx.miniapp.config.impl; | ||||
import java.io.File; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
import java.util.concurrent.TimeUnit; | |||||
import java.util.concurrent.locks.Condition; | |||||
import java.util.concurrent.locks.Lock; | |||||
import cn.binarywang.wx.miniapp.config.WxMaConfig; | |||||
import com.github.jedis.lock.JedisLock; | |||||
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||||
import me.chanjar.weixin.common.bean.WxAccessToken; | |||||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | |||||
import redis.clients.jedis.Jedis; | import redis.clients.jedis.Jedis; | ||||
import redis.clients.jedis.JedisPool; | import redis.clients.jedis.JedisPool; | ||||
/** | /** | ||||
* 基于Redis的微信配置provider. | |||||
* 基于Redis的微信配置provider. 使用连接池 JedisPool 进行 Redis 操作。 | |||||
* | * | ||||
* <pre> | * <pre> | ||||
* 需要引入依赖<a href="https://github.com/abelaska/jedis-lock">jedis-lock</a>,才能使用该类。 | * 需要引入依赖<a href="https://github.com/abelaska/jedis-lock">jedis-lock</a>,才能使用该类。 | ||||
* </pre> | * </pre> | ||||
* | |||||
* @author <a href="https://github.com/winter4666">winter</a> | |||||
*/ | */ | ||||
public class WxMaRedisConfigImpl implements WxMaConfig { | |||||
private static final String ACCESS_TOKEN = "accessToken"; | |||||
private static final String JSAPI_TICKET = "jsapiTicket"; | |||||
private static final String CARD_API_TICKET = "cardApiTicket"; | |||||
private static final String HASH_VALUE_FIELD = "value"; | |||||
private static final String HASH_EXPIRE_FIELD = "expire"; | |||||
public class WxMaRedisConfigImpl extends AbstractWxMaRedisConfig { | |||||
private JedisPool jedisPool; | private JedisPool jedisPool; | ||||
/** | |||||
* 微信小程序唯一id,用于拼接存储到redis时的key,防止key重复. | |||||
*/ | |||||
private String maId; | |||||
private volatile String msgDataFormat; | |||||
protected volatile String appid; | |||||
private volatile String secret; | |||||
protected volatile String token; | |||||
private volatile String aesKey; | |||||
private volatile String httpProxyHost; | |||||
private volatile int httpProxyPort; | |||||
private volatile String httpProxyUsername; | |||||
private volatile String httpProxyPassword; | |||||
private Lock accessTokenLock; | |||||
private Lock jsapiTicketLock; | |||||
private Lock cardApiTicketLock; | |||||
/** | /** | ||||
* 临时文件目录. | |||||
* JedisPool 在此配置类是必须项,使用 WxMaRedisConfigImpl(JedisPool) 构造方法来构造实例 | |||||
*/ | */ | ||||
protected volatile File tmpDirFile; | |||||
private volatile ApacheHttpClientBuilder apacheHttpClientBuilder; | |||||
private String getRedisKey(String key) { | |||||
StringBuilder redisKey = new StringBuilder("maConfig:"); | |||||
if (maId == null) { | |||||
return redisKey.append(key).toString(); | |||||
} else { | |||||
return redisKey.append(maId).append(":").append(key).toString(); | |||||
} | |||||
@Deprecated | |||||
public WxMaRedisConfigImpl() { | |||||
} | } | ||||
private String getValueFromRedis(String key) { | |||||
try (Jedis jedis = jedisPool.getResource()) { | |||||
return jedis.hget(getRedisKey(key), HASH_VALUE_FIELD); | |||||
} | |||||
} | |||||
private void setValueToRedis(String key, long expiresTime, String value) { | |||||
try (Jedis jedis = jedisPool.getResource()) { | |||||
Map<String, String> hash = new HashMap<String, String>(); | |||||
hash.put(HASH_VALUE_FIELD, value); | |||||
hash.put(HASH_EXPIRE_FIELD, String.valueOf(expiresTime)); | |||||
jedis.hmset(getRedisKey(key), hash); | |||||
} | |||||
} | |||||
private long getExpireFromRedis(String key) { | |||||
try (Jedis jedis = jedisPool.getResource()) { | |||||
String expire = jedis.hget(getRedisKey(key), HASH_EXPIRE_FIELD); | |||||
return expire == null ? 0 : Long.parseLong(expire); | |||||
} | |||||
} | |||||
private void setExpire(String key, long expiresTime) { | |||||
try (Jedis jedis = jedisPool.getResource()) { | |||||
jedis.hset(getRedisKey(key), HASH_EXPIRE_FIELD, String.valueOf(expiresTime)); | |||||
} | |||||
public WxMaRedisConfigImpl(JedisPool jedisPool) { | |||||
this.jedisPool = jedisPool; | |||||
} | } | ||||
/** | |||||
* 使用 WxMaRedisConfigImpl(JedisPool) 构造方法来设置 JedisPool | |||||
*/ | |||||
@Deprecated | |||||
public void setJedisPool(JedisPool jedisPool) { | public void setJedisPool(JedisPool jedisPool) { | ||||
this.jedisPool = jedisPool; | this.jedisPool = jedisPool; | ||||
} | } | ||||
public void setMaId(String maId) { | |||||
this.maId = maId; | |||||
} | |||||
@Override | |||||
public String getAccessToken() { | |||||
return getValueFromRedis(ACCESS_TOKEN); | |||||
} | |||||
@Override | |||||
public Lock getAccessTokenLock() { | |||||
if (accessTokenLock == null) { | |||||
synchronized (this) { | |||||
if (accessTokenLock == null) { | |||||
accessTokenLock = new DistributedLock(getRedisKey("accessTokenLock")); | |||||
} | |||||
} | |||||
} | |||||
return accessTokenLock; | |||||
} | |||||
@Override | |||||
public boolean isAccessTokenExpired() { | |||||
return System.currentTimeMillis() > getExpireFromRedis(ACCESS_TOKEN); | |||||
} | |||||
@Override | |||||
public synchronized void updateAccessToken(WxAccessToken accessToken) { | |||||
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()); | |||||
} | |||||
@Override | |||||
public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) { | |||||
setValueToRedis(ACCESS_TOKEN, System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L, accessToken); | |||||
} | |||||
@Override | |||||
public String getJsapiTicket() { | |||||
return getValueFromRedis(JSAPI_TICKET); | |||||
} | |||||
@Override | |||||
public Lock getJsapiTicketLock() { | |||||
if (jsapiTicketLock == null) { | |||||
synchronized (this) { | |||||
if (jsapiTicketLock == null) { | |||||
jsapiTicketLock = new DistributedLock(getRedisKey("jsapiTicketLock")); | |||||
} | |||||
} | |||||
} | |||||
return jsapiTicketLock; | |||||
} | |||||
@Override | |||||
public boolean isJsapiTicketExpired() { | |||||
return System.currentTimeMillis() > getExpireFromRedis(JSAPI_TICKET); | |||||
} | |||||
@Override | |||||
public void expireJsapiTicket() { | |||||
setExpire(JSAPI_TICKET, 0); | |||||
} | |||||
@Override | |||||
public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { | |||||
// 预留200秒的时间 | |||||
setValueToRedis(JSAPI_TICKET, System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L, jsapiTicket); | |||||
} | |||||
@Override | |||||
public String getCardApiTicket() { | |||||
return getValueFromRedis(CARD_API_TICKET); | |||||
} | |||||
@Override | |||||
public Lock getCardApiTicketLock() { | |||||
if (cardApiTicketLock == null) { | |||||
synchronized (this) { | |||||
if (cardApiTicketLock == null) { | |||||
cardApiTicketLock = new DistributedLock(getRedisKey("cardApiTicketLock")); | |||||
} | |||||
} | |||||
} | |||||
return cardApiTicketLock; | |||||
} | |||||
@Override | |||||
public boolean isCardApiTicketExpired() { | |||||
return System.currentTimeMillis() > getExpireFromRedis(CARD_API_TICKET); | |||||
} | |||||
@Override | |||||
public void expireCardApiTicket() { | |||||
setExpire(CARD_API_TICKET, 0); | |||||
} | |||||
@Override | |||||
public void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) { | |||||
setValueToRedis(CARD_API_TICKET, System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L, cardApiTicket); | |||||
} | |||||
@Override | |||||
public void expireAccessToken() { | |||||
setExpire(ACCESS_TOKEN, 0); | |||||
} | |||||
@Override | |||||
public String getSecret() { | |||||
return this.secret; | |||||
} | |||||
public void setSecret(String secret) { | |||||
this.secret = secret; | |||||
} | |||||
@Override | |||||
public String getToken() { | |||||
return this.token; | |||||
} | |||||
public void setToken(String token) { | |||||
this.token = token; | |||||
} | |||||
@Override | |||||
public long getExpiresTime() { | |||||
return getExpireFromRedis(ACCESS_TOKEN); | |||||
} | |||||
@Override | |||||
public String getAesKey() { | |||||
return this.aesKey; | |||||
} | |||||
public void setAesKey(String aesKey) { | |||||
this.aesKey = aesKey; | |||||
} | |||||
@Override | |||||
public String getMsgDataFormat() { | |||||
return this.msgDataFormat; | |||||
} | |||||
public void setMsgDataFormat(String msgDataFormat) { | |||||
this.msgDataFormat = msgDataFormat; | |||||
} | |||||
@Override | |||||
public String getHttpProxyHost() { | |||||
return this.httpProxyHost; | |||||
} | |||||
public void setHttpProxyHost(String httpProxyHost) { | |||||
this.httpProxyHost = httpProxyHost; | |||||
} | |||||
@Override | |||||
public int getHttpProxyPort() { | |||||
return this.httpProxyPort; | |||||
} | |||||
public void setHttpProxyPort(int httpProxyPort) { | |||||
this.httpProxyPort = httpProxyPort; | |||||
} | |||||
@Override | |||||
public String getHttpProxyUsername() { | |||||
return this.httpProxyUsername; | |||||
} | |||||
public void setHttpProxyUsername(String httpProxyUsername) { | |||||
this.httpProxyUsername = httpProxyUsername; | |||||
} | |||||
@Override | |||||
public String getHttpProxyPassword() { | |||||
return this.httpProxyPassword; | |||||
} | |||||
public void setHttpProxyPassword(String httpProxyPassword) { | |||||
this.httpProxyPassword = httpProxyPassword; | |||||
} | |||||
@Override | @Override | ||||
public String toString() { | |||||
return WxMaGsonBuilder.create().toJson(this); | |||||
} | |||||
@Override | |||||
public ApacheHttpClientBuilder getApacheHttpClientBuilder() { | |||||
return this.apacheHttpClientBuilder; | |||||
} | |||||
public void setApacheHttpClientBuilder(ApacheHttpClientBuilder apacheHttpClientBuilder) { | |||||
this.apacheHttpClientBuilder = apacheHttpClientBuilder; | |||||
} | |||||
@Override | |||||
public boolean autoRefreshToken() { | |||||
return true; | |||||
} | |||||
@Override | |||||
public String getAppid() { | |||||
return appid; | |||||
} | |||||
public void setAppid(String appid) { | |||||
this.appid = appid; | |||||
} | |||||
/** | |||||
* 基于redis的简单分布式锁. | |||||
*/ | |||||
private class DistributedLock implements Lock { | |||||
private JedisLock lock; | |||||
private DistributedLock(String key) { | |||||
this.lock = new JedisLock(getRedisKey(key)); | |||||
} | |||||
@Override | |||||
public void lock() { | |||||
try (Jedis jedis = jedisPool.getResource()) { | |||||
if (!lock.acquire(jedis)) { | |||||
throw new RuntimeException("acquire timeouted"); | |||||
} | |||||
} catch (InterruptedException e) { | |||||
throw new RuntimeException("lock failed", e); | |||||
} | |||||
} | |||||
@Override | |||||
public void lockInterruptibly() throws InterruptedException { | |||||
try (Jedis jedis = jedisPool.getResource()) { | |||||
if (!lock.acquire(jedis)) { | |||||
throw new RuntimeException("acquire timeouted"); | |||||
} | |||||
} | |||||
} | |||||
@Override | |||||
public boolean tryLock() { | |||||
try (Jedis jedis = jedisPool.getResource()) { | |||||
return lock.acquire(jedis); | |||||
} catch (InterruptedException e) { | |||||
throw new RuntimeException("lock failed", e); | |||||
} | |||||
} | |||||
@Override | |||||
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { | |||||
try (Jedis jedis = jedisPool.getResource()) { | |||||
return lock.acquire(jedis); | |||||
} | |||||
} | |||||
@Override | |||||
public void unlock() { | |||||
try (Jedis jedis = jedisPool.getResource()) { | |||||
lock.release(jedis); | |||||
} | |||||
} | |||||
@Override | |||||
public Condition newCondition() { | |||||
throw new RuntimeException("unsupported method"); | |||||
} | |||||
protected Jedis getJedis() { | |||||
return jedisPool.getResource(); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,24 @@ | |||||
package cn.binarywang.wx.miniapp.config.impl; | |||||
import redis.clients.jedis.Jedis; | |||||
/** | |||||
* 基于Redis的微信配置provider. 使用自己管理的 Jedis 实例进行 Redis 操作。 | |||||
* | |||||
* <pre> | |||||
* 需要引入依赖<a href="https://github.com/abelaska/jedis-lock">jedis-lock</a>,才能使用该类。 | |||||
* </pre> | |||||
*/ | |||||
public class WxMaRedisConnectionConfigImpl extends AbstractWxMaRedisConfig { | |||||
public WxMaRedisConnectionConfigImpl(Jedis jedis) { | |||||
this.jedis = jedis; | |||||
} | |||||
private Jedis jedis; | |||||
@Override | |||||
protected Jedis getJedis() { | |||||
return jedis; | |||||
} | |||||
} |