/**
*
* @author xuyw
* @email xyw10000@163.com
* @date 2014-06-12
*/
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。
正常情况下access_token有效期为7200秒,反复获取将导致上次获取的access_token失效。因为获取access_token的api调用次数很有限。建议开发人员全局存储与更新access_token,频繁刷新access_token会导致api调用受限。影响自身业务。
access_token调用频率一天为2000次,假设简单的使用自己定义菜单全然够用.仅仅是微信推出多客服后,假设频繁发送客服消息,将有可能不够用
那么怎么延长?应当将其缓存起来循环使用
公众平台的开发接口的access_token长度将增长,其存储至少要保留512个字符空间
能够考虑使用redis缓存技术将其缓存起来。本人比較推荐。
设置缓存可将其设置1小时30分钟自己主动失效。可避免临界条件2小时的问题。获取从redis 缓存 获取access_token 若为空则去又一次请求。将获取的结果存入redis。以便下次使用。
access_token存储起来,下次须要access_token则将其查出。若是失效则。又一次创建并更新数据库.若是没有失效,则直接使用。
附上我的小小设计,不足之处还望指出
数据库设计
CREATE TABLE `wx_access_token` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`access_token` varchar(600) NOT NULL COMMENT 'access_token凭证',
`expires_in` bigint(20) NOT NULL COMMENT '凭证有效时间。单位:秒',
`create_time` bigint(20) NOT NULL COMMENT '创建时间距离当前时间毫秒数',
`userid` varchar(128) NOT NULL COMMENT 'userid',
`create_date` varchar(25) NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
核心代码
省略第一次调用保存代码,相信大家都会
以后调用代码,先查询
// 存在
String _token = map.get("access_token") + "";
String expires_in = map.get("expires_in") + "";
String create_time = map.get("create_time") + "";
int _in = Integer.parseInt(expires_in);
long _time = Long.parseLong(create_time);
if ((System.currentTimeMillis()-_time)/1000 < _in) {// 有效
//System.out.println("无须创建");
accessToken = new AccessToken();
accessToken.setExpiresIn(_in);
accessToken.setToken(_token);
} else {// 无效
//System.out.println("无效又一次创建");
Map map2 = new HashMap();
map2.put("create_time", System.currentTimeMillis());
map2.put("userid", uid);
accessToken = WxUtil.getAccessToken(appid, appsecret);
map2.put("access_token", accessToken.getToken());
map2.put("expires_in", accessToken.getExpiresIn());
wxDao.saveAccessToken(map2);//更新数据库
}
public static AccessToken getAccessToken(String appid, String appsecret) {
AccessToken accessToken = null;
String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?
grant_type=client_credential&appid="+appid+"&secret="+appsecret; JSONObject jsonObject = httpRequest(requestUrl, "GET", null); // 假设请求成功 if (null != jsonObject) { try { accessToken = new AccessToken(); accessToken.setToken(jsonObject.getString("access_token")); accessToken.setExpiresIn(jsonObject.getInt("expires_in")); } catch (JSONException e) { accessToken = null; // 获取token失败 log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg")); } } return accessToken; }
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据须要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式。防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
log.error("Weixin server connection timed out.");
} catch (Exception e) {
log.error("https request error:{}", e);
}
return jsonObject;
}
public class MyX509TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
public class AccessToken {
// 获取到的凭证
private String token;
// 凭证有效时间。单位:秒
private int expiresIn;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
}