java缓存数据并配置有效时间[通俗易懂]

java缓存数据并配置有效时间[通俗易懂]没有用到redis只是单纯的使用内存存储数据实现的功能:缓存数据并配置有效时间,可设置默认时间自动清除缓存,也可以自己设置。直接上代码:importjava.util.LinkedList;importjava.util.List;importjava.util.Map.Entry;importjava.util.Timer;importjava.util.TimerTask;importjava.util.concurrent.ConcurrentHashMap;publ

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

没有用到redis 只是单纯的使用内存存储数据

实现的功能:缓存数据并配置有效时间,可设置默认时间自动清除缓存,也可以自己设置。

直接上代码:

import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

public class TimeExpiredPoolCache {
    private static  long defaultCachedMillis = 10 * 60 * 1000L;//过期时间默认10分钟
    private static long timerMillis = 10 * 60 * 1000L;//定时清理默认10分钟
    /**
     * 对象池
     */
    private static ConcurrentHashMap<String, DataWrapper<?>> dataPool = null;
    /**
     * 对象单例
     */
    private static TimeExpiredPoolCache instance = null;
    private TimeExpiredPoolCache() {
        dataPool = new ConcurrentHashMap<String, DataWrapper<?>>();
    }
    private static synchronized void syncInit() {
        if (instance == null) {
            instance = new TimeExpiredPoolCache();
            initTimer();
        }
    }
    public static TimeExpiredPoolCache getInstance() {
        if (instance == null) {
            syncInit();
        }
        return instance;
    }
    /**
     * 定时器定时清理过期缓存
     */
    private static Timer timer = new Timer();
    private static void initTimer() {
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    clearExpiredCaches();
                } catch (Exception e) {
                    //logger.error("clearExpiredCaches error.", e);
                }
            }
        }, timerMillis, timerMillis);
    }

    /**
     * 缓存数据
     * @param key key值
     * @param data 缓存数据
     * @param cachedMillis 过期时间
     * @param dataRenewer 刷新数据
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T put(String key, T data, long cachedMillis, DataRenewer<T> dataRenewer) throws Exception {
        DataWrapper<T> dataWrapper = (DataWrapper<T>)dataPool.get(key);
        if (data == null && dataRenewer != null) {
            data = dataRenewer.renewData();
        }
        //当重新获取数据为空,直接返回不做put
        if (data == null){
            return null;
        }
        if (dataWrapper != null) {
            //更新
            dataWrapper.update(data, cachedMillis);
        } else {
            dataWrapper = new DataWrapper<T>(data, cachedMillis);
            dataPool.put(key, dataWrapper);
        }
        return data;
    }
    /**
     * 直接设置缓存值和时间
     * @param key
     * @param data
     * @param cachedMillis
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T put(String key, T data, long cachedMillis) throws Exception{
        DataWrapper<T> dataWrapper = (DataWrapper<T>)dataPool.get(key);
        if (dataWrapper != null) {
            //更新
            dataWrapper.update(data, cachedMillis);
        } else {
            dataWrapper = new DataWrapper<T>(data, cachedMillis);
            dataPool.put(key, dataWrapper);
        }
        return data;
    }
    /**
     * 默认构造时间的缓存数据
     * @param key
     * @param data
     * @param dataRenewer
     * @return
     */
    @Deprecated
    public <T> T put(String key, T data, DataRenewer<T> dataRenewer) throws Exception {
        return put(key, data, defaultCachedMillis, dataRenewer);
    }
    /**
     * 获取缓存
     * @param key
     * @param cachedMillis
     * @param dataRenewer
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String key, long cachedMillis, DataRenewer<T> dataRenewer) throws Exception {
        DataWrapper<T> dataWrapper = (DataWrapper<T>)dataPool.get(key);
        if (dataWrapper != null && !dataWrapper.isExpired()) {
            return dataWrapper.data;
        }
        return put(key, null, cachedMillis, dataRenewer);
    }
    @SuppressWarnings("unchecked")
    public <T> T get(String key) throws Exception {
        DataWrapper<T> dataWrapper = (DataWrapper<T>)dataPool.get(key);
        if (dataWrapper != null && !dataWrapper.isExpired()) {
            return dataWrapper.data;
        }
        return null;
    }
    /**
     * 清除缓存
     */
    public void clear() {
        dataPool.clear();
    }

    /**
     * 删除指定key的value
     * */
    public void remove(String key){
        dataPool.remove(key);
    }

    /**
     * 数据封装
     */
    private class DataWrapper<T> {
        /**
         * 数据
         */
        private T data;
        /**
         * 到期时间
         */
        private long expiredTime;
        /**
         * 缓存时间
         */
        private long cachedMillis;
        private DataWrapper(T data, long cachedMillis) {
            this.update(data, cachedMillis);
        }
        public void update(T data, long cachedMillis) {
            this.data = data;
            this.cachedMillis = cachedMillis;
            this.updateExpiredTime();
        }
        public void updateExpiredTime() {
            this.expiredTime = System.currentTimeMillis() + cachedMillis;
        }
        /**
         * 数据是否过期
         * @return
         */
        public boolean isExpired() {
            if (this.expiredTime > 0) {
                return System.currentTimeMillis() > this.expiredTime;
            }
            return true;
        }
    }
    /**
     * 数据构造
     */
    public interface DataRenewer<T> {
        public T renewData();
    }

    /**
     * 清除过期的缓存
     */
    private static void clearExpiredCaches() {
        List<String> expiredKeyList = new LinkedList<String>();

        for(Entry<String, DataWrapper<?>> entry : dataPool.entrySet()){
            if (entry.getValue().isExpired()) {
                expiredKeyList.add(entry.getKey());
            }
        }
        for (String key : expiredKeyList) {
            dataPool.remove(key);
        }
    }
	}

测试:

import com.example.demo2.utils.TimeExpiredPoolCache;
import org.springframework.web.bind.annotation.*;

@RestController
public class CacheDemo {

    @RequestMapping(value = "/saveToken", method = RequestMethod.GET)
    public String  saveToken(){
        try {
            TimeExpiredPoolCache.getInstance().put("token","1008611",1000L*30);
            new TimeThread().run();
            return "保存token进入缓冲成功";
        } catch (Exception e) {
            return "保存token进入缓存失败";
        }
    }

    @RequestMapping(value = "/getToken", method = RequestMethod.GET)
    public String  getToken(){
        try {
           // token = String.valueOf(TimeExpiredPoolCache.getInstance().get("token"));
            String   token = TimeExpiredPoolCache.getInstance().get("token");
            if (null!=token){
                return token;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return "数据为空................";
    }

    public static class TimeThread implements  Runnable{

        @Override
        public void run() {
            for(int i=30;i>0;i--){
                System.out.println("缓冲倒计时:"+i+" 秒");
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

浏览直接访问 (我这里设置的端口号是8888)
在这里插入图片描述
localhost:8888/saveToken 调用存储token值为1008611,时间为30秒有效
在这里插入图片描述
localhost:8888/getToken 可以获取token值,可以在缓存有效期内和有效期外分别调用,看下缓存值是否存在
在这里插入图片描述
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/185958.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • React 时间控件

    React 时间控件使用bootstrap的datetimepicker安装:npminstallreact-bootstrap-datetimepicker使用bootstrap的datetime安装:npminstall–savereact-datetime若使用中文,还需要安装moment,这样datetime插件中的locale属性(控制语言)才能够正常使用:安装moment:npminstal

    2022年5月23日
    84
  • 课程表课程设计_工程经济学课程设计

    课程表课程设计_工程经济学课程设计一、需求分析由于大学上课教室分散,学生经常会忘记自己的课程或是上课的教室。这在一定程度上促进学生课表软件的开发。使其可以帮助学生记录自己的课程和对自己课程的掌握。因为手机相对笔记本电脑更加具有便携性

    2022年8月3日
    9
  • 9. 数仓开发之 DWD 层

    9. 数仓开发之 DWD 层数仓开发之DWD层交易域加购事务事实表DWD层设计要点:DWD层的设计依据:维度建模理论,该层存储维度模型的事实表DWD层的数据存储格式:orc列式存储+snappy压缩DWD层表名的命名规范:dwd_数据域_表名_单分区增量****全量标识(inc/full)交易域加购事务事实表…

    2022年6月26日
    38
  • socket常用函数_socket是可重入函数吗

    socket常用函数_socket是可重入函数吗前言socketpair是Linux下的函数,其主要作用是创建一对套节字来进行进程间通信,其与匿名管道(PIPE)的作用相似,这两个套节字均可读可写.具体介绍见本博客另一篇文章:https://blog.csdn.net/wufuhuai/article/details/79747912实现我们都知道socket不仅能够进行跨进程通信,而且socket是可以双向通信的,即是…

    2022年10月14日
    2
  • Java 二维数组转换成List<List<String>>[通俗易懂]

    Java 二维数组转换成List<List<String>>[通俗易懂]在拿到二维数组的数据时,需要将它转换成嵌套的list,如下工具类:importjava.util.ArrayList;importjava.util.List;/***将二维数组转换成List>形式工具**@authorqiulinhe**2017年3月1日下午3:09:52*/publicclassArrayToListTe

    2022年6月20日
    193
  • 内存泄漏以及常见的解决方法

    内存泄漏以及常见的解决方法

    2021年12月3日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号