小白的springboot之旅(七) - springboot之缓存

11 篇文章 2 订阅

关键词:springboot,jpa,hibernate,ehcache

我们通常使用缓存来提高系统的性能。这篇我们讲解springboot集成ehcache,用于hibernate的二级缓存。

一、Ehcache简介

ehcache是一个纯java的缓存框架,既可以当做一个通用缓存使用,也可以作为将其作为hibernate的二级缓存使用。具有快速、精干等特点,是Hibernate中默认的CacheProvider。

缓存数据可选择如下三种存储方案:

MemoryStore –On-heap memory used to hold cache elements. This tier is subject to Javagarbage collection.

OffHeapStore –Provides overflow capacity to the MemoryStore. Limited in size only byavailable RAM. Not subject to Java garbage collection (GC). Available only withTerracotta BigMemory products.

DiskStore –Backs up in-memory cache elements and provides overflow capacity to the othertiers.

二、springboot集成ehcache

1)添加maven依赖

2)配置hibernate二级缓存

3)配置ehcache.xml

ehcache2.x配置文件样板参考官方网站提供的ehcache.xml

配置说明:

4)事件监听

ehcache有两大类事件,一是cacheManager相关的事件,如cache的init/added等;二是cahche相关的事件,如cache put/expire等。在ehcache中,默认没有这两类事件的监听器,需要自主实现监听器以及监听器工厂类,然后配置到ehcache.xml中。

EhcacheCacheManagerEventListener

package com.xiaoi.document.split.platform.cache;

import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.event.CacheEventListener;

/**
 * 自定义cache相关事件监听
 *
 * @Author Yuan Jingshan
 * @Date 2018-05-09
 */
@Slf4j
public class EhcacheCacheEventListener implements CacheEventListener {

    @Override
    public void notifyElementRemoved(Ehcache ehcache, Element element) throws CacheException {
        log.info("cache removed. key = {}, value = {}", element.getObjectKey(), element.getObjectValue());
    }

    @Override
    public void notifyElementPut(Ehcache ehcache, Element element) throws CacheException {
        log.info("cache put. key = {}, value = {}", element.getObjectKey(), element.getObjectValue());
    }

    @Override
    public void notifyElementUpdated(Ehcache ehcache, Element element) throws CacheException {
        log.info("cache updated. key = {}, value = {}", element.getObjectKey(), element.getObjectValue());
    }

    @Override
    public void notifyElementExpired(Ehcache ehcache, Element element) {
        log.info("cache expired. key = {}, value = {}", element.getObjectKey(), element.getObjectValue());
    }

    @Override
    public void notifyElementEvicted(Ehcache ehcache, Element element) {
        log.info("cache evicted. key = {}, value = {}", element.getObjectKey(), element.getObjectValue());
    }

    @Override
    public void notifyRemoveAll(Ehcache ehcache) {
        log.info("all elements removed. cache name = {}", ehcache.getName());
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    @Override
    public void dispose() {
        log.info("cache dispose.");
    }
}

EhcacheCacheEventListenerFactory

package com.xiaoi.document.split.platform.cache;

import net.sf.ehcache.event.CacheEventListener;
import net.sf.ehcache.event.CacheEventListenerFactory;

import java.util.Properties;

/**
 * 自定义cache相关事件监听工厂
 *
 * @Author Yuan Jingshan
 * @Date 2018-05-09
 */
public class EhcacheCacheEventListenerFactory extends CacheEventListenerFactory {

    @Override
    public CacheEventListener createCacheEventListener(Properties properties) {
        return new EhcacheCacheEventListener();
    }

}

EhcacheCacheManagerEventListener

package com.xiaoi.document.split.platform.cache;

import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Status;
import net.sf.ehcache.event.CacheManagerEventListener;

/**
 * 自定义cacheManager相关事件监听
 *
 * @Author Yuan Jingshan
 * @Date 2018-05-09
 */
@Slf4j
public class EhcacheCacheManagerEventListener implements CacheManagerEventListener {

    private final CacheManager cacheManager;

    public EhcacheCacheManagerEventListener(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    @Override
    public void init() throws CacheException {
        log.info("init ehcache.");
    }

    @Override
    public void dispose() throws CacheException {
        log.info("ehcache dispose.");
    }

    @Override
    public void notifyCacheAdded(String s) {
        log.info("cacheAdded. {}", s);
        log.info(cacheManager.getCache(s).toString());
    }

    @Override
    public void notifyCacheRemoved(String s) {

    }

    @Override
    public Status getStatus() {
        return null;
    }
}

EhcacheCacheManagerEventListenerFactory

package com.xiaoi.document.split.platform.cache;

import net.sf.ehcache.CacheManager;
import net.sf.ehcache.event.CacheManagerEventListener;
import net.sf.ehcache.event.CacheManagerEventListenerFactory;

import java.util.Properties;

/**
 * 自定义cacheManager相关事件监听工厂
 *
 * @Author Yuan Jingshan
 * @Date 2018-05-09
 */
public class EhcacheCacheManagerEventListenerFactory extends CacheManagerEventListenerFactory {

    @Override
    public CacheManagerEventListener createCacheManagerEventListener(CacheManager cacheManager, Properties properties) {
        return new EhcacheCacheManagerEventListener(cacheManager);
    }

}

5)使用二级缓存

要使用entitycache,需要在entity上配上相应的注解方可生效javax.persistence.Cacheable注解标记该entity使用二级缓存,org.hibernate.annotations.Cache注解指定缓存策略

package com.xiaoi.document.split.demo.entity;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import javax.persistence.*;

/**
 * 实体映射
 *
 * @Author Yuan Jingshan
 * @Date 2018-05-16
 */
@Entity
@Table(name = "qa_person")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "entityCache")
public class Person {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "age")
    private Integer age;

    @Column(name = "address")
    private String address;

    public Person() {
    }

    public Person(Long id, String name, Integer age, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

编写unitTest

package com.xiaoi.document.split.demo.service.impl;

import com.xiaoi.document.split.demo.service.PersonService;
import lombok.extern.slf4j.Slf4j;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class PersonServiceImplTest {

    @Autowired
    private PersonService personService;

    @Before
    public void setUp() throws Exception {

    }

    @After
    public void tearDown() throws Exception {

    }

    @Test
    public void getAll() throws Exception {
        log.info("第一次查询");
        personService.getAll();
        log.info("第二次查询");
        personService.getAll();
    }

}

最后,我们需要在springboot应用层面打开cache功能。  

package com.xiaoi.document.split;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DocumentSplitApplicationTests {

	@Test
	public void contextLoads() {
	}

}

 6)启动项目,运行unitTest

2018-05-19 12:13:06,866 - INFO - main com.xiaoi.document.split.demo.service.impl.PersonServiceImplTest- 第一次查询
Hibernate: select person0_.id as id1_0_0_, person0_.address as address2_0_0_, person0_.age as age3_0_0_, person0_.name as name4_0_0_ from qa_person person0_ where person0_.id=?
2018-05-19 12:13:06,947 - INFO - main com.xiaoi.document.split.platform.cache.EhcacheCacheEventListener- cache put. key = com.xiaoi.document.split.demo.entity.Person#1, value = Item{value=CacheEntry(com.xiaoi.document.split.demo.entity.Person), version=null, timestamp=6253376253722624}
2018-05-19 12:13:06,950 - INFO - main com.xiaoi.document.split.demo.service.impl.PersonServiceImplTest- 第二次查询
2018-05-19 12:13:06,956 - INFO - Thread-5 org.springframework.web.context.support.GenericWebApplicationContext- Closing org.springframework.web.context.support.GenericWebApplicationContext@52815fa3: startup date [Sat May 19 12:13:01 CST 2018]; root of context hierarchy
2018-05-19 12:13:06,960 - INFO - Thread-5 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean- Closing JPA EntityManagerFactory for persistence unit 'default'
2018-05-19 12:13:06,961 - INFO - Thread-5 com.xiaoi.document.split.platform.cache.EhcacheCacheEventListener- cache dispose.
2018-05-19 12:13:06,989 - INFO - Thread-5 com.xiaoi.document.split.platform.cache.EhcacheCacheManagerEventListener- ehcache dispose.
2018-05-19 12:13:06,998 - INFO - Thread-5 com.alibaba.druid.pool.DruidDataSource- {dataSource-1} closed

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Spring Boot中整合Ehcache缓存,需要进行以下几个步骤: 1. 添加Ehcache依赖 在pom.xml文件中添加Ehcache依赖: ``` <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>${ehcache.version}</version> </dependency> ``` 2. 配置Ehcache缓存 在application.yml(或application.properties)文件中配置Ehcache缓存: ``` spring: cache: type: ehcache ehcache: config: classpath:ehcache.xml ``` 其中,`spring.cache.type`属性指定使用的缓存类型为Ehcache,`ehcache.config`属性指定Ehcache配置文件的路径(在classpath下)。 3. 编写Ehcache配置文件 在classpath下创建`ehcache.xml`文件,配置Ehcache缓存的相关信息: ``` <ehcache> <diskStore path="java.io.tmpdir"/> <defaultCache maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30" maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" transactionalMode="off"> </defaultCache> <cache name="userCache" maxEntriesLocalHeap="1000" maxEntriesLocalDisk="10000" eternal="false" diskSpoolBufferSizeMB="20" timeToIdleSeconds="300" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LFU" transactionalMode="off"> </cache> </ehcache> ``` 其中,`defaultCache`为默认缓存配置,`cache`为自定义缓存配置。 4. 在代码中使用缓存 在需要使用缓存的方法上添加`@Cacheable`注解,指定缓存名称和缓存key: ``` @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override @Cacheable(value = "userCache", key = "#id") public User getUserById(Integer id) { return userDao.getUserById(id); } // ... } ``` 其中,`value`属性指定缓存名称,`key`属性为缓存key表达式,可以使用Spring表达式语言(SpEL)进行动态表达。 以上就是在Spring Boot中整合Ehcache缓存的步骤,通过使用Ehcache缓存可以有效地提高应用程序的性能和响应速度。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值