mirror of
https://gitee.com/gz-yami/mall4j.git
synced 2026-03-22 09:17:16 +08:00
更新集群模式多次重复获取微信accessToken的问题
This commit is contained in:
@@ -45,5 +45,5 @@ public @interface RedisLock {
|
||||
*
|
||||
* @return 秒
|
||||
*/
|
||||
TimeUnit timeUnit() default TimeUnit.SECONDS;
|
||||
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.yami.shop.mp.component;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
|
||||
import com.yami.shop.common.exception.YamiShopBindException;
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.BasicResponseHandler;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
/**
|
||||
* WxMaServiceImpl 在集群模式获取accessToken的方式
|
||||
* @author LGH
|
||||
*/
|
||||
public class WxMaServiceClusterImpl extends WxMaServiceImpl {
|
||||
|
||||
|
||||
private static final String REDISSON_LOCK_PREFIX = "redisson_lock:";
|
||||
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
public void setRedissonClient(RedissonClient redissonClient) {
|
||||
this.redissonClient = redissonClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
|
||||
if (!this.getWxMaConfig().isAccessTokenExpired() && !forceRefresh) {
|
||||
return this.getWxMaConfig().getAccessToken();
|
||||
}
|
||||
|
||||
RLock rLock = redissonClient.getLock(REDISSON_LOCK_PREFIX + ":WxMaServiceCluster:getAccessToken");
|
||||
|
||||
boolean doingUpdateAccessToken;
|
||||
|
||||
try {
|
||||
doingUpdateAccessToken = rLock.tryLock(10, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
return this.getWxMaConfig().getAccessToken();
|
||||
}
|
||||
|
||||
if (!doingUpdateAccessToken) {
|
||||
throw new YamiShopBindException("服务器繁忙,请稍后再试");
|
||||
}
|
||||
|
||||
if (this.getWxMaConfig().isAccessTokenExpired()) {
|
||||
return this.getWxMaConfig().getAccessToken();
|
||||
}
|
||||
|
||||
try {
|
||||
String url = String.format(WxMaService.GET_ACCESS_TOKEN_URL, this.getWxMaConfig().getAppid(),
|
||||
this.getWxMaConfig().getSecret());
|
||||
try {
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
if (this.getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
|
||||
httpGet.setConfig(config);
|
||||
}
|
||||
try (CloseableHttpResponse response = getRequestHttpClient().execute(httpGet)) {
|
||||
String resultContent = new BasicResponseHandler().handleResponse(response);
|
||||
WxError error = WxError.fromJson(resultContent);
|
||||
if (error.getErrorCode() != 0) {
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
|
||||
this.getWxMaConfig().updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
|
||||
|
||||
return this.getWxMaConfig().getAccessToken();
|
||||
} finally {
|
||||
httpGet.releaseConnection();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} finally {
|
||||
rLock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.yami.shop.mp.component;
|
||||
|
||||
import com.yami.shop.common.exception.YamiShopBindException;
|
||||
import me.chanjar.weixin.common.WxType;
|
||||
import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.BasicResponseHandler;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* WxMpServiceImpl 在集群模式获取accessToken的方式
|
||||
* @author LGH
|
||||
*/
|
||||
public class WxMpServiceClusterImpl extends WxMpServiceImpl {
|
||||
|
||||
|
||||
private static final String REDISSON_LOCK_PREFIX = "redisson_lock:";
|
||||
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
public void setRedissonClient(RedissonClient redissonClient) {
|
||||
this.redissonClient = redissonClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
|
||||
if (!this.getWxMpConfigStorage().isAccessTokenExpired() && !forceRefresh) {
|
||||
return this.getWxMpConfigStorage().getAccessToken();
|
||||
}
|
||||
|
||||
RLock rLock = redissonClient.getLock(REDISSON_LOCK_PREFIX + ":WxMpServiceCluster:getAccessToken");
|
||||
|
||||
boolean doingUpdateAccessToken;
|
||||
|
||||
try {
|
||||
doingUpdateAccessToken = rLock.tryLock(10, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
return this.getWxMpConfigStorage().getAccessToken();
|
||||
}
|
||||
|
||||
if (!doingUpdateAccessToken) {
|
||||
throw new YamiShopBindException("服务器繁忙,请稍后再试");
|
||||
}
|
||||
|
||||
if (this.getWxMpConfigStorage().isAccessTokenExpired()) {
|
||||
return this.getWxMpConfigStorage().getAccessToken();
|
||||
}
|
||||
|
||||
|
||||
Object result = null;
|
||||
try {
|
||||
String url = String.format(WxMpService.GET_ACCESS_TOKEN_URL,
|
||||
this.getWxMpConfigStorage().getAppId(), this.getWxMpConfigStorage().getSecret());
|
||||
try {
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
if (this.getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
|
||||
httpGet.setConfig(config);
|
||||
}
|
||||
try (CloseableHttpResponse response = getRequestHttpClient().execute(httpGet)) {
|
||||
String resultContent = new BasicResponseHandler().handleResponse(response);
|
||||
WxError error = WxError.fromJson(resultContent, WxType.MP);
|
||||
if (error.getErrorCode() != 0) {
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
|
||||
this.getWxMpConfigStorage().updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
|
||||
return this.getWxMpConfigStorage().getAccessToken();
|
||||
} finally {
|
||||
httpGet.releaseConnection();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
} finally {
|
||||
rLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,9 @@ package com.yami.shop.mp.config;
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
|
||||
import com.yami.shop.mp.component.WxMaInRedisConfig;
|
||||
import com.yami.shop.mp.component.WxMaServiceClusterImpl;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -30,10 +32,13 @@ public class WxMaConfiguration {
|
||||
|
||||
private final WxMaInRedisConfig wxMaInRedisConfig;
|
||||
|
||||
private final RedissonClient redissonClient;
|
||||
|
||||
@Bean
|
||||
public WxMaService wxMaService() {
|
||||
WxMaService service = new WxMaServiceImpl();
|
||||
WxMaServiceClusterImpl service = new WxMaServiceClusterImpl();
|
||||
service.setWxMaConfig(wxMaInRedisConfig);
|
||||
service.setRedissonClient(redissonClient);
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,11 +11,13 @@
|
||||
package com.yami.shop.mp.config;
|
||||
|
||||
import com.yami.shop.mp.component.WxMpInRedisConfigStorage;
|
||||
import com.yami.shop.mp.component.WxMpServiceClusterImpl;
|
||||
import com.yami.shop.mp.handler.MenuHandler;
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -34,11 +36,13 @@ public class WxMpConfiguration {
|
||||
|
||||
private final MenuHandler menuHandler;
|
||||
private final WxMpInRedisConfigStorage wxMpInRedisConfigStorage;
|
||||
private final RedissonClient redissonClient;
|
||||
|
||||
@Bean
|
||||
public WxMpService wxMpService() {
|
||||
WxMpService service = new WxMpServiceImpl();
|
||||
WxMpServiceClusterImpl service = new WxMpServiceClusterImpl();
|
||||
service.setWxMpConfigStorage(wxMpInRedisConfigStorage);
|
||||
service.setRedissonClient(redissonClient);
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user