springboot整合ehcache实现二级缓存踩坑

1 篇文章 0 订阅
1 篇文章 0 订阅

最近在优化项目代码,发现了有一个接口A执行的时候会频繁调用另一个获取用户信息的接口B。虽然接口B加了redis缓存,但是由于redis服务器是单独部署,频繁的I/O请求仍然对接口响应性能有影响,于是想到了加二级缓存,这样接口A调用接口B的时候可以把重复的用户信息暂存,进而提高性能。

二级缓存很多,我选择了ehcache。在网上搜了一些教程,发现配置非常简单,于是立刻着手做,然而过程其实并不顺利,踩了一些坑,这里记录下。

1、pom引入。注意<version>标签,如果是springboot的话应该会自动匹配版本号,也可以自己填写2.10.6之类的。

            <dependency>
                <groupId>net.sf.ehcache</groupId>
                <artifactId>ehcache</artifactId>
                <version>${ehcache.version}</version>
            </dependency>

2、在resources目录下创建一个ehcache.xml配置文件,该文件存储了ehcache相关的配置,示例如下。我这里配置了一个名叫gatewayUser的缓存,过期时间设置为2分钟,下面会用到。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

    <diskStore path="java.io.tmpdir"/>

    <!-- 设定缓存的默认数据过期策略 -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"/>

    <!-- 自定义的缓存 -->
    <cache name="gatewayUser"
           maxElementsInMemory="1000"
           eternal="false"
           timeToIdleSeconds="120"/>

</ehcache>

这里有一个小点需要注意:

<ehcache>标签中的

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"

可以不加,没什么影响。如果加了发现飘红,可采用以下方式处理Idea 使用ehcache.xml 出现异常_OY..的博客-CSDN博客

3、在Application启动类上添加@EnableCaching注解

4、在方法上加注解:

注意这里的value一定和xml配置文件中的名字相同。比如这里的value为“gatewayUser”,则对应的就是ehcache.xml文件中自定义的“gatewayUser”配置,表示该方法的缓存都会使用同一个配置,且都会放在同一个缓存中。key表示每个缓存的唯一标识,这里用userId就可以了。

特别注意,为了使得@Cacheable生效,方法必须是public;如果同一个类中调用,还必须注入当前类,这样才能触发AOP。

网上很多资料到这里基本就结束了,但如果你运行程序并调用该方法,会报错,类似这种:

{
  "code": 8000,
  "data": [],
  "message": "未知错误java.lang.IllegalArgumentException: Cannot find cache named 'gatewayUser' for Builder......
}

程序提示没有找到相应的cache,如果在源码上打断点,会发现确实没有正确的加载缓存配置: 

这里有人会说需要在application.yml中加以下配置:

spring.cache.ehcache.config=classpath:ehcache.xml

但其实加了仍旧会报错!因为ehcache默认的会去resource目录下找ehcache.xml配置,所以这里加不加无所谓。其实这里是少了一个配置类。

5、(重要)再写一个cacheManager配置类:

package ......

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;


@Configuration
@EnableCaching
public class EhCacheConfig {

    //需要生成一个缓存管理器
    @Bean
    public CacheManager cacheManager() {
        net.sf.ehcache.CacheManager ehCM = ehCacheCacheManager().getObject();
        CacheManager cacheManager = new EhCacheCacheManager(ehCM);
        return cacheManager;
    }

    //缓存管理器由该工厂Bean生成
    @Bean
    public EhCacheManagerFactoryBean ehCacheCacheManager() {
        EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
        cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));//工厂去读配置文件
        cmfb.setShared(true);

        return cmfb;
    }
}

 再次运行程序,发现缓存已生效!

到这里ehcache缓存已经能够正常工作了。

在方法内部我们仍旧使用redis进行缓存。这样就实现了二级缓存,程序性能又能提升啦。

@Cacheable(value="gatewayUser", key="#userId")
public GatewayUser getUserInfoByUserId(Integer userId) {
        String key = "userinfo:" + userId.toString();
        //尝试从redis缓存中获取
        String userstr = redis.opsForValue().get(key);
        GatewayUser gatewayUser = null;
        if (StringUtils.isNotBlank(userstr)) {
            return JSON.parseObject(userstr, GatewayUser.class);
        } else {
            //到数据库中查询
            //将查询结果插入redis缓存中
            redis.opsForValue().set(key, reportStat);
            redis.expire(key, 3600 * 48, TimeUnit.SECONDS);

            return gatewayUser;
        }
        
    }

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值