分分钟实践SpringBoot+Ehcache

前言

以前一直用Redis做缓存,但后来慢慢了解到了Ehcache,貌似Redis的名声早就超越了Ehcache,就很少看到有人提起Ehcache以及文章,但是,还是有必要了解一下的,说不定以后会用的上。更何况Ehcache也是Java领域中比较优秀的缓存,不知道小伙伴发现没,Ehcache正着念反着念,都是 Ehcache。

Ehcache简介

Ehcache是一个用Java实现的使用简单、高速、线程安全的缓存管理类库,提供了用内存、磁盘文件存储,以及分布式存储等管理方案。同时Ehcache作为开放源代码项目,采用限制比较宽松的Apache License V2.0作为授权方式,被广泛地用于Hibernate、Spring 等其他开源系统。

Ehcache的主要特点如下:

  1. 快速、简单。在过去众多的测试中已经表明Ehcache是最快的Java缓存之一,Ehcache的线程机制是为大型高并发系统设计的,Ehcache的API也易于使用,很容易部署上线和运行。

  2. 多种缓存策略。提供LRU、LFU和FIFO缓存策略。

  3. 缓存数据有两级。内存和磁盘,因此无须担心容量问题。缓存在内存和硬盘存储可以伸缩到GB

  4. 缓存数据会在虚拟机重启的过程中写入磁盘。Ehcache 是第一个引入缓存数据持久化存储的开源Java缓存框架,缓存的数据可以在机器重启后从磁盘上重新获得,可以通过cache.flush方法将缓存写入到磁盘上面。

  5. 可以通过RMI、 可插入API等方式进行分布式缓存。

  6. 具有缓存和缓存管理器的监听接口(CacheManagerEventListener、CacheEventListener)。

普通Java项目使用

到目前为止,ehcache最新版本是3.8.1,但是由于大部分的博客都低于这个版本,API可能有差异了,无法参考,所以还是到官网http://www.ehcache.org/documentation/3.8/getting-started.html下。

<!-- https://mvnrepository.com/artifact/org.ehcache/ehcache -->
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.8.1</version>
</dependency>

另外ehcache使用SLF4J进行记录,如果是普通Java项目,还需要加入以下依赖。

 <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-api</artifactId>
     <version>1.7.25</version>
 </dependency>
 <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-nop</artifactId>
     <version>1.7.2</version>
 </dependency>

下面是代码示例。

public class Main {
    public static void main(String[] args) {
        /**
         * 构建CacheManager和一个Cache,别名为cache-1,键值对为Long和String
         */
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                .withCache("cache-1",
                        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)))
                .build();
        cacheManager.init();

        /**
         * 获取别名为cache-1的Cache
         */
        Cache<Long, String> cache1 =
                cacheManager.getCache("cache-1", Long.class, String.class);


        /**
         * 获取值,如果没有,则返回null
         */
        System.out.println(cache1.get(1L));
        /**
         * put一个值
         */
        cache1.put(1L,"缓存值");
        System.out.println(cache1.get(1L));


        /**
         * 通过createCache创建一个Cache
         */
        cacheManager.createCache("cache-2",
                CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, User.class, ResourcePoolsBuilder.heap(10)));
        Cache<Long, User> cache2 =
                cacheManager.getCache("cache-2", Long.class, User.class);
        System.out.println(cache2.get(1L));
        cache2.put(1L,new User("张三"));
        System.out.println(cache2.get(1L).getName());
    }
}

我们也可以通过XML来配置。关于节点意思可以查看文档http://www.ehcache.org/documentation/3.8/xml.html。

<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.xsd">

    <cache alias="cache-1">
        <key-type>java.lang.String</key-type>
        <value-type>java.lang.String</value-type>
        <resources>
            <heap unit="entries">20</heap>
            <offheap unit="MB">10</offheap>
        </resources>
    </cache>
</config>

只是构建CacheManager方式不同,其他API都一样。

public class XmlMain {
    public static void main(String[] args) {
        URL resource = XmlMain.class.getResource("/ehcache.xml");
        System.out.println(resource);
        Configuration xmlConfig = new XmlConfiguration(resource);
        CacheManager myCacheManager = CacheManagerBuilder.newCacheManager(xmlConfig);

        myCacheManager.init();
        Cache<String, String> cache2 =
                myCacheManager.getCache("cache-1", String.class, String.class);
        System.out.println(cache2);
        cache2.put("1","1");
    }
}

Spring Boot整合Ehcache

​首先要明确我们要做的事:实现计算某个数平方根的接口,如果此数小于10,则不进行缓存,否则将其缓存,并在5秒后过期。

引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>2.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
    <version>1.1.1</version>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.8.1</version>
</dependency>

1.控制器

@RestController
public class TestController {
    private Logger log = LoggerFactory.getLogger(TestController.class);
    @Autowired
    private NumberService numberService;

    @GetMapping(path = "/square/{number}")
    public String getSquare(@PathVariable Long number) {
        log.info("计算{}的平方", number);
        return String.format("{\"square\": %s}", numberService.square(number));
    }
}

2.Service
我们用@Cacheable注释该方法,让Spring处理缓存。Spring会创建NumberService的代理,拦截对square方法的调用并调用Ehcache。我们还需要提供要使用的缓存的名称以及key。condition是条件,此处条件意思是缓存number大于10的数。

@Service
public class NumberService {
    private Logger log = LoggerFactory.getLogger(NumberService.class);
    @Cacheable(
            value = "squareCache",
            key = "#number",
            condition = "#number>10")
    public BigDecimal square(Long number) {
        BigDecimal square = BigDecimal.valueOf(number)
                .multiply(BigDecimal.valueOf(number));
        log.info("{}的平方是{}", number, square);
        return square;
    }
}

3.开启缓存
我们需要开启@EnableCaching。

@Configuration
@EnableCaching
public class EhcacheConfig {
}

也可以写到启动类上。
在这里插入图片描述
4.XML配置
我们还需要通过xml方式配置缓存。
在resources下创建ehcache.xml。

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.ehcache.org/v3"
        xmlns:jsr107="http://www.ehcache.org/v3/jsr107"
        xsi:schemaLocation="
            http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
            http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">

    <cache alias="squareCache">
        <key-type>java.lang.Long</key-type>
        <value-type>java.math.BigDecimal</value-type>
        <expiry>
            <ttl unit="seconds">5</ttl>
        </expiry>

        <listeners>
            <listener>
                <class>com.hxl.springbootdemo.list.CacheEventLogger</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>UNORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>EXPIRED</events-to-fire-on>
            </listener>
        </listeners>

        <resources>
            <heap unit="entries">2</heap>
            <offheap unit="MB">10</offheap>
        </resources>
    </cache>

</config>

并在applicaion.properties下加入以下配置

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

5.监听器
另外还有一个监听器。

public class CacheEventLogger implements CacheEventListener<Object, Object> {

    private Logger log = LoggerFactory.getLogger(CacheEventLogger.class);
    @Override
    public void onEvent(CacheEvent<? extends Object, ? extends Object> cacheEvent) {

        log.info("旧值={},key={},新值={},type={}",cacheEvent.getOldValue(),cacheEvent.getKey(),cacheEvent.getNewValue(),cacheEvent.getType().name());
    }
}

运行之后在浏览器测试,当我们输入大于10的数字后,会将其缓存下来,过5秒后会过期,如果同样的数字在5秒内继续访问,则不会再次计算。
在这里插入图片描述
当输入小于10时,都不会缓存。
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值