本人原本是想做微信公眾號菜單的創建修改刪除等操作的,但是發現需要access_token,通過閱讀文檔,發現文檔要求有以下幾點:
1.access_token 獲取后有效期是2小時
2.access_token 占用512個字符空間
3.獲取access_token 的url 為(get請求) : https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
4.請求成功返回的格式為:{"access_token":"ACCESS_TOKEN","expires_in":7200}
思路:
1.前提必須是成功獲取到 access_token
2. 項目里需要配置一個定時器,用來定期獲取 access_token
3.成功獲取后應該把access_token妥善保存,比如保存在 數據庫、緩存(本人所選,redis)、配置文件中都可以
步驟一:獲取access_token

1 package com.encore.util; 2 3 import org.json.JSONObject; 4 5 import java.io.BufferedReader; 6 import java.io.InputStreamReader; 7 import java.net.HttpURLConnection; 8 import java.net.URL; 9 import java.util.List; 10 import java.util.Map; 11 12 public class WeChatTokenUtil { 13 //獲取access_token的url 14 private static final String BASE_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?"; 15 //固定值 16 private static final String GRANT_TYPE = "client_credential"; 17 //自己的AppID 18 private static final String APP_ID = "**********"; 19 //自己的AppSecret 20 private static final String SECRET = "***********"; 21 22 public static String getToken(){ 23 String url = BASE_TOKEN_URL + "grant_type="+GRANT_TYPE+"&appid="+APP_ID+"&secret="+SECRET; 24 try{ 25 URL realUrl = new URL(url); 26 // 打開和URL之間的連接 27 HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection(); 28 connection.setRequestMethod("GET"); 29 connection.connect(); 30 // 獲取所有響應頭字段 31 Map<String, List<String>> map = connection.getHeaderFields(); 32 // 遍歷所有的響應頭字段 33 for (String key : map.keySet()) { 34 System.err.println(key + "--->" + map.get(key)); 35 } 36 // 定義 BufferedReader輸入流來讀取URL的響應 37 BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); 38 String result = ""; 39 String line; 40 while ((line = in.readLine()) != null) { 41 result += line; 42 } 43 JSONObject jsonObject = new JSONObject(result); 44 return jsonObject.getString("access_token"); 45 } catch (Exception e) { 46 System.err.printf("獲取token失敗!"); 47 e.printStackTrace(System.err); 48 return ""; 49 } 50 } 51 52 }
步驟二:配置定時器:
在spring的xml中配置:

1 <!-- 定時器配置 --> 2 <task:annotation-driven scheduler="myScheduler"/> 3 <task:scheduler id="myScheduler" pool-size="5"/>
注意:寫定時方法的類必須在spring能夠掃描的到的包下
步驟三:配置redis(如果不用redis可以跳過此步驟,直接把access_token保存到數據庫或者配置文件中就可以了)
1.前提是本機裝了redis,網上有很多教程,本文不做過多介紹,並不復雜
2.引入項目需要的redis依賴

1 <!-- redis 依賴 --> 2 <dependency> 3 <groupId>redis.clients</groupId> 4 <artifactId>jedis</artifactId> 5 <version>2.9.0</version> 6 <type>jar</type> 7 </dependency>
3.配置reids連接(跟配置jdbc連接類似)

1 redis.host=127.0.0.1 2 redis.port=6379 3 redis.timeout=3000
4.新建一個reids.xml

1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 6 7 <context:property-placeholder location="classpath:redis.properties" /> 8 9 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" /> 10 11 <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool" scope="singleton" > 12 <constructor-arg index="0" ref="jedisPoolConfig" /> 13 <constructor-arg index="1"> 14 <list> 15 <bean class="redis.clients.jedis.JedisShardInfo"> 16 <constructor-arg name="host" value="${redis.host}"/> 17 <constructor-arg name="port" value="${redis.port}"/> 18 <constructor-arg name="timeout" value="${redis.timeout}"/> 19 </bean> 20 </list> 21 </constructor-arg> 22 </bean> 23 24 </beans>
5.將redis.xml引入到spring的xml中

1 <import resource="redis.xml"/>
6.編寫一個redis連接池的類,包含安全關閉連接池的方法,同樣也要使這個類能夠被spring所掃描到

1 package com.encore.service; 2 3 import lombok.extern.slf4j.Slf4j; 4 import org.springframework.stereotype.Service; 5 import redis.clients.jedis.ShardedJedis; 6 import redis.clients.jedis.ShardedJedisPool; 7 8 import javax.annotation.Resource; 9 10 @Service("redisPool") 11 @Slf4j 12 public class RedisPool { 13 14 @Resource(name = "shardedJedisPool") 15 private ShardedJedisPool shardedJedisPool; 16 17 public ShardedJedis instance(){ 18 return shardedJedisPool.getResource(); 19 } 20 21 public void safeClose(ShardedJedis shardedJedis){ 22 try { 23 if (shardedJedis != null){ 24 shardedJedis.close(); 25 } 26 }catch (Exception e){ 27 log.error("redis 關閉異常", e); 28 } 29 } 30 }
7.封裝一個類,提供把數據寫入redis和從redis中讀取數據的方法,也要讓這個類被spring所管理

1 package com.encore.service; 2 3 import org.springframework.stereotype.Service; 4 import redis.clients.jedis.ShardedJedis; 5 6 import javax.annotation.Resource; 7 8 @Service("redisCacheService") 9 public class RedisCacheService { 10 11 // 注入RedisPool 12 @Resource(name = "redisPool") 13 private RedisPool redisPool; 14 15 16 /** 17 * 把要存儲的值放進緩存 18 * @param cacheKey 鍵值,可以用來獲取要存儲的值 19 * @param toSavedValue 要存儲的值 20 * @param timeOutSeconds 過期時間 單位為秒 21 */ 22 public void saveCache(String cacheKey, String toSavedValue, int timeOutSeconds){ 23 if (toSavedValue == null){ 24 return; 25 } 26 ShardedJedis shardedJedis = null; 27 try { 28 shardedJedis = redisPool.instance(); 29 shardedJedis.setex(cacheKey, timeOutSeconds, toSavedValue); 30 }catch (Exception e){ 31 e.printStackTrace(); 32 }finally { 33 redisPool.safeClose(shardedJedis); 34 } 35 } 36 37 /** 38 * 根據鍵值從緩存中獲取數據 39 * @param cacheKey 緩存的鍵值 40 * @return 41 */ 42 public String getFromCache(String cacheKey){ 43 ShardedJedis shardedJedis = null; 44 try { 45 shardedJedis = redisPool.instance(); 46 String value = shardedJedis.get(cacheKey); 47 return value; 48 }catch (Exception e){ 49 return null; 50 }finally { 51 redisPool.safeClose(shardedJedis); 52 } 53 } 54 55 56 }
步驟四:實現定時器的方法(這個類要可以被spring掃描的到),實現每1.5小時獲取一次access_token,並將其放到redis,同時保證可以從redis中讀取出來

1 package com.encore.service; 2 3 import com.encore.util.WeChatTokenUtil; 4 import org.springframework.scheduling.annotation.Scheduled; 5 import org.springframework.stereotype.Component; 6 7 import javax.annotation.Resource; 8 9 @Component 10 public class TaskService { 11 12 @Resource 13 private RedisCacheService redisCacheService; 14 15 private static final String TOKEN_KEY = "my_wechat_token"; 16 17 @Scheduled(fixedRate= 1000*60*90, initialDelay = 2000)//項目啟動2秒中之后執行一次,然后每90min執行一次,單位都為ms 18 public void getToken(){ 19 //1. 獲取token 20 String access_token = WeChatTokenUtil.getToken(); 21 System.out.println("從微信服務器獲取的token======"+access_token); 22 redisCacheService.saveCache(TOKEN_KEY, access_token ,60*120); 23 String getToken = redisCacheService.getFromCache(TOKEN_KEY); 24 System.out.println("從redis中獲取的token === "+getToken); 25 } 26 }
最后,在開啟項目進行測試的時候,先把redis服務器打開,經測試,可以正常獲取access_token,也可以存放到redis中,同時也可以從redis中讀取出來,如圖所示,可以從Redis Desktop Manager中看得到存放進去的access_token: