Browse Source

#1100 小程序模块添加Redis配置类WxMaInRedisConfig

master
winter 5 years ago
committed by Binary Wang
parent
commit
16bb8f122a
3 changed files with 411 additions and 1 deletions
  1. +1
    -1
      pom.xml
  2. +6
    -0
      weixin-java-miniapp/pom.xml
  3. +404
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaInRedisConfig.java

+ 1
- 1
pom.xml View File

@@ -246,7 +246,7 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
</dependencies>


+ 6
- 0
weixin-java-miniapp/pom.xml View File

@@ -80,6 +80,12 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.github.jedis-lock</groupId>
<artifactId>jedis-lock</artifactId>
<version>1.0.0</version>
<optional>true</optional>
</dependency>
</dependencies>

<build>


+ 404
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/config/WxMaInRedisConfig.java View File

@@ -0,0 +1,404 @@
package cn.binarywang.wx.miniapp.config;

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 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.JedisPool;

/**
* 基于Redis的微信配置provider.
*
* <pre>
* 需要引入依赖<a href="https://github.com/abelaska/jedis-lock">jedis-lock</a>,才能使用该类。
* </pre>
*
* @author <a href="https://github.com/winter4666">winter</a>
*/
public class WxMaInRedisConfig 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";
protected JedisPool jedisPool;
/**
* 微信小程序唯一id,用于拼接存储到redis时的key,防止key重复
*/
protected String maId;
protected volatile String msgDataFormat;
protected volatile String appid;
protected volatile String secret;
protected volatile String token;
protected volatile String aesKey;

protected volatile String httpProxyHost;
protected volatile int httpProxyPort;
protected volatile String httpProxyUsername;
protected volatile String httpProxyPassword;

protected Lock accessTokenLock;
protected Lock jsapiTicketLock;
protected Lock cardApiTicketLock;

/**
* 临时文件目录
*/
protected volatile File tmpDirFile;

protected 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();
}
}
private String getValueFromRedis(String key) {
Jedis jedis = jedisPool.getResource();
try {
return jedis.hget(getRedisKey(key), HASH_VALUE_FIELD);
} finally {
jedis.close();
}
}
private void setValueToRedis(String key, long expiresTime, String value) {
Jedis jedis = jedisPool.getResource();
try {
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);
} finally {
jedis.close();
}
}
private long getExpireFromRedis(String key) {
Jedis jedis = jedisPool.getResource();
try {
String expire = jedis.hget(getRedisKey(key), HASH_EXPIRE_FIELD);
return expire == null ? 0 : Long.valueOf(expire);
} finally {
jedis.close();
}
}
private void setExpire(String key, long expiresTime) {
Jedis jedis = jedisPool.getResource();
try {
jedis.hset(getRedisKey(key), HASH_EXPIRE_FIELD, String.valueOf(expiresTime));
} finally {
jedis.close();
}
}

public void setJedisPool(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
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() {
Jedis jedis = jedisPool.getResource();
try {
if(!lock.acquire(jedis)) {
throw new RuntimeException("acquire timeouted");
}
} catch (InterruptedException e) {
throw new RuntimeException("lock failed",e);
} finally {
jedis.close();
}
}

@Override
public void lockInterruptibly() throws InterruptedException {
Jedis jedis = jedisPool.getResource();
try {
if(!lock.acquire(jedis)) {
throw new RuntimeException("acquire timeouted");
}
} finally {
jedis.close();
}
}

@Override
public boolean tryLock() {
Jedis jedis = jedisPool.getResource();
try {
return lock.acquire(jedis);
} catch (InterruptedException e) {
throw new RuntimeException("lock failed",e);
} finally {
jedis.close();
}
}

@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
Jedis jedis = jedisPool.getResource();
try {
return lock.acquire(jedis);
} finally {
jedis.close();
}
}

@Override
public void unlock() {
Jedis jedis = jedisPool.getResource();
try {
lock.release(jedis);
} finally {
jedis.close();
}
}

@Override
public Condition newCondition() {
throw new RuntimeException("unsupported method");
}
}
}

Loading…
Cancel
Save