1.技术背景:
系统缓存是位于应用程序与物理数据源之间,用于临时存放复制数据的内存区域,目的是为减少应用程序对物理数据源访问的次数,从而提高应用程序的运行性能。缓存设想内存是有限的,缓存的时效性也是有限的,所以可以设定内存数量的大小可以执行失效算法,可以在内存满了的情况下,按照最少访问等算法将缓存直接移除或切换到硬盘上。
Ehcache从Hibernate发展而来,逐渐涵盖了Cache界的全部功能,是目前发展势头最好的一个项目,具有快速、简单、低消耗、扩展性强、支持对象或序列化缓存,支持缓存或元素的失效,提供LRU、LFU和FIFO缓存策略,支持内存缓存和硬盘缓存和分布式缓存机制等特点。其中Cache的存储方式为内存或磁盘(ps:无须担心容量问题)
2.EhCahe的类层次介绍:
主要分为三层,最上层是CacheManager,它是操作Ehcache的入口。可以通过CacheManager.getInstance()获得一个单子的CacheManager,或者通过CacheManager的构造函数创建一个新的CacheManager。每个CacheManger都管理多个Cache。每个Cache都以一种类Hash的方式,关联多个Element。Element就是我们用于存放缓存内容的地方。
3.环境搭建:
很简单只需要将ehcache-2.1.0-distribution.tar.gz和ehcache-web-2.0.2-distribution.tar.gz挤压的jar包放入WEB-INF/lib下。
再创建一个重要的配置文件ehcache.xml,可以从ehcache组件包中拷贝一个,也可以自己建立一个,需要放到classpath下,一般放于/WEB-INF/classed/ehcache.xml;具体的配置文件可以网上搜一下
4.实际运用
一个网站的首页估计是被访问次数最多的,我们可以考虑给首页做一个页面缓存;
缓存策略:应该是某个固定时间之内不变的,比如说2分钟更新一次,以应用结构page-filter-action-service-dao-db为例。
位置:页面缓存做到尽量靠近客户的地方,就是在page和filter之间,这样的优点就是第一个用户请求后,页面被缓存,第二个用户在请求,走到filter这个请求就结束了,需要在走到action-service-dao-db,好处当然是服务器压力大大降低和客户端页面响应速度加快。
首页页面缓存存活时间定为2分钟,也就是参数timeToLiveSeconds(缓存的存活时间)应该设置为120,同时timeToIdleSeconds(多长时间不访问缓存,就清楚该缓存)最好也设为2分钟或者小于2分钟。
接着我们来看一下SimplePageCachingFilter 的配置,
1
2
3
4
5
6
7
8
9
10
|
< filter >
< filter-name >indexCacheFilterfilter-name>
< filter-class >
net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter < filter-class >
< filter >
< filter-mapping >
< filter-name >indexCacheFilterfilter-name>
< url-pattern >*index.actionurl-pattern>
< filter-mapping >
|
将上述代码加入到web.xml,那么当打开首页时,你会发现2分钟才会有一堆sql语句出现在控制台,也可以调整为5分钟,总之一切尽在掌控之中。
当然,如果你像缓存首页的部分内容时,你需要使用SimplePageFragmentCachingFilter这个filter,我看一下:
1
2
3
4
5
6
7
8
9
10
|
< filter >
< filter-name >indexCacheFilterfilter-name>
< filter-class >
net.sf.ehcache.constructs.web.filter.SimplePageFragmentCachingFilter < filter-class >
filter> < filter-mapping >
< filter-name >indexCacheFilterfilter-name>
< url-pattern >*/index_right.jsp< url-pattern >
< filter-mapping >
|
如此我们将jsp页面通过jsp:include到其他页面,这样就做到了页面局部缓存的效果,这一点貌似没有oscache的tag好用。
此外cachefilter中还有一个特性,就是gzip,也就是缓存中的元素是被压缩过的,如果客户端浏览器支持压缩的话,filter会直接返回压缩过的流,这样节省了带宽,把解压的工作交给了客户端浏览即可,当然如果客户端不支持gzip,那么filter会把缓存的元素拿出来解压后在返回给客户端浏览器(大多数爬虫是不支持gzip的,所以filter也会解压后在返回流)。
总之,Ehcache是一个非常轻量级的缓存实现,而且从1.2之后支持了集群,而且是hibernate默认的缓存provider,本文主要介绍Ehcahe对页面缓存的支持,但是它的功能远不止如此,要用好缓存,对J2ee中缓存的原理、适用范围、适用场景等等都需要比较深刻的理解,这样才能用好用对缓存。
为了大家通过实际例子加深了解与场景运用,在奉献一个实例:
*在Spring中运用EhCache
适用任意一个现有开源Cache Framework,要求可以Cache系统中service或者DAO层的get/find等方法返回结果,如果数据更新(适用了Create/update/delete),则刷新cache中相应的内容。
根据需求,计划适用Spring AOP+enCache来实现这个功能,采用ehCache原因之一就是Spring提供了enCache的支持,至于为何仅仅支持ehcache而不支持oscache和jbosscache就无从得知了。
AOP少不了拦截器,先创建一个实现了MethodInterceptor接口的拦截器,用来拦截Service/DAO的方法调用,拦截到方法后,搜索该方法的结果在cache中是否存在,如果存在,返回cache中结果,如果不存在返回数据库查询结果,并将结果返回到缓存。
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
42
43
44
45
46
47
48
49
50
51
52
|
public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean
{ private static final Log logger = LogFactory.getLog(MethodCacheInterceptor. class );
private Cache cache;
public void setCache(Cache cache) {
this .cache = cache;
} public MethodCacheInterceptor() {
super ();
} /** * 拦截Service/DAO 的方法,并查找该结果是否存在,如果存在就返回cache 中的值, * 否则,返回数据库查询结果,并将查询结果放入cache */ public Object invoke(MethodInvocation invocation) throws Throwable {
String targetName = invocation.getThis().getClass().getName(); String methodName = invocation.getMethod().getName(); Object[] arguments = invocation.getArguments(); Object result; logger.debug( "Find object from cache is " + cache.getName());
String cacheKey = getCacheKey(targetName, methodName, arguments); Element element = cache.get(cacheKey); Page 13 of 26
if (element == null ) {
logger.debug( "Hold up method , Get method result and create cache........!" );
result = invocation.proceed(); element = new Element(cacheKey, (Serializable) result);
cache.put(element); } return element.getValue();
} /** * 获得cache key 的方法,cache key 是Cache 中一个Element 的唯一标识 * cache key 包括包名+类名+方法名,如com.co.cache.service.UserServiceImpl.getAllUser */ private String getCacheKey(String targetName, String methodName, Object[] arguments) {
StringBuffer sb = new StringBuffer();
sb.append(targetName).append( "." ).append(methodName);
if ((arguments != null ) && (arguments.length != 0 )) {
for ( int i = 0 ; i < arguments.length; i++) {
sb.append( "." ).append(arguments[i]);
} } return sb.toString();
} /** * implement InitializingBean,检查cache 是否为空 */ public void afterPropertiesSet() throws Exception {
Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it." );
} } |
上面的代码可以看到,在方法invoke中,完成了搜索cache/新建cache的功能
随后,再建立一个拦截器MethodCacheAfterAdvice,作用是在用户进行create/update/delete操作时来刷新、remove相关cache内容,这个拦截器需要实现AfterRetruningAdvice接口,将会在所拦截的方法执行后执行在afterReturning(object arg0,Method arg1,Object[] arg2,object arg3)方法中所预定的操作
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
|
public class MethodCacheAfterAdvice implements AfterReturningAdvice, InitializingBean
{ private static final Log logger = LogFactory.getLog(MethodCacheAfterAdvice. class );
private Cache cache;
Page 15 of 26
public void setCache(Cache cache) {
this .cache = cache;
} public MethodCacheAfterAdvice() {
super ();
} public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws
Throwable { String className = arg3.getClass().getName(); List list = cache.getKeys(); for ( int i = 0 ;i<list.size();i++){
String cacheKey = String.valueOf(list.get(i)); if (cacheKey.startsWith(className)){
cache.remove(cacheKey); logger.debug( "remove cache " + cacheKey);
} } } public void afterPropertiesSet() throws Exception {
Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it." );
} } |
该方法获取目标class的全名,如:com.co.cache.test.TestServiceImpl,然后循环cache的key list,刷新/remove cache中所有和该class相关的element。
接着就是配置encache的属性,如最大缓存数量、cache刷新的时间等等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
< ehcache >
< diskStore path = "c:\\myapp\\cache" />
< defaultCache
maxElementsInMemory = "1000"
eternal = "false"
timeToIdleSeconds = "120"
timeToLiveSeconds = "120"
overflowToDisk = "true"
/> < cache name = "DEFAULT_CACHE"
maxElementsInMemory = "10000"
eternal = "false"
timeToIdleSeconds = "300000"
timeToLiveSeconds = "600000"
overflowToDisk = "true"
/> </ ehcache >
|
这里需要注意的是defaultCache定义了一个默认的cache,这个Cache不能删除,否则会抛出No default cache is configured异常。另外由于使用拦截器来刷新Cache内容,因此在定义cache生命周期时可以定义较大的数值,timeToIdleSeconds="30000000",timeToLiveSeconds="6000000",好像还不够大?
然后再将Cache和两个拦截器配置到Spring的配置文件cache.xml中即可,需要创建两个“切入点”,分别用于拦截不同方法名的方法。在配置application.xml并且导入cache.xml。这样一个简单的Spring+Encache框架就搭建完成。
由于时间关系就介绍到这里,以后有机会还会介绍Ehcache在分布式集群系统中的使用,谢谢大家。
转自:http://blog.csdn.net/yangchao228/article/details/7027485
相关推荐
EhCache是一个纯Java的进程内缓存框架,具有快速、上手简单等特点,是Hibernate中默认的缓存提供方。 2、Hibernate缓存 Hibernate三级缓存机制简介: 一级缓存:基于Session级别分配一块缓存空间,缓存访问的对象...
EhCache是一个开源的、高性能的Java缓存框架,它被广泛用于提高应用程序的性能,减少数据库负载。在这个“ehcache缓存入门项目”中,我们将深入探讨EhCache的基本概念、配置、使用方法以及一些实用技巧。 1. **...
Ehcache 是一款广泛使用的开源Java缓存解决方案,它为应用程序提供了高效的数据缓存能力,从而提升了系统的性能和响应速度。Ehcache 1.3.0 版本是其历史版本之一,尽管现在已经有了更高级的版本,但了解这个版本对于...
本入门案例将带你了解如何使用Ehcache实现分布式缓存,并特别关注如何将文件数据转换为树形结构。 首先,让我们理解Ehcache的基本概念。Ehcache的核心组件包括缓存管理器(Cache Manager)、缓存(Cache)和缓存项...
在IT领域,尤其是在Java Web开发中,`SpringMVC`、`Spring`、`Hibernate`以及`Ehcache`和`Fastjson`是常见的技术组件,它们分别在不同的层面上发挥着关键作用。以下是这些技术的详细介绍: 1. **SpringMVC**: ...
Ehcache是一款广泛使用的开源Java缓存框架,主要用于提高应用程序的性能和响应速度。在2.9版本中,它提供了强大的缓存功能,包括本地缓存、分布式缓存以及内存管理和缓存策略。这份官方文档详细阐述了Ehcache的核心...
Ehcache 是一个广泛使用的开源Java缓存系统,它提供了内存和磁盘存储,以及对缓存数据的分布式处理能力。在Java应用程序中,Ehcache能够显著提高性能,减少数据库负载,通过缓存经常访问的数据来提升响应速度。本文...
ehCache是一款广泛使用的开源Java缓存库,特别适用于提高应用程序的性能和响应速度。它允许在内存中存储数据,减少对数据库的访问,从而优化系统性能。ehCache 2.6.8是该库的一个版本,包含了基础包、整合包以及源码...
Ehcache是一款高效、开源的Java缓存库,广泛应用于提高应用程序性能,减少数据库负载。在这个压缩包中,我们关注的是Ehcache的核心组件ehcache-core-2.5.2,以及一个示例Cache配置文件Sample cache配置.xml。 **一...
Ehcache是一款广泛使用的Java缓存库,特别适合于提高CPU和I/O密集型应用程序的性能,同时增强应用的可扩展性。它由Adam Murdoch在为SourceForge项目创建页面时灵感突发命名,因其名字是回文而得名。Ehcache自版本...
Ehcache是一个开源的、高性能的Java缓存库,它为应用程序提供了本地内存缓存功能,以提高数据访问速度和减少数据库负载。`ehcache-2.5.1-distribution.tar.gz`是Ehcache 2.5.1版本的发行版压缩包,通常包含了Ehcache...
结合这些组件,我们可以创建一个高效、可扩展的J2EE基础平台,其中Spring管理业务逻辑,Struts处理用户交互,Proxool优化数据库访问,内存数据库提供快速的数据存储,EhCache则用于缓存以提升性能,而Licence管理则...
Ehcache是一个流行的Java缓存库,用于在应用程序中实现高效的数据存储和检索。它能够显著提高性能,尤其是在处理大量数据或频繁访问相同数据时。Ehcache支持内存和磁盘存储,同时还提供了缓存复制和分布式缓存的能力...
**Ehcache** 是一个广泛使用的Java分布式内存缓存系统,它被设计用来提高应用程序的性能,通过存储经常访问的数据来减少对数据库的依赖。Ehcache_2.10.4版本是其在2015年的一个稳定版本,提供了丰富的功能和优化。这...
Ehcache是一款开源的、高性能的Java缓存解决方案,它可以被用于存储和检索数据,以减少对数据库的访问,从而提升应用性能。Ehcache支持内存和磁盘存储,还具备缓存预热、缓存失效策略、缓存分区等功能。在RMI场景下...
Ehcache是Java环境下的一种流行缓存解决方案,它可以显著提升应用的性能,减少数据库的负载。Ehcache可以在内存中存储数据,当需要时快速提供,而无需每次都去数据库查询。它支持分布式缓存,可以在多台服务器之间...
`mybatis-ehcache`便是MyBatis与Ehcache集成的一个组件,用于实现二级缓存功能。 **Ehcache** 是一个广泛使用的开源Java分布式缓存系统,它可以极大地提高应用的性能和响应速度,尤其在读多写少的场景下效果显著。...
Ehcache是一款流行的Java缓存库,用于提高应用性能。它可以存储对象到内存中,避免频繁访问数据库,从而减少响应时间。在Spring MVC和MyBatis的环境中,Ehcache可以用来缓存查询结果,降低数据库压力。通过配置...
这只是一个基础示例,实际应用中可能还需要考虑缓存同步、分布式缓存、缓存更新策略等问题。例如,如果在多节点环境中,可能需要使用分布式Ehcache,如Terracotta服务器,来确保缓存的一致性。 总结来说,Spring ...