简单聊聊Ehcache缓存
阅读原文时间:2023年07月09日阅读:2

最近工作没有那么忙,有时间来写写东西。今年的系统分析师报名已经开始了,面对历年的真题,真的难以入笔,所以突然对未来充满了担忧,还是得抓紧时间学习技术。

同事推了一篇软文,看到了这个Ehcache,感觉简单又好用,所以在自己这边也做个记录。

先来谈谈什么是Ehcache缓存,我们从实际场景出发,支撑一个系统最直接的东西就是数据库,针对数据库我们最常用的操作就是查询。反复的查询数据库会导致数据库压力变大,传统的数据库查询效率就不高(网络、sql语句复杂),导致查询体验不好。尤其当我们查询的语句还是类似甚至重复的时候,这就是浪费资源了。那这个时候,缓存机制就变得很有必要了。像我们经常使用的实现缓存的方式大致有两种,一种是NoSQL数据库,比如Redis、MongoDB等,另一种便是今天要提的缓存框架:Ehcache、Memcache等。

引用官方的内容一句话定义:EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。

下面就开始使用了:

整合Ehcache-优化性能-降低查询数据库的频率

Spring集成Ehcache:

配置Ehcache缓存管理器(EhcacheManager),将其注入给Spring平台缓存管理器(cachemanager),Spring平台缓存管理器再注入给Spring缓存注解驱动。代码中使用注解进行缓存。

Shiro集成Ehcache:

配置Ehcache缓存管理器(EhcacheManager),将其注入给Shiro缓存管理器(这里是shiro整合ehcache的缓存管理器),最后将Shiro的缓存管理器注入给Shiro安全管理器

1.通过maven坐标导入jar(ehcache和spring的context-support)

2.6.10

<groupId>net.sf.ehcache</groupId>

<artifactId>ehcache-core</artifactId>

<version>${ehcache.version}</version>

<groupId>org.springframework</groupId>

<artifactId>spring-context-support</artifactId>

<version>${spring.version}</version>

2.配置ApplicationContext.xml (Shiro整合ehcache)

<bean id="ehcacheManager"

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">

<!-- 注入缓存配置文件的位置 -->

<property name="configLocation" value="classpath:ehcache.xml" />

<!-- 注入ehcache的缓存管理器 -->

<property name="cacheManager" ref="ehcacheManager" />

<!-- 注入 Realm连接安全数据 -->

<property name="realm" ref="bosRealm"></property>

<!-- 注入shiro的缓存管理器 -->

<property name="cacheManager" ref="shiroCacheManager" />

3.BosRealm中添加注解

@Component("bosRealm")

public class BosRealm extends AuthorizingRealm{

//注入缓存名称

@Value("BosShiroCache")//注入缓存具体对象的名字,该名字在ehcache.xml中配置的

public void setSuperAuthenticationCacheName(String authenticationCacheName){

    super.setAuthenticationCacheName(authenticationCacheName);

}

}

4.配置ehcache.xml

<cache name=" BosShiroCache " maxElementsInMemory="10000" eternal="false"

timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000"

diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">

<persistence strategy="localTempSwap" />

默认的策略:

<defaultCache maxElementsInMemory="10000" eternal="false"

timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000"

diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">

<persistence strategy="localTempSwap" />

动态菜单优化

减少无用数据查询(减少SQL的发出)

问题:每次菜单生成的语句太多。生成了很多与功能权限菜单无关的语句,如角色等

解决:在Function的实体类中,使用@JSON(serialize=fase)

对每个用户菜单进行缓存

问题:每次刷新整个页面都会重新生成菜单,都会重新查询一次数据库。

解决方案:使用缓存。具体:使用spring 整合ehcache的缓存

1.使用maven坐标引入jar

略(上面已经引过了)

2.配置ApplicationContext.xml

xmlns:cache="http://www.springframework.org/schema/cache"

http://www.springframework.org/schema/cache

http://www.springframework.org/schema/cache/spring-cache.xsd

<!-- 注入ehcache的管理器 - -->

<property name="cacheManager" ref="ehCacheManager" />

3.编写ehcache.xml,添加一个新的缓存区域,如MenuSpringCache

4.在方法上添加注解

提示:spring的缓存管理器默认的key是方法名+参数,如果参数是个对象,那么会发生每次缓存的key都不一样,虽然数据的一样的。因此这种情况下,需要手动指定key

/**

* 获取用户权限

*/

@Override

//value:缓存区域,缓存的东西往哪放

//缓存的的key的生成策略

//1.没有参数,key='0'

//2.有1个参数,那么key是对象本身,一般是对象地址

//3.有多个参数,那么key是多个对象的hash值

@Cacheable(value="SpringCache",key="#user.id")

public List findFunctionByUser(User user) {

如添加权限,要清除缓存

/**

* 添加功能

*/

@Override

//清除ehcache的某区域的所有对象

@CacheEvict(value="SpringCache",allEntries=true)

public void save(Function function) {

Hibernate中使用ehcache

1.导入 jar 包:ehcache-1.5.0.jar/ commons-logging.jar/ backport-util-concurrent.jar

2.开启二级缓存(我要使用二级缓存)

3.确定二级缓存提供商(我要使用哪个二级缓存)

4.确定需要缓存内容

1>配置需要缓存的类

2>配置需要缓存的集合

5.配置 ehcache 自定义配置文件

<groupId>org.hibernate</groupId>

<artifactId>hibernate-ehcache</artifactId>

<version>5.0.7.Final</version>

在 hibernate.cfg.xml 配置缓存,或者交由spring管理,在sessionFactory中配置

开启二级缓存

true

确定缓存提供商

org.hibernate.cache.EhCacheProvider

确定缓存内容

ehcache 配置文件

文件名:ehcache.xml

参考官方文件配置

<diskStore path="f:cache" />

<defaultCache maxElementsInMemory="10000"

    eternal="false"

    timeToIdleSeconds="120"

    timeToLiveSeconds="120"

    overflowToDisk="true" />

<cache name="hibernateCache"

    maxElementsInMemory="10000"

    eternal="false"

    timeToIdleSeconds="300"

    timeToLiveSeconds="600"

    overflowToDisk="true" />

测试

//测试二级缓存是否配置成功

@Test

public void test(){

Configuration configuration = new Configuration().configure();

SessionFactory sessionFactory = configuration.buildSessionFactory();

//获取session1

Session session1 = sessionFactory.openSession();

Transaction tx = session1.beginTransaction();

User user1 = session1.get(User.class, 10L);

System.out.println(user1.getUser\_code());

tx.commit();

session1.close();

//获取session2

Session session2 = sessionFactory.openSession();

Transaction tx2 = session2.beginTransaction();

User user2 = session2.get(User.class, 10L);

System.out.println(user2.getUser\_code());

tx2.commit();

session2.close();

}

查询缓存

查询缓存默认不使用。需要手动开启

查询缓存:将 HQL 语句与 查询结果进行绑定。通过 HQL 相同语句可以缓存内容。

默认情况 Query 对象只将查询结果存放在一级和二级缓存,不从一级或二级缓存获取。

查询缓存就是让 Query 可以从二级缓存获得内容。

true

@Test

public void demo(){

// 查询缓存

Session s1 = factory.openSession();

s1.beginTransaction();

//1 query查询

Query q1 = s1.createQuery("from Customer");

//设置查询缓存为true

q1.setCacheable(true);

List<Customer> a1 = q1.list();

for (Customer c1 : a1) {

    System.out.println(c1);

}

//2 cid =1 -- 一级缓存获得

Customer customer = (Customer) s1.get(Customer.class, 1);

System.out.println(customer);

s1.getTransaction().commit();

s1.close();

System.out.println("----------");

Session s2 = factory.openSession();

s2.beginTransaction();

//2 cid =1 -- 二级缓存获得

Customer customer2 = (Customer) s2.get(Customer.class, 1);

System.out.println(customer2);

//3 query查询

Query q2 = s2.createQuery("from Customer");

q2.setCacheable(true);

List<Customer> a2 = q2.list();

for (Customer c2 : a2) {

    System.out.println(c2);

}

s2.getTransaction().commit();

s2.close();

}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器