使用 Map + 定时器 定时存取微信 Token
来源:互联网 发布:java jsoup 爬虫实例 编辑:程序博客网 时间:2024/06/14 04:58
微信的 Token 可以存放在数据库里 , 需要的时候从数据库读取 . 但是这样日积月累 , 数据量会逐渐撑大 , 而且 token 我们用指定时间(两小时内)就会丢弃 , 以后也不会用到过期的 token , 所以将它保存在数据库是很浪费资源的 . 所以我写了个缓存类来定时获取微信的 token 到 map
首先 , 定义存 map 的方法
package com.newtec.weixin.manager;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ScheduledThreadPoolExecutor;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.newtec.weixin.pojo.CacheConfModel;/** * 使用 map 作为一级缓存 , 必要时代替数据库存取token */public class CacheMgr { private static Logger log = LoggerFactory.getLogger(CacheMgr.class); public static Map cacheMap = new HashMap();//存放缓存 public static Map cacheConfMap = new HashMap();//存放配置信息 static final Lock lock = new ReentrantLock(); public static String key; private static Object value; private static CacheConfModel ccm; //单例 private static CacheMgr cacheMgr = null; private CacheMgr(){} public static CacheMgr getIntance(){ if(cacheMgr == null){ cacheMgr = new CacheMgr(); } return cacheMgr; } /** * 增加缓存信息 * @param key * @param value * @param ccm * @return */ public class AddCache implements Runnable{ public AddCache(String key,Object value,CacheConfModel ccm) { CacheMgr.key = key; CacheMgr.value = value; CacheMgr.ccm = ccm; } @Override public void run() { //定时线程处理的业务 log.info("开始清理缓存--- {}",key); ClearCache.clearCache();//每次运行清除上次缓存 只有一个token缓存能够存在 log.info("开始缓存--- {}",key); lock.lock(); try { cacheMap.put(key, value); cacheConfMap.put(key, ccm); log.info("增加缓存结束:key={},value={}",key,value); log.info("缓存大小为={}",cacheMap.size()); } catch (Exception e) { e.printStackTrace(); }finally{ lock.unlock(); } } } /** * 获取缓存实体 * @param key 缓存键 * @return */ public Object getValue(String key){ Object obj = cacheMap.get(key); if(obj != null){ return obj; }else{ return null; } } /** * 获取缓存总数 * @return 缓存总数 */ public int getSize(){ return cacheMap.size(); } /** * 删除缓存 * @param key * @return */ public boolean removeCache(String key){ boolean flag = false; try { cacheMap.remove(key); cacheConfMap.remove(key); flag = true; } catch (Exception e) { e.printStackTrace(); } return flag; }}
如果你没有 log 的 jar 包 , 可以选择不打印 log
由于我们每次只用到一个 token , 当最新的 token 生成时 ,以前的 token 都会失效 , 所以在增加 token缓存之前需要清理之前的缓存
public class ClearCache{ static final Lock lock = new ReentrantLock(); final Condition myLock = lock.newCondition(); public static void clearCache(){ while(true){ try { lock.lock();//每次只允许一个线程清理缓存 Set tempSet = new HashSet(); Set set = CacheMgr.cacheMap.keySet(); Iterator it = set.iterator(); while(it.hasNext()){//迭代 String key = (String) it.next(); CacheConfModel ccm = (CacheConfModel)CacheMgr.cacheConfMap.get(key); tempSet.add(key); //记录清除数据 } //清除 Iterator tempIt = tempSet.iterator(); while(tempIt.hasNext()){ String key = (String) tempIt.next(); CacheMgr.cacheMap.remove(key); CacheMgr.cacheConfMap.remove(key); } if(CacheMgr.cacheMap.size()<=0 && CacheMgr.cacheConfMap.size()<=0){//如果缓存已被清空,跳出循环 , 否则继续清理 , 知道 map 中没有 token 为止 break; } } catch (Exception e) { e.printStackTrace(); }finally{ lock.unlock(); } } }}
然后我们需要一个 servlet 执行缓存存取过程
public class AutoLoadCacheServlet extends HttpServlet { private static CacheMgr cacheMgr = CacheMgr.getIntance(); private static ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(1); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { CacheConfModel cModel = new CacheConfModel(); Date d = new Date(); cModel.setBeginTime(d.getTime()); cModel.setDurableTime(60); cModel.setForever(true); AddCache addCache = cacheMgr.new AddCache("TOKEN", CommonUtil.getToken( CommonUtil.APPID, CommonUtil.APPSECRET).getAccessToken(), cModel); //执行的回调方法,第一次执行时间,周期,时间类型 stpe.scheduleAtFixedRate(addCache, 0, 7000,TimeUnit.SECONDS); //System.out.println(CacheMgr.cacheMap.get("TOKEN")); } }
缓存配置类 – CacheConfModel
public class CacheConfModel { private long beginTime;// 缓存开始时间 private boolean isForever = false;// 是否持久保存 private int durableTime;// 持续时间 public long getBeginTime() { return beginTime; } public void setBeginTime(long beginTime) { this.beginTime = beginTime; } public boolean isForever() { return isForever; } public void setForever(boolean isForever) { this.isForever = isForever; } public int getDurableTime() { return durableTime; } public void setDurableTime(int durableTime) { this.durableTime = durableTime; }}
最后在启动 web 项目时 , 自动装载这个 servelet
在 web.xml 配置
<servlet> <servlet-name>autoLoadCacheServlet</servlet-name> <servlet-class>com.newtec.weixin.servlet.AutoLoadCacheServlet </servlet-class> <load-on-startup>0</load-on-startup> </servlet>
这样当 web 项目启动时 , 缓存就会通过定时器自动增加并清理
这里不使用 timer 的原因是
Timer 和 Timertask 是单线程的,而且没有处理异常,当程序超过指定时间没有运行的时候,程序就会异常终止 , 即使我们用线程锁使得缓存存取/清理同步了 , 仍然不能保证不会在处理缓存的时候跑出异常导致程序终止
所以需要多个线程或者需要额外的灵活性和功能时,推荐使用ScheduledThreadPoolExecutor
阅读全文
1 0
- 使用 Map + 定时器 定时存取微信 Token
- 微信开发定时器更新token
- 定时刷新获取八爪鱼token(获取微信token也是一样的道理)
- 使用thinkphp微信token验证失败
- 微信Token验证
- 微信获取token
- 微信Token失败
- 微信token验证
- 微信token验证
- 微信开发定时获取token,保证线程安全,高可用
- 使用缓存Memcache存储更新微信access token
- 使用缓存Memcache存储更新微信access token
- 使用缓存Memcache存储更新微信access token
- 使用缓存Memcache存储更新微信access token
- 使用缓存Memcache存储更新微信access token
- thinphp3.2 使用微信扩展类 token验证失败
- 微信token验证代码
- 微信开发-Token处理
- 把妹需要勇敢,心有猛虎,细嗅蔷薇
- storm 1.1.0 与 kafka 2.10-0.10.2.1的安装部署
- WebLogic使用总结(七)——WebLogic部署Web应用并绑定域名
- 2017年6月28日
- 网络编程(基于winsocket)-- 常用函数介绍(一)
- 使用 Map + 定时器 定时存取微信 Token
- Linux内核分析
- 各位相加
- js 异步实现与编程
- Injection for Xcode:成吨的提高开发效率
- 异方差性质
- 阿里yum源的配置与本地yum源的配置
- scala 使用jxl导出多sheet页
- 论文翻译