最近在准备面试,决定把自己做过的项目中的逻辑梳理一次。
1:SDK请求微信的时候。
首先是向微信端发送请求,
发送请求包含了:
- 1:根据账户和密码来获取token。String accessToken = getAccessToken(false)
- 2:如果获取token后,开始去请求微信,
- 3:如果发生了错误,就会去判断错误类型,是不是token不正确,或者是token失效了
如果是token问题/失效,就强制去让token在redis中过期,这样下一次请求就会去刷新token
然后重新去获取token,获取后重新设置到redis中。
然后再次去执行请求,此时就直接从redis中获取了token,
整个请求,有个重试次数,如果请求重试次数超过了限制,就直接报错。
在获取token的过程中,进行了加锁操作。加锁过程中,存放最新的token到redis中
jedis.setex(this.accessTokenKey, expiresInSeconds - 200, accessToken);
setex是一个原子性的操作,主要是解决,设置值,以及设置过期时间不是原子性的问题。
获取token的步骤是:
//如果过期了,就去重新获取
if (!this.getWxMpConfigStorage().isAccessTokenExpired() && !forceRefresh) {
return this.getWxMpConfigStorage().getAccessToken();
}
//加锁来防止多线程获取
Lock lock = this.getWxMpConfigStorage().getAccessTokenLock();
lock.lock();
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 {
lock.unlock();
}
网友评论