1.access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token,所以这个数据是非常的重要的,首先阅读以下微信开发文档,对于access_token是这样写的。
根据文档的指示,我们的access_token的需求如下:单一获取和刷新access_token的值,全局保存,用到的都去这个地方去拿。定时去刷新(现在是2个小时刷新一次)
2.我们使用redis来全局缓存access_token的值,需要用到access_token的时候就去redis当中去取。并且,这个值每两个小时刷新一次。
//刷新access_token 100分钟刷新一次,服务器启动的时候刷新一次(access_token有效期是120分钟,我设置的是每100分钟刷新一次)
@Scheduled(initialDelay = 1000, fixedDelay = 100*60*1000)
public void get_access_token() {
try {
String appid = "填上你公众号的appid";
String appsecret = "填上你公众号的appsecret";
String requestUrl = "https://api.weixin.qq/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
requestUrl = requestUrl.replace("APPID",appid).replace("APPSECRET",appsecret);
JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl,"GET",null);
if(jsonObject.getString("access_token")!=null){
Jedis jedis = jedisPool.getResource();
try {
Map<String,String> map = new HashMap<String,String>();
map.put("access_token",jsonObject.getString("access_token"));
jedis.hmset(appid, map);
} catch(Exception e){
if(jedis != null){
jedis.close();
jedis = null;
}
e.printStackTrace();
} finally {
if(jedis != null){
jedis.close();
}
}
}
else{
logger.info("定时刷新access_token失败,微信返回的信息是"+jsonObject.toJSONString());
}
}
catch (Exception e){
logger.info("更新access_token的过程当中发生了异常,异常的信息是"+e.getMessage());
}
}
/**
* 发送https请求
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
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 conn = (HttpsURLConnection) url.openConnection();
//HttpURLConnection con= url.openConnection();
conn.setSSLSocketFactory(ssf);
//2017年9月15日16:21:40
//新设置的,可能是一直在链接导致的程序死亡
conn.setConnectTimeout(10 * 1000);
conn.setReadTimeout(50 * 1000);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
jsonObject = JSONObject.parseObject(buffer.toString());
} catch (ConnectException ce) {
System.out.println("连接超时:{}" + ce);
} catch (Exception e) {
System.out.println("https请求异常:{}" + e);
//log.error("https请求异常:{}", 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 {
}
// 返回受信任的X509证书数组
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
其中jedisPool的配置如下:
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.poolMaxIdle}")
private int maxIdle;
@Value("${spring.redis.poolMaxWait}")
private long maxWaitMillis;
/*@Value("${spring.redis.password}")
private String password;*/
@Bean
@Scope("singleton")
public JedisPool redisPoolFactory() {
System.out.println("jedispool");
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, null);
logger.info("host:"+host);
logger.info("port:"+port);
logger.info("timeout:"+timeout);
return jedisPool;
}
这样,我们就把access_token全局进行了缓存,在其他需要使用到access_token的时候,就去redis当中获取数据,调用其他的接口。我们满足了微信开发文档的三点要求
1.全局唯一获取刷新access_token ,全局缓存,需要的都去redis当中去取。
2.定时刷新access_token,不会出现access_token过期的情况
3.access_token有效时间可能会在未来有调整,到时候我们只需要改一下定时器的时间即可。
更多推荐
JAVA微信公众号开发-获取access_token并保证access_token长久有效
发布评论