access_token 是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
1、为了保密appsecrect,第三方需要一个access_token获取和刷新的中控服务器。而其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则会造成access_token覆盖而影响业务;
2、目前access_token的有效期通过返回的expire_in来传达,目前是7200秒之内的值。中控服务器需要根据这个有效时间提前去刷新新access_token。在刷新过程中,中控服务器对外输出的依然是老access_token,此时公众平台后台会保证在刷新短时间内,新老access_token都可用,这保证了第三方业务的平滑过渡;
3、access_token的有效时间可能会在未来有调整,所以中控服务器不仅需要内部定时主动刷新,还需要提供被动刷新access_token的接口,这样便于业务服务器在API调用获知access_token已超时的情况下,可以触发access_token的刷新流程。
http请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
下面介绍的方法并非使用中控服务器更新token,而是通过一个默认启动的servlet,启动一个进程,该进程会不停的请求微信接口获取token,若获取成功,就会休眠7000秒。
代码:
token实体类
AccessToken .java
package com.sh.po;
public class AccessToken {
private String accessToken;
private int expiresin;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public int getExpiresin() {
return expiresin;
}
public void setExpiresin(int expiresin) {
this.expiresin = expiresin;
}
}
默认启动的servlet
AccessTokenServlet.java
package com.sh.sevlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sh.util.TokenThread;
import java.io.IOException;
/**
* 定义一个默认启动的servlet,在init方法中启动一个Thread,这个进程中定义一个无限循环的方法,用来获取access_token,
* 当获取成功后,此进程休眠7000秒,否则休眠3秒钟继续获取
* @author Administrator
*
*/
public class AccessTokenServlet extends HttpServlet {
public void init() throws ServletException {
//获取servlet初始参数appid和appsecret(参数在web.xml配置),并赋值给TokenThread对应的静态全局变量。
//TokenThread.appId和TokenThread.appSecret是静态的
TokenThread.appId = getInitParameter("appid");
TokenThread.appSecret = getInitParameter("appsecret");
System.out.println("appid:"+TokenThread.appId);
System.out.println("appSecret:"+TokenThread.appSecret);
new Thread(new TokenThread()).start(); //启动进程
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
web.xml配置
<servlet>
<servlet-name>AccessTokenServletservlet-name>
<servlet-class>com.sh.sevlet.AccessTokenServletservlet-class>
<init-param>
<param-name>appidparam-name>
<param-value>APPIDparam-value>
init-param>
<init-param>
<param-name>appsecretparam-name>
<param-value>APPSECRETparam-value>
init-param>
<load-on-startup>0load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>AccessTokenServletservlet-name>
<url-pattern>/accesstokenservleturl-pattern>
servlet-mapping>
获取access_token的进程类
package com.sh.util;
import org.json.JSONObject;
import com.sh.po.AccessToken;
/**
* 定义Thread类,在此类中调用access_token获取接口,并将得到的数据抽象到静态实体,以便在其它地方使用
* @author Administrator
*
*/
public class TokenThread implements Runnable {
public static String appId = "";
public static String appSecret= "";
//注意是静态的,可以全局存储访问。
public static AccessToken accessToken = null;
public void run(){
while (true){
try{
accessToken = this.getAccessToken(); //调用getAccessToken获取access_token
if(null!=accessToken){
System.out.println(accessToken.getAccessToken());
Thread.sleep(7000 * 1000); //获取到access_token 休眠7000秒
}else{
Thread.sleep(1000*3); //access_token为空 休眠3秒
}
}catch(Exception e){
System.out.println("发生异常:"+e.getMessage());
e.printStackTrace();
try{
Thread.sleep(1000*10); //发生异常休眠1秒
}catch (Exception e1){
}
}
}
}
/**
* 获取access_token
* @return
*/
private AccessToken getAccessToken(){
//微信jssdk获取jsapi_ticket时获取access_tokend的请求路径 https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
//此处获取的access_token和网页授权时获取的access_token的不同
String jsticket = "";
try {
jsticket = Http.methodGet("https://api.weixin.qq.com/cgi-bin/token","grant_type=client_credential&appid="+this.appId+"&secret="+this.appSecret+"");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JSONObject ticket = new JSONObject(jsticket);
AccessToken token = new AccessToken();
token.setAccessToken(ticket.getString("access_token"));
return token;
}
}
在poster.java的使用
String jstoken = TokenThread.accessToken.getAccessToken();