使用HashMap缓存Cookie

本文介绍了如何使用ConcurrentHashMap结合LinkedList在Java中缓存Cookie。通过创建特定的Cookie类,并在多线程环境中使用synchronized关键字确保线程安全,实现高效的内存缓存策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用ConcurrentHashMap 设置Cookie

上篇说到将Cookie 存到HttpServletResponse中,前端缓存的形式。现在将cookie缓存至内存。
使用ConcurrentHashMap结合LinkedList的形式,将cookie缓存。

1.先设置cookie类。

  public class CookieObj {
      /**
       * 缓存对象
       */
      private Object cacheValue;
      /**
       * 设置过期时间
       */
      private Long ttlTime;
  
      public CookieObj() {
      }
  
      public CookieObj(Object cacheValue, long ttlTime) {
          this.cacheValue = cacheValue;
          this.ttlTime = ttlTime;
      }
  
      public Object getCacheValue() {
          return cacheValue;
      }
  
      public void setCacheValue(Object cacheValue) {
          this.cacheValue = cacheValue;
      }
  
      public Long getTtlTime() {
          return ttlTime;
      }
  
      public void setTtlTime(Long ttlTime) {
          this.ttlTime = ttlTime;
      }
  
      @Override
      public String toString() {
          return "CookieObj{" +
                  "cacheValue=" + cacheValue +
                  ", ttlTime=" + ttlTime +
                  '}';
      }
  }

2 设置cookie

  /**
   * @description: Cookie缓存工具类
   * @author: Lina
   * @create: 2020-11-24 19:38
   */
  public class CookieUtils {
      private static Logger LOGGER = LoggerFactory.getLogger(CookieUtils.class);
  
      /**
       * 最大缓存数量
       */
      private static final Integer COOKIE_MAX = 1000;
  
      /**
       * 当前缓存个数
       */
      private static Integer CURRENT_SIZE = 0;
  
      /**
       * 设置清除定时时长为3h
       */
      static final Long CLEAR_TIME = 3 * 60 * 60 * 1000L;
      /**
       * 设置在线时长为2h
       */
      static final Long ONLINE_TIME = 2 * 60 * 60 * 1000L;
      /**
       * 清理过期缓存是否在运行
       */
      private static volatile Boolean CLEAN_THREAD_IS_RUN = false;
      /**
       * 缓存对象
       */
      private static final Map<String, CookieObj> COOKIE_MAP = new ConcurrentHashMap<>();
  
      /**
       * 最近使用的
       */
      private static final List<String> COOKIE_USE_LOG_LIST = new LinkedList<>();
  
      /**
       * 设置缓存cookie
       *
       * @param cookieKey
       * @param cookieValue
       */
      public static void setCookie(String cookieKey, Object cookieValue) {
          Long ttlTime = null;
          checkSize();
          saveCookieUseLog(cookieKey);
          CURRENT_SIZE = CURRENT_SIZE + 1;
          if (ttlTime == null) {
              ttlTime = System.currentTimeMillis() + ONLINE_TIME; //设置cookie时长
          }
          CookieObj cookieObj = new CookieObj(cookieValue, ttlTime);
          COOKIE_MAP.put(cookieKey, cookieObj);
          LOGGER.info("设置的cookieKey为 :" + cookieKey);
      }
  
      /**
       * 通过key 获取cookie值
       *
       * @param cookieKey
       * @return
       */
      public static String getCookie(String cookieKey) {
          startCleanCookieThread();
          if (checkCookie(cookieKey)) {
              saveCookieUseLog(cookieKey);
              LOGGER.info("获取到的cookie值为:" + COOKIE_MAP.get(cookieKey).getCacheValue().toString());
              return COOKIE_MAP.get(cookieKey).getCacheValue().toString();
          }
          return null;
      }
  
      /**
       * 保存缓存的使用记录,用Linked保存一个cookie,后续用来处理过期的cookie
       *
       * @param cookieKey
       */
      private static void saveCookieUseLog(String cookieKey) {
          synchronized (COOKIE_USE_LOG_LIST) {
              COOKIE_USE_LOG_LIST.remove(cookieKey);
              COOKIE_USE_LOG_LIST.add(0, cookieKey);
          }
      }
  
      /**
       * 判断
       *
       * @param cookieKey
       * @return
       */
      public static boolean isExist(String cookieKey) {
          return checkCookie(cookieKey);
      }
  
      /**
       * 检查缓存是否存在,检查是否过期
       * @param cookieKey
       * @return
       */
      private static boolean checkCookie(String cookieKey) {
          CookieObj cookieObj = COOKIE_MAP.get(cookieKey);
          if (cookieObj == null) {
              return false;
          }
          if (cookieObj.getTtlTime() == -1L) {
              return true;
          }
          if (cookieObj.getTtlTime() < System.currentTimeMillis()) {
              deleteCookie(cookieKey);
              return false;
          }
          return true;
      }
  
      /**
       * 删除过期Cookie
       *
       * @param cookieKey
       * @return
       */
      private static void deleteCookie(String cookieKey) {
          Object cookieObj = COOKIE_MAP.remove(cookieKey);
          if (cookieObj != null) {
              LOGGER.info("删除过期Cookie" + cookieKey);
              CURRENT_SIZE = CURRENT_SIZE - 1;
          }
      }
  
      /**
       * 删除所有缓存的Cookie
       */
      static void clearAll() {
          COOKIE_MAP.clear();
          CURRENT_SIZE = 0;
          LOGGER.info("清除所有缓存的Cookie");
      }
  
  
      /**
       * 检查Cookie个数
       */
      private static void checkSize() {
          // 若超过限制,则清除过期的cookie
          if (CURRENT_SIZE >= COOKIE_MAX) {
              deleteTimeOut();
          }
          if (CURRENT_SIZE >= COOKIE_MAX) {
              deleteLru();
          }
      }
  
      /**
       * 删除最近最久未用的cookie
       */
      private static void deleteLru() {
          String cookieKey = null;
          synchronized (COOKIE_USE_LOG_LIST) {
              if (COOKIE_USE_LOG_LIST.size() >= COOKIE_MAX - 10) {
                  cookieKey = COOKIE_USE_LOG_LIST.remove(COOKIE_USE_LOG_LIST.size() - 1);
              }
          }
          if (cookieKey != null) {
              deleteCookie(cookieKey);
          }
          LOGGER.info("删除最近最久未用的cookie");
      }
  
      /**
       * 清除过期的cookie
       */
      static void deleteTimeOut() {
          LOGGER.info("clear timeOut cookie:");
          List<String> deleteList = new LinkedList<>();
          for (Map.Entry<String, CookieObj> entry : COOKIE_MAP.entrySet()) {
              if (entry.getValue().getTtlTime() < System.currentTimeMillis() && entry.getValue().getTtlTime() != -1L) {
                  deleteList.add(entry.getKey());
              }
          }
          // 将过期的Cookie删除
          for (String deleteKey : deleteList) {
              deleteCookie(deleteKey);
          }
          LOGGER.info("已删除cookie条数:" + deleteList.size());
      }
  
      /**
       * 设置清理线程的运行状态为正在运行
       */
      static void setCleanThreadRun() {
          CLEAN_THREAD_IS_RUN = true;
      }
  
      private static void startCleanCookieThread() {
          if (!CLEAN_THREAD_IS_RUN) {
              CleanOutLineThread cleanOutLineThread = new CleanOutLineThread();
              Thread thread = new Thread(cleanOutLineThread);
              thread.setName("清除Cookie的线程");
              thread.setDaemon(true);
              thread.start();
          }
      }
  
  }
  
  class CleanOutLineThread implements Runnable {
      private static Logger LOGGER = LoggerFactory.getLogger(CleanOutLineThread.class);
  
      @Override
      public void run() {
          CookieUtils.setCleanThreadRun();
          while (true) {
              LOGGER.info("开始清除过期cookie");
              CookieUtils.deleteTimeOut();
              try {
                  Thread.sleep(CookieUtils.CLEAR_TIME);
              } catch (Exception e) {
                  LOGGER.error("清除过期cookie出错");
              }
          }
      }
  }

以上是使用ConcurrentHashMap缓存cookie的方法。期间使用的LinkedList也需要synchronized关键字,同步代码快,来保证线程竞争问题,保证在多线程的环境下,安全使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值