Ehcache缓存的使用

ehcache缓存框架

查询的操作最频繁,,某个线程很多的查询都是重复的,或者有些数据跨线程查询也是重复。 
问题:造成数据库压力变大。传统的数据库查询效率就不高(网络、sql语句复杂),导致查询体验不好。 
解决:使用缓存机制。

缓存用什么东西来弄? 
传统有专门缓存框架:ehcache,memcache 
NoSQL数据库:Redis、MongoDB

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)

        <ehcache.version>2.6.10ehcache.version>

        <dependency>
            <groupId>net.sf.ehcachegroupId>
            <artifactId>ehcache-coreartifactId>
            <version>${ehcache.version}version>
        dependency>

        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-context-supportartifactId>
            <version>${spring.version}version>
        dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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

        
        <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
            
            <property name="configLocation" value="classpath:ehcache.xml"/>
        bean>
        
        <bean id="shrioCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
            
            <property name="cacheManager" ref="ehcacheManager"/>
        bean>


    
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            
            <property name="realm" ref="bosRealm">property>
            
            <property name="cacheManager" ref="shiroCacheManager"/>
        bean>


    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

3.BosRealm中添加注解

        @Component("bosRealm")
        public class BosRealm extends AuthorizingRealm{
            //注入缓存名称
            @Value("BosShiroCache")//注入缓存具体对象的名字,该名字在ehcache.xml中配置的
            public void setSuperAuthenticationCacheName(String authenticationCacheName){
                super.setAuthenticationCacheName(authenticationCacheName);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.配置ehcache.xml

        
        <cache name=" BosShiroCache "
                maxElementsInMemory="10000"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                maxElementsOnDisk="10000000"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU">
            <persistence strategy="localTempSwap"/>
        cache>

        默认的策略:
        
        <diskStore path="java.io.tmpdir"/>
        
        <defaultCache
                maxElementsInMemory="10000"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                maxElementsOnDisk="10000000"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU">
            <persistence strategy="localTempSwap"/>
        defaultCache>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

动态菜单优化

减少无用数据查询(减少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
  • 1
  • 2
  • 3
  • 4
            
            <bean id="springCacheManagerSpring" class="org.springframework.cache.ehcache.EhCacheCacheManager">
                
                <property name="cacheManager" ref="ehCacheManager"/>
            bean>

            
            <cache:annotation-driven cache-manager="springCacheManagerSpring"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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) {
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

如添加权限,要清除缓存

        /**
         * 添加功能
         */
        @Override
        //清除ehcache的某区域的所有对象
        @CacheEvict(value="SpringCache",allEntries=true)
        public void save(Function function) {
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Hibernate中使用ehcache

1.导入 jar 包:ehcache-1.5.0.jar/ commons-logging.jar/ backport-util-concurrent.jar 
2.开启二级缓存(我要使用二级缓存) 
3.确定二级缓存提供商(我要使用哪个二级缓存) 
4.确定需要缓存内容 
1>配置需要缓存的类 
2>配置需要缓存的集合 
5.配置 ehcache 自定义配置文件

引入Maven坐标

    <dependency>
        <groupId>org.hibernategroupId>
        <artifactId>hibernate-ehcacheartifactId>
        <version>5.0.7.Finalversion>
    dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

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

开启二级缓存

    
    <property name="hibernate.cache.use_second_level_cache">trueproperty>
  • 1
  • 2

确定缓存提供商

"hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider
  • 1

确定缓存内容

    
      
    <class-cache usage="read-write" class="cn.aric.domain.User"/> 
    
    <collection-cache usage="read-write" collection="cn.aric.doain.Customer.orderSet"/>
  • 1
  • 2
  • 3
  • 4
  • 5

ehcache 配置文件

文件名:ehcache.xml 
参考官方文件配置

        <ehcache>
            <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"
                />

        ehcache>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

测试

        //测试二级缓存是否配置成功
        @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();
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

查询缓存

查询缓存默认不使用。需要手动开启 
查询缓存:将 HQL 语句与 查询结果进行绑定。通过 HQL 相同语句可以缓存内容。 
默认情况 Query 对象只将查询结果存放在一级和二级缓存,不从一级或二级缓存获取。 
查询缓存就是让 Query 可以从二级缓存获得内容。

        
        "hibernate.cache.use_query_cache">true


        @Test
        public void demo(){
            // 查询缓存
            Session s1 = factory.openSession();
            s1.beginTransaction();
            //1 query查询
            Query q1 = s1.createQuery("from Customer");
            //设置查询缓存为true
            q1.setCacheable(true);
            List 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 a2 = q2.list();
            for (Customer c2 : a2) {
                System.out.println(c2);
            }
            s2.getTransaction().commit();
            s2.close();
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

你可能感兴趣的:(Ehcache缓存的使用)