• 在Spring中使用cache(EhCache的对象缓存和页面缓存)


    Spring框架从version3.1开始支持cache,并在version4.1版本中对cache功能进行了增强。

    spring cache 的关键原理就是 spring AOP,通过 spring AOP,其实现了在方法调用前、调用后获取方法的入参和返回值,进而实现了缓存的逻辑。关于Spring Cache原理的详细介绍,参见http://blog.csdn.net/guugle2010/article/details/40115675 

    1、采用Spring的默认开箱即用的cache(Out of the box)

    采用Spring开箱即用的Cache,必须加载spring-context.jar包。

    不支持高可用性,也不具备持久化数据能力(只能read)并发不好。

    1.1 在方法上使用注解

    @Cacheable主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
    value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 例如:
    @Cacheable(value=”mycache”) 或者 
    @Cacheable(value={”cache1”,”cache2”}
    key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 例如:
    @Cacheable(value=”testcache”,key=”#userName”)
    condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 例如:
    @Cacheable(value=”testcache”,condition=”#userName.length()>2”)
    @CachePut主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
    value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 例如:
    @CachePut(value=”mycache”) 或者 
    @CachePut(value={”cache1”,”cache2”}
    key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 例如:
    @CachePut(value=”testcache”,key=”#userName”)
    condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 例如:
    @CachePut(value=”testcache”,condition=”#userName.length()>2”)
    @CachEvict主要针对方法配置,能够根据一定的条件对缓存进行清空
    value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 例如:
    @CachEvict(value=”mycache”) 或者 
    @CachEvict(value={”cache1”,”cache2”}
    key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 例如:
    @CachEvict(value=”testcache”,key=”#userName”)
    condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才清空缓存 例如:
    @CachEvict(value=”testcache”,
    condition=”#userName.length()>2”)
    allEntries 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 例如:
    @CachEvict(value=”testcache”,allEntries=true)
    beforeInvocation 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存 例如:
    @CachEvict(value=”testcache”,beforeInvocation=true)

    @Caching

    @CacheConfig

    默认的key生成器策略KeyGenerator

    If no params are given, return SimpleKey.EMPTY.
    If only one param is given, return that instance.
    If more the one param is given, return a SimpleKey containing all parameters.

    1.2 基于XML的配置

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:cache="http://www.springframework.org/schema/cache"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context.xsd
               http://www.springframework.org/schema/cache
               http://www.springframework.org/schema/cache/spring-cache.xsd">
        <context:component-scan base-package="com.traveller.domain.cache"/>
        <context:annotation-config/>
        <cache:annotation-driven/>
        <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
            <property name="caches">
                <set>
                    <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">
                        <property name="name" value="default"/>
                    </bean>
                    <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">
                        <property name="name" value="ascenceCache"/>
                    </bean>
                </set>
            </property>
        </bean>
    </beans>

    1.3 基于配置类的配置

    @Configuration
    @EnableCaching
    public class CacheConfig implements CachingConfigurer {
        @Bean
        @Override
        public CacheManager cacheManager() {
            SimpleCacheManager cacheManager = new SimpleCacheManager();
    
            cacheManager.setCaches(Arrays.asList(
                    new ConcurrentMapCache("scenceCache"),
                    new ConcurrentMapCache("userCache")));
    
            return cacheManager;
        }
       ...... }

    参考:

    http://www.cnblogs.com/rollenholt/p/4202631.html

    https://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html


    2、EHCache 集成

    Ehcache从 Hibernate发展而来,逐渐涵盖了Cahce界的全部功能,是目前发展势头最好的一个项目。

    Ehcache可以对页面、对象、数据进行缓存,同时支持集群/分布式缓存,具有快速,简单,低消耗,依赖性小,扩展性强的特点;支持对象或序列化缓存,支持缓存或元素的失效,提供LRU、LFU和FIFO淘汰算法,支持内存缓存和磁盘缓存等特点。

    Spirng集成ehCache,需要spring-context-support.jar包的支持。

    FIFO,first in first out,这个是大家最熟的,先进先出。
    LFU, Less Frequently Used,直白一点就是讲一直以来最少被使用的。缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
    LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。

    2.1 基于xml的配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache"
      xmlns:p="http://www.springframework.org/schema/p"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
          http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd">
    
      <cache:annotation-driven cache-manager="cacheManager" />
      
      <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
          p:cacheManager-ref="cacheManagerFactory" />
          
      <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
          p:configLocation="classpath:ehcache.xml" p:shared="false" />
    </beans>

     2.2 基于配置类的配置

    @Configuration
    @EnableCaching
    public class CacheConfig implements CachingConfigurer {
        @Bean
        public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {
            EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
            ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
            return ehCacheManagerFactoryBean;
        }
    
        @Bean
        public CacheManager cacheManager() {
            EhCacheCacheManager cacheManager = new EhCacheCacheManager();
            cacheManager.setCacheManager(ehCacheManagerFactoryBean().getObject());
            return cacheManager;
        }
    }

     2.3 ehcache.xml的配置

    To learn how to configure Ehcache, read this official ehcache.xml example.

    <?xml version="1.0" encoding="UTF-8"?>  
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"  
        monitoring="autodetect">  
        <!-- <diskStore path="java.io.tmpdir" /> -->  
        <diskStore path="E:/cachetmpdir"/>  
        <defaultCache maxElementsInMemory="10000" eternal="false"  
            timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"  
            maxElementsOnDisk="10000000" diskPersistent="false"  
            diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" />  
              
        <cache name="scenceCache" maxElementsInMemory="10000"  
            maxElementsOnDisk="1000" eternal="false" overflowToDisk="true"  
            diskSpoolBufferSizeMB="20" timeToIdleSeconds="300" timeToLiveSeconds="600"  
            memoryStoreEvictionPolicy="LFU" />  
    </ehcache> 

    maxElementsInMemory: 缓存最大数目
    eternal: 缓存是否持久
    timeToIdleSeconds: 当缓存闲置n秒后销毁
    timeToLiveSeconds: 当缓存存活n秒后销毁
    overflowToDisk: 是否保存到磁盘,当系统宕机时

    2.4 测试

    In non-web application, you need to shut down the Spring context manually, so that Ehcache got chance to shut down as well, otherwise Ehcache manager will hang there.

    public class CacheTest {   
        private static final Logger log = LoggerFactory.getLogger(CacheTest.class);
        public static void main(String[] args) {
            ApplicationContext context = new AnnotationConfigApplicationContext(
                    AppConfig.class,CacheConfig.class);
            ScenceRepository obj = context.getBean(ScenceRepository.class);
            Scence user = obj.findOne(1);
         System.out.println(user2.getName());
            Scence user2 = obj.findOne(1);
            System.out.println(user2.getName());
            
            //shut down the Spring context.
            ((ConfigurableApplicationContext)context).close();
        }
    }

    2.5 问题

    启动报错:ERROR DiskStorageFactory:495 - Disk Write of 1 failed: java.io.NotSerializableException: com.huawei.traveller.domain.Scence ,Scence没有实现序列化,加上Serializable接口即可

    参考

    http://www.mkyong.com/spring/spring-caching-and-ehcache-example/

    http://wangchaoqun.com/blog/2014/04/spring-cache-zhi-ehcache-he-memcached.html/


    3、EhCache页面缓存

    页面缓存,简单来说,就是把经常访问的页面(例如首页index.jsp)缓存起来,下次在访问的时候,直接从缓存读取(还要不要读取数据库?)

    需要加载jar包:ehcache-web.jar、ehcache-core.jar

    Spring EhCache页面缓存的做法,定义一个过滤器,这个过滤器规定了哪些文件需要被缓存;在规定的超时时间内,多次访问这个文件会从缓存中读取,而不是从数据库重新加载。

    3.1 修改ehcache,增加一个名为SimplePageCachingFilter的cache项目

    <?xml version="1.0" encoding="UTF-8"?>  
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"  
        monitoring="autodetect">   
        <diskStore path="E:/cachetmpdir"/>  
        <defaultCache maxElementsInMemory="10000" 
            eternal="false"  
            timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"  
            maxElementsOnDisk="10000000" diskPersistent="false"  
            diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" />  
        <cache name="scenceCache" maxElementsInMemory="10000"  
            maxElementsOnDisk="1000" eternal="false" overflowToDisk="true"  
            diskSpoolBufferSizeMB="20" timeToIdleSeconds="300" timeToLiveSeconds="600"  
            memoryStoreEvictionPolicy="LFU" />  
        <cache name="SimplePageCachingFilter" maxElementsInMemory="10000"  
            maxElementsOnDisk="1000" eternal="false" overflowToDisk="true"  
            diskSpoolBufferSizeMB="20" timeToIdleSeconds="300" timeToLiveSeconds="600"  
            memoryStoreEvictionPolicy="LFU" /> 
    </ehcache>  

     3.2 给应用配置一个过滤器

    使用配置类的方法

    FilterRegistration.Dynamic cacheFilterilterRegistration = servletContext.addFilter(
    "webPageCacheFilter", net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter.class);
    cacheFilterilterRegistration.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/index.*");

     3.3 测试

     如果连续刷新发现时间显示不变,说明页面缓存有效

    <%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html >
    <body>
    <%=new java.util.Date()%>
    </body>
    </html>

     3.4 问题

    (1)本来页面缓存cache起名为WebPageCachingFilter,但是启动的时候报错:cache 'SimplePageCachingFilter' not found in configuration:看来一下源码,发现启动如果不起名的话,默认名为SimplePageCachingFilter,但是我又无法再类加载的时候起名,所以只能暂时用SimplePageCachingFilter

    (2)页面缓存不生效问题:??

    参考

    http://www.iteye.com/topic/128458/
    http://blog.csdn.net/zljjava/article/details/38422407

     

  • 相关阅读:
    Python 基础之函数初识与函数参数
    python 基础之浅拷贝与深拷贝
    Python 基础之集合相关操作与函数和字典相关函数
    Python 基础之字符串操作,函数及格式化format
    Rocket
    Rocket
    Rocket
    Rocket
    Rocket
    Rocket
  • 原文地址:https://www.cnblogs.com/mingziday/p/4854047.html
Copyright © 2020-2023  润新知