使用guava过期map

时间:2021-06-29 12:30:01

最近需要将微信的accesstoken保存到缓存里面,防止重复请求微信接口获取token,造成token请求次数超标,其实随便一个缓存都可以轻松解决,但是现有的环境中没有redis,没有memcahe,做一个这个小功能,不需要引入这些框架,就用guava的过期map就可以了,不要要是服务宕机了,可又要重新获取了,这个...不再考虑范围内了.

依赖包:

        <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>

Cache这个类有很多,防止导错,给出包名:

import com.alibaba.fastjson.JSON;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

声明全局静态变量Cache

private static Cache<String, String> cache = null;

设置过期时间,一般微信的token过期时间是7200s,我设的短一些:

    /**
* 缓存其accessToken 和 ticketToken 的值
*
* @param key
* @return
* @throws Exception
*/
public static String getTicketToken(String key) throws Exception{
if (Objects.isNull(cache) || getCacheAccessToken(key).equals(WeChatConstant.TICKET_TOKEN)){
Gson gson = new Gson();
cache = CacheBuilder.newBuilder().expireAfterWrite(7100,TimeUnit.SECONDS).build();
String accessToken = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+WeChatConstant.APPID +"&secret="+WeChatConstant.SECRET;
String httpResult = getHttpResult(accessToken);
log.info("获取的accesstoken:{}",httpResult);
System.out.println("----"+accessToken+"----");
AccessToken aT = gson.fromJson(accessToken, AccessToken.class);
String signUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+aT.getAccess_token()+"&type=jsapi";
String resultSign = getHttpResult(signUrl);
TicketToken ticket = gson.fromJson(resultSign, TicketToken.class);
log.info("生成的ticket:{},值是:{}",ticket,ticket.getTicket());
cache.put(WeChatConstant.TICKET_TOKEN,ticket.getTicket());
log.info("重新生成accessToken:{},{}",accessToken,new Date(System.currentTimeMillis()));
return ticket.getTicket();
}else{
return getCacheAccessToken(key);
}
}

 

    /**
* token失效,返回key值
*
* @param key
* @return
* @throws ExecutionException
*/
private static String getCacheAccessToken(String key) throws ExecutionException {
return cache.get(key, () -> {
return key;
});
} /**
* 随机加密
* @param hash
* @return
*/
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
/**
* 获取访问地址链接返回值
*/
private static String getHttpResult(String url) {
String result = "";
HttpGet httpRequest = new HttpGet(url);
try {
HttpResponse httpResponse = HttpClients.createDefault().execute(httpRequest);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
result = EntityUtils.toString(httpResponse.getEntity());
}
} catch (ClientProtocolException e) {
e.printStackTrace();
result = e.getMessage().toString();
} catch (IOException e) {
e.printStackTrace();
result = e.getMessage().toString();
}
return result;
}
/**
* 产生随机串--由程序自己随机产生
* @return
*/
private static String create_nonce_str() {
return UUID.randomUUID().toString();
}
/**
* 由程序自己获取当前时间
* @return
*/
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}

  给出两个json转换的实体类:

/**
* @author zhangyi
* @date 2019/2/11 17:19
*/
@Data
public class AccessToken {
private String access_token;
private Integer expires_in;
}

  

/**
* @author zhangyi
* @date 2019/2/11 17:25
*/
@Data
public class TicketToken { private Integer errcode; private String errmsg; private String ticket; private Integer expires_in; }

常量:

    /**
* 第三方用户唯一凭证即appsecret
*/
public static final String SECRET = ""; /**
* 第三方用户唯一凭证密钥,
*/
public static final String APPID = ""; /**
* 微信access_token
*/
public static final String ACCESS_TOKEN = "ACCESS_TOKEN";
/**
* 微信ticket_token
*/
public static final String TICKET_TOKEN = "TICKET_TOKEN";

至此完成这个功能就不需要引入框架,直接使用这个工具类就可以完成了,俗话说:杀鸡焉用宰牛刀,哈哈,希望可以帮到各位