何为access_token?引用微信官方的一定义:access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。微信获取access_token接口每日限制调用2000次,因此我们必须将token保存起来,省着点去获取新的access_token。
最简单的方式就是保存在内存中,此方法适用于单机应用。如果服务是集群或者分布式应用,还是保存在数据库中吧。此例以保存在内存中为例。
1:token过期的时候重新去获取新的token。
2:内存中拿不到token的时候去调用微信接口获取token。
CoreService类:
/**
* 获取微信公众号平台接口的ACCESS_TOKEN
* @return
*/
public String getWeixinAccessToken(){
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
ServletContext application = webApplicationContext.getServletContext();
if(application.getAttribute("tokenMap")!=null){
WeixinAccessToken tempToken=(WeixinAccessToken) application.getAttribute("tokenMap");
if(System.currentTimeMillis()>tempToken.getExpirationTime()){
return tempToken.getAccessToken();
}else{
return getAccessToken();
}
}else{
return getAccessToken();
}
}
private String getAccessToken() {
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
ServletContext application = webApplicationContext.getServletContext();
String appId=appid;
String appSecret=secret;
String url="https://api.weixin.qq.com/cgi-bin/token";
String returnData=Common.sendGet(url,"grant_type=client_credential&appid="+appId+"&secret="+appSecret);
JSONObject json=JSONObject.fromObject(returnData);
if(json.containsKey("access_token")){
if(json.get("access_token")!=null&&!json.get("access_token").equals("")){
application.setAttribute("tokenMap", new WeixinAccessToken(json.get("access_token").toString(),
System.currentTimeMillis()+Integer.parseInt(json.get("expires_in").toString())));
return json.get("access_token").toString();
}
}
return null;
}
上面的实现麻烦了些,还有另外一种方式是将access_token存在redis,利用redis的过期策略来维护access_token的有效期。
实现如下:
/**
* 获取access_token
* @return
*/
private String getAccessToken(){
//从缓存里去获取token
String weixinAccessToken=JedisUtil.get("weixinAccessToken");
if(StringUtil.isBlank(weixinAccessToken)){
String appId=appid;
String appSecret=secret;
String url="https://api.weixin.qq.com/cgi-bin/token";
String returnData=HttpUtil.sendGet(url,"grant_type=client_credential&appid="+appId+"&secret="+appSecret);
JSONObject json=JSONObject.fromObject(returnData);
if(json.containsKey("access_token")){
if(json.get("access_token")!=null&&!json.get("access_token").equals("")){
weixinAccessToken=json.get("access_token").toString();
JedisUtil.set("weixinAccessToken",weixinAccessToken, 7200);
}
}
}
return weixinAccessToken;
}
WeixinAccessToken类:
public class WeixinAccessToken {
private String accessToken;
private long expirationTime;
public WeixinAccessToken(){
}
public WeixinAccessToken(String accessToken,long expirationTime){
this.accessToken=accessToken;
this.expirationTime=expirationTime;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public long getExpirationTime() {
return expirationTime;
}
public void setExpirationTime(long expirationTime) {
this.expirationTime = expirationTime;
}
}
发送get请求和post请求工具类HttpUtil:
/**
* 向指定URL发送GET方法的请求
* @param url 发送请求的URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/**
* 发送post请求
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setConnectTimeout(30000);
conn.setRequestProperty("Accept", "*/*");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}