【Java EE 学习 78 上】【数据采集系统第十天】【Service使用Spring缓存模块】

1、需求分析

  调查问卷中或许每个单击动做都会引起大量的数据库访问,特别是在参与调查的过程当中,只是单击“上一页”或者“下一页”的按钮就会引起大量的查询,必须对这种问题进行优化才行。使用缓存策略进行查询缓存是下降数据库压力很是理想的方法,这里最起码可以有两种缓存方式:java

  1.使用hibernate的二级缓存。spring

  2.使用spring自带的缓存模块进行查询缓存。使用spring自带的缓存模块功能必需要知足一下条件:数据库

    (1)spring版本必须至少在3.1或以上,这里使用了spring3.1express

    (2)必需要使用第三方缓存厂商的缓存支持,这里使用ehcacheapache

  这里使用spring自带的缓存模块进行查询缓存。缓存

2、集成spring的缓存模块实现对Service缓存代理,下降数据库压力

  1.引入类库

    [spring功能模块]app

    spring-modules-cache.jar  eclipse

    [第三方缓存供应商] ide

    backport-util-concurrent.jar
    com.springsource.org.apache.commons.logging-1.1.1.jar
    ehcache-1.5.0.jar
    jsr107cache-1.1.jar测试

  2.配置ehcache.xml配置文件,指定缓存的过时策略

 1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
 2     <diskStore path="java.io.tmpdir"/>
 3     <defaultCache  4             maxElementsInMemory="10000"
 5  eternal="false"
 6  timeToIdleSeconds="120"
 7  timeToLiveSeconds="120"
 8  overflowToDisk="true"
 9  maxElementsOnDisk="10000000"
10  diskPersistent="false"
11  diskExpiryThreadIntervalSeconds="120"
12  memoryStoreEvictionPolicy="LRU"
13             />
14     <!-- 自定义一个缓存策略 -->
15     <cache name="surveyCache"
16  maxElementsInMemory="10000"
17  eternal="false"
18  timeToIdleSeconds="120"
19  timeToLiveSeconds="120"
20  overflowToDisk="true"
21  maxElementsOnDisk="10000000"
22  diskPersistent="false"
23  diskExpiryThreadIntervalSeconds="120"
24  memoryStoreEvictionPolicy="LRU"
25             />
26 </ehcache>

    上面配置中的属性意思都比较简单,很容易理解,不赘述。

  3.经过配置文件配置spring的缓存模块

    首先,必须必须引入缓存的命名空间才行,因为eclipse中并无自带该命名空间相关信息,因此须要外部引入xsd约束,引入方式:

    Window->preferences->XML->XML catalog->Add找到spring-cache-3.1.xsd文件添加进来便可,因为对应的location已经失效,因此建议使用本地文件协议file:///替代http协议。

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/aop file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/beans file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/beans/spring-beans-2.5.xsd  http://www.springframework.org/schema/cache file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema\cache/spring-cache-3.1.xsd http://www.springframework.org/schema/tx file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/context file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/context/spring-context-2.5.xsd">

  (1)ehcache工厂配置

1 <!-- ehcacheManager工厂配置 -->
2 <bean id="ehcacheManager"
3  class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
4     <property name="configLocation" value="classpath:ehcache.xml"></property>
5 </bean>

  (2)ehcache管理器配置

1 <!-- ehcache管理器 -->
2 <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
3     <property name="cacheManager" ref="ehcacheManager"></property>
4 </bean>

  (3)配置key生成器,这里须要自定义一个key生成器类,先存档,以后详解

<!-- Key生成器 ,先存档 -->
    <bean id="surveyKeyGenerator" class="com.kdyzm.cache.SurveykeyGenerator" />

  (4)定义缓存通知,该配置的做用就是肯定针对什么样的方法进行缓存,针对什么样的方法清空缓存。

 1 <!-- 定义缓存通知 -->
 2 <cache:advice id="cacheAdvice" cache-manager="cacheManager"
 3  key-generator="surveyKeyGenerator"><!-- 这里须要配置key生成器 -->
 4     <cache:caching cache="surveyCache">
 5         <!-- 设置缓存的方法 -->
 6         <cache:cacheable method="get*" />
 7         <cache:cacheable method="load" />
 8         <cache:cacheable method="find*" />
 9         <cache:cacheable method="is*" />
10 
11         <!-- 设置须要清空缓存的方法 -->
12         <cache:cache-evict method="save*" all-entries="true" />
13         <cache:cache-evict method="update*" all-entries="true" />
14         <cache:cache-evict method="delete*" all-entries="true" />
15         <cache:cache-evict method="batch*" all-entries="true" />
16         <cache:cache-evict method="create*" all-entries="true" />
17         <cache:cache-evict method="new*" all-entries="true" />
18     </cache:caching>
19 </cache:advice>

  (5)配置缓存AOP,建立切入点表达式,肯定缓存对象的范围

    为了将缓存通知首先启动,将其order属性配置为0(并非由于0才首先启动,只是相对于日志通知和事务通知来讲其order属性值最小)。

 1 <aop:config>
 2     <!-- 日志切入点 -->
 3     <aop:pointcut  4         expression="(execution(* *..*Service.save*(..))  5  or execution(* *..*Service.update*(..))  6  or execution(* *..*Service.delete*(..))  7  or execution(* *..*Service.batch*(..))  8  or execution(* *..*Service.create*(..))  9  or execution(* *..*Service.new*(..))) and !bean(logService)"
10  id="loggerPointcut" />
11     <aop:pointcut expression="execution(* *..*Service.*(..))"
12  id="txPointcut" />
13     <!-- 必须配置order属性,使用该属性能够改变配置的通知的加载顺序,order值越大,优先级越高 必须让事务的通知放到后面,让日志的通知先执行,这样才能在执行完成日志的通知后事务确保可以结束。 14  order值越小,优先级越高 为了解决事务没有结束的问题,必须同时修改解除绑定的时间 -->
15 <aop:advisor advice-ref="cacheAdvice" 16  pointcut="execution(* com.kdyzm.service.SurveyService.*(..)) or 17  execution(* com.kdyzm.service.PageService.*(..)) or 18  execution(* com.kdyzm.service.QuestionService.*(..)) or 19  execution(* com.kdyzm.service.AnswerService.*(..))" order="0" />
20     <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"
21  order="2" />
22     <aop:aspect id="loggerAspect" ref="logger" order="1">
23         <aop:around method="record" pointcut-ref="loggerPointcut" />
24     </aop:aspect>
25 </aop:config>

  这里对调查相关的全部Service中的相关方法都进行了代理缓存。

  4.如何自定义key生成器

    配置文件中有一个key生成器的配置,该配置的做用就是根据当前执行的方法环境(方法名、参数列表、类名)计算出来惟一的标识符(key值),若是该标识符已经存在,则缓存管理器就会调用缓存中的数据不然就执行目标方法并将目标方法的查询结果缓存起来。

 1 package com.kdyzm.cache;  2 
 3 import java.lang.reflect.Method;  4 
 5 import org.springframework.cache.interceptor.KeyGenerator;  6 
 7 /**
 8  * 自定义key生成器  9  * @author kdyzm 10  * 11  */
12 public class SurveykeyGenerator implements KeyGenerator{ 13 
14     //什么对象调用的什么方法,参数列表是什么
15  @Override 16     public Object generate(Object arg0, Method arg1, Object... arg2) { 17         String targetCode=arg0.getClass().getSimpleName()+"["+arg0.hashCode()+"]";    //arg0是类 18         String methodName=arg1.getName();                            //arg1是方法 19         if(arg2!=null){                                       //arg2是参数列表 20             StringBuffer stringBuffer=new StringBuffer(); 21             stringBuffer.append("("); 22             for(int i=0;i<arg2.length;i++){ 23  stringBuffer.append(arg2[i].toString()); 24                 stringBuffer.append(","); 25  } 26             stringBuffer.append(")"); 27             targetCode= targetCode+"."+methodName+stringBuffer.toString(); 28  System.out.println(targetCode); 29             return targetCode; 30  } 31         targetCode= targetCode+"."+methodName+"()"; 32  System.out.println(targetCode); 33         return targetCode; 34  } 35 }

3、测试效果

  1.在主页上单击参与调查,查看后台

  

  清空控制台,从新单击一次“参与调查”超连接,再次查看后台,这时候就会发现没有SQL语句发出了(手要快,不要超过120秒,以前配置的ehcach.xml配置文件中声明了若是超过120s没用的话就会清空缓存,因此仍是会发出SQL查询语句)

  2.测试参与调查的过程当中的缓存效果。

    这里须要建立多个调查页,在翻页的过程当中查看缓存的效果,这里个人调查1中一共有三页。

    (1)单击调查1,依次单击下一页,直到最后一页,观察控制台打印,发现不断地有SQL查询发出

  

  

    (2)单击上一页、直到第一页,仍是发现不断的有查询发出。

    (3)从第一页单击“下一页”直到最后一页,发现再也不有查询发出,单击上一页仍是没有发现有SQL语句发出,证实spring缓存配置成功。

  

相关文章
相关标签/搜索