Springboot集成Ehcache3实现本地缓存

如果只需要在单个应用程序中使用本地缓存,则可以选择Ehcache;它支持内存和磁盘存储,这里不以注解方式演示,通过自己实现缓存管理者灵活控制缓存的读写;

1、引入相关依赖

java 复制代码
		<!-- ehcache3集成start -->
		<dependency>
			<groupId>org.ehcache</groupId>
			<artifactId>ehcache</artifactId>
			<version>3.10.8</version>
		</dependency>
		<dependency>
			<groupId>javax.cache</groupId>
			<artifactId>cache-api</artifactId>
		</dependency>
		<!-- ehcache3集成end -->

2、修改yml配置

java 复制代码
spring:
  cache:
    type: jcache
    jcache:
      config: classpath:cache/ehcache.xml

3、配置ehcache.xml文件

XML 复制代码
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.ehcache.org/v3"
        xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd">
    <!-- 缓存持久化配置: 定义磁盘缓存位置 -->
    <persistence directory="E:/project_home/limit_control/cache/light-element-mybatis"/>
    <!-- 缓存模板: 未填写缓存名时使用的默认缓存,同时也可被继承 -->
    <cache-template name="defaultCache">
        <key-type>java.lang.String</key-type>
        <value-type>java.lang.Object</value-type>
        <resources>
            <heap unit="MB">64</heap>
            <offheap unit="MB">128</offheap>
        </resources>
    </cache-template>
    <!-- 缓存列表: 自定义缓存配置 -->
    <!-- 不过期 -->
    <cache alias="EXPIRE_NONE" uses-template="defaultCache"/>
    <!-- 24小时过期 -->
    <cache alias="EXPIRE_24_HOURS" uses-template="defaultCache">
        <expiry>
            <ttl unit="hours">24</ttl>
        </expiry>
    </cache>
    <!-- 30分钟过期 -->
    <cache alias="EXPIRE_30_MINUTES" uses-template="defaultCache">
        <expiry>
            <ttl unit="minutes">30</ttl>
        </expiry>
    </cache>
</config>

4、编写缓存策略枚举

java 复制代码
public enum CacheStrategy {
    EXPIRE_30_MINUTES,
    EXPIRE_24_HOURS,
    EXPIRE_NONE
}

5、编写缓存管理者,来控制缓存的增删改查

java 复制代码
import com.alibaba.fastjson.JSON;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
 * ehcache3缓存管理者
 */
@Configuration
@EnableCaching
public class EhCacheManager {
    private static CacheManager cacheManager;

    public EhCacheManager(CacheManager cacheManager) {
        EhCacheManager.cacheManager = cacheManager;
    }

    /**
     * 获取默认缓存
     *
     * @return
     */
    public static Cache getDefaultCache() {
        return getCache("EXPIRE_24_HOURS");
    }

    /**
     * 获取指定缓存
     *
     * @param cacheName 缓存名称
     * @return
     */
    public static Cache getCache(String cacheName) {
        if (cacheManager == null) {
            return null;
        }
        return cacheManager.getCache(cacheName);
    }

    /**
     * 获取缓存内容(对象)
     *
     * @param cacheName 缓存名称
     * @param key       键
     * @param clazz<T>  class类型
     * @return
     */
    public static <T extends Object> T getObjValue(String cacheName, String key, Class<T> clazz) {
        Object o = getValue(cacheName, key);
        if (o == null) {
            return null;
        }
        T t = (T) JSON.parseObject(JSON.toJSONString(o), clazz);
        return t;
    }

    /**
     * 获取缓存内容(集合)
     *
     * @param cacheName 缓存名称
     * @param key       键
     * @param clazz<T>  class类型
     * @return
     */
    public static <T extends Object> List<T> getListValue(String cacheName, String key, Class<T> clazz) {
        Object o = getValue(cacheName, key);
        if (o == null) {
            return null;
        }
        List<T> ts = JSON.parseArray(JSON.toJSONString(o), clazz);
        return ts;
    }

    /**
     * 获取缓存内容
     *
     * @param cacheName
     * @param key
     * @return
     */
    private static Object getValue(String cacheName, String key) {
        Cache cache = getCache(cacheName);
        if (cache == null && cache.get(key) == null) {
            return null;
        }
        Cache.ValueWrapper valueWrapper = cache.get(key);
        if (valueWrapper == null) {
            return null;
        }
        Object o = valueWrapper.get();
        if (o == null) {
            return null;
        }
        return o;
    }

    /**
     * 新增或修改缓存数据
     *
     * @param cacheName 缓存名称
     * @param key       键
     * @param value     值
     */
    public static void put(String cacheName, String key, Object value) {
        Cache cache = getCache(cacheName);
        if (cache == null) {
            return;
        }
        cache.put(key, value);
    }

    /**
     * 删除缓存数据
     *
     * @param cacheName 缓存名称
     * @param key       键
     */
    public static void del(String cacheName, String key) {
        Cache cache = getCache(cacheName);
        if (cache == null) {
            return;
        }
        cache.evict(key);
    }
}

6、编写controller进行简单测试

java 复制代码
import cn.hutool.core.collection.CollectionUtil;
import com.yx.light.element.mybatis.cache.CacheStrategy;
import com.yx.light.element.mybatis.cache.EhCacheManager;
import com.yx.light.element.mybatis.mapper.entity.GroupHeader;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping(value = "/index")
@Slf4j
public class IndexController {

    @GetMapping(value = "/list")
    public List<GroupHeader> list() {
        List<GroupHeader> listValue = EhCacheManager.getListValue(CacheStrategy.EXPIRE_30_MINUTES.name(), "list", GroupHeader.class);
        if (CollectionUtil.isEmpty(listValue)) {
            log.info("集合缓存不存在或已过期,查询数据库!");
            //模拟查库
            List<GroupHeader> objects = new ArrayList<>();
            for (int i = 0; i < 5; i++) {
                GroupHeader groupHeader = new GroupHeader();
                groupHeader.setGroupCode("aaaaa-" + i);
                groupHeader.setGroupName("多个对象" + i);
                objects.add(groupHeader);
            }
            listValue = objects;
            EhCacheManager.put(CacheStrategy.EXPIRE_30_MINUTES.name(), "list", listValue);
            log.info("集合数据加载到缓存!");
        } else {
            log.info("从集合缓存中直接获取数据!");
        }
        return listValue;
    }

    @GetMapping(value = "/one")
    public GroupHeader one() {
        GroupHeader objValue = EhCacheManager.getObjValue(CacheStrategy.EXPIRE_30_MINUTES.name(), "obj", GroupHeader.class);
        if (objValue == null) {
            log.info("对象缓存不存在或已过期,查询数据库!");
            //模拟查库
            GroupHeader groupHeader = new GroupHeader();
            groupHeader.setGroupCode("aaaaa");
            groupHeader.setGroupName("单个对象");
            objValue = groupHeader;
            EhCacheManager.put(CacheStrategy.EXPIRE_30_MINUTES.name(), "obj", groupHeader);
            log.info("对象数据加载到缓存!");
        } else {
            log.info("从对象缓存中直接获取数据!");
        }
        return objValue;
    }

    @GetMapping(value = "/del")
    public void del() {
        log.info("清理对象缓存!");
        EhCacheManager.del(CacheStrategy.EXPIRE_30_MINUTES.name(), "obj");
    }

}

7、分别调用接口查看日志打印

相关推荐
皮皮林55122 分钟前
拒绝写重复代码,试试这套开源的 SpringBoot 组件,效率翻倍~
java·spring boot
用户908324602733 天前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
用户8307196840823 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解3 天前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解3 天前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记4 天前
Spring Boot Web MVC配置详解
spring boot·后端
初次攀爬者4 天前
Kafka 基础介绍
spring boot·kafka·消息队列
用户8307196840824 天前
spring ai alibaba + nacos +mcp 实现mcp服务负载均衡调用实战
spring boot·spring·mcp
Java水解4 天前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端