/**
 * 
 * @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;
	}
}