使用EhCache注解在Spring中进行缓存

本文概述

  • 项目概况
  • 项目设置
  • 一个简单的RESTful Web服务
  • 插入EhCache Spring注解
  • 刷新缓存
  • 总结
EhCache是??一种广泛使用的纯Java缓存, 可以轻松地与大多数流行的Java框架(例如Spring和Hibernate)集成。由于它可以轻松集成到项目中, 因此通常被认为是Java应用程序最方便的选择。特别是:
  • 只需在你的项目中包含JAR即可进行设置。无需其他安装步骤。
  • 它与应用程序运行的过程相同, 因此速度很快。无需其他服务即可运行。
简而言之, EhCache是??任何纯Java应用程序的绝佳选择。
此外, EhCache Spring注解通过简单地将注解添加到可缓存的方法中, 而无需修改方法实现, 即可无缝集成到任何Spring应用程序中。
使用EhCache注解在Spring中进行缓存

文章图片
尽管EhCache提供了直接而丰富的API来以编程方式操作缓存, 但本文主要侧重于通过EhCache Spring Annotations以较少干扰的方式增强Spring应用程序。我们将建立一个Spring MVC项目, 并在Tomcat中部署一个RESTful Web服务。然后, EhCache将被集成到Web服务。
项目概况 我们将在示例项目的上下文中演示EhCache注解。我们将在Tomcat 8服务器上建立一个基于Spring MVC的Web服务。
【使用EhCache注解在Spring中进行缓存】我在Eclipse中开发了该项目, 可以按照此处的说明进行安装。
可以在此处下载Tomcat的最新稳定版本Tomcat 8。
当然, 这些特定平台不是EhCache所必需的。你始终可以选择自己喜欢的IDE和服务器。
此处提供了EhCache Spring Annotations JAR。我们可以看到, 每个版本都有两个JAR:一个带有依赖项, 另一个不带依赖项。具有依赖项的一个还包括EhCache 2和Spring 3, 它们是EhCache批注起作用所必需的。如果我们下载带有依赖项的文件并将其添加到我们的构建路径, 则设置起来会更容易。
EhCache Spring Annotations也与Spring 4兼容, 尽管它必须单独配置。目前尚不清楚该项目是否会在不久的将来支持EhCache 3。对于正在使用或打算使用EhCache 3的用户, 不建议使用本文中讨论的注解方法。
最后, 我们将使用Maven来管理一切。 Maven预装了大多数Eclipse安装程序, 但也可以在此处获得。可以很容易地添加Spring MVC和EhCache Spring Annotations依赖关系, 如本文稍后所示。
项目设置 如果你以前从未设置过Spring项目, 则还可以在Stefan Varga上找到有关该主题的文章。
对于此演示, 我们将使用Maven原型maven-archetype-webapp设置一个基本项目。总体文件结构如下所示:
使用EhCache注解在Spring中进行缓存

文章图片
使用三个软件包创建目录src / main / java:com.srcmini.blog, com.srcmini.blog.cache和com.srcmini.blog.service。我们的应用程序源将包含在这些软件包中, 如下所述。
让我们在web.xml中定义一个称为” springrest” 的Tomcat servlet:
< web-app> ... < servlet> < servlet-name> springrest< /servlet-name> < servlet-class> org.springframework.web.servlet.DispatcherServlet < /servlet-class> < load-on-startup> 1< /load-on-startup> < /servlet> < servlet-mapping> < servlet-name> springrest< /servlet-name> < url-pattern> /*< /url-pattern> < /servlet-mapping> < /web-app>

除非另有明确说明, 否则Spring MVC DispatcherServlet将在目录WEB-INF中查找名为{servlet-name} -servlet.xml的XML配置文件。让我们创建一个名为springrest-servlet.xml的配置文件。要启用以@RequestMapping注解的Spring流程控制器方法, 我们只需将< mvc:annotation-driven /> 添加到此文件中。另外, 我们通过添加< context:component-scan base-package =” com.srcmini.blog” /> 来定义Spring的基本软件包, 以自动扫描和注册bean。 springrest-servlet.xml配置变为:
< beans ... > < mvc:annotation-driven /> < context:component-scan base-package="com.srcmini.blog" /> < /beans>

一个简单的RESTful Web服务 现在, 我们已经正确配置了项目, 让我们实现一个简单的” 消息服务” API。在我们的基本程序包project.srcmini.blog中, 我们将添加SpringRestControllerWithEhCache.java, 其中一个GET方法用于按ID获取消息, 而一个POST方法用于按ID设置消息:
@RestController @RequestMapping( "/" ) public class SpringRestControllerWithEhCache { @Autowired MessageService messageService; @RequestMapping( value = "http://www.srcmini.com/message/{id}", method = RequestMethod.GET ) public String getMessage( @PathVariable Integer id ) { String message = messageService.getMessage( id ); System.out.println( "get message ["+message+"] at "+new Date() ); return message; }@RequestMapping( value = "http://www.srcmini.com/message/set/{id}/{message}", method = RequestMethod.POST ) public String setMessage( @PathVariable Integer id, @PathVariable String message ) { System.out.println( "set message ["+message+"] at "+new Date() ); messageService.setMessage( id, message ); return message; } }

我们将在com.srcmini.blog.service中定义MessageService类。它将访问存储在我们的记录系统(SOR)中的消息。在生产应用程序中, SOR类似于关系数据库。为简单起见, 我们将使用HashMap:
@Service public class MessageService { private ConcurrentHashMap< Integer, String> messages = new ConcurrentHashMap< Integer, String> (); public String getMessage( Integer id ) { System.out.println( "Getting data from SOR......" ); return messages.get( id ); }public void setMessage( Integer id, String message ){ messages.put( id, message ); } }

现在, 如果我们将项目导出为WAR并将其部署在Tomcat中, 则应该能够通过在http:// localhost:8080创建HTTP POST请求来为ID = 1设置一条消息, 例如” test_message” / EhCacheExample / message / set / 1 / test_message。然后, 我们应该能够通过http:// localhost:8080 / EhCacheExample / message / 1上的HTTP GET请求获得” test_message” 。我使用Insomnia作为便捷的REST客户端来进行测试。
插入EhCache Spring注解 现在, 让我们为EhCache工作。仅需几个简单的步骤即可配置我们的项目以正确运行EhCache。
使用EhCache注解在Spring中进行缓存

文章图片
步骤1:更新依赖项以使用EhCache Spring注解
在Maven的pom.xml中添加EhCache Spring Annotations依赖项:
< !-- ehcache --> < dependency> < groupId> com.googlecode.ehcache-spring-annotations< /groupId> < artifactId> ehcache-spring-annotations< /artifactId> < version> 1.2.0< /version> < /dependency>

步骤2:设置自定义缓存管理器
Spring具有内置的EhCache缓存管理器org.springframework.cache.ehcache.EhCacheManagerFactoryBean。这适用于大多数缓存情况, 但是我发现定义自定义缓存管理器很有用, 因为它允许我使用相同的缓存管理器以编程方式或通过批注控制缓存。本文重点介绍注解, 但让我们继续定义自定义缓存管理器, 以便在需要时可以随时使用。如果你希望使用默认的缓存管理器, 则可以跳过此步骤。
我们将在com.srcmini.blog.cache.CustomCacheManager中定义新类:
public class CustomCacheManager extends net.sf.ehcache.CacheManager{public CustomCacheManager(){ super(); }/* Add your own cache methods here. * * public void myCustomCacheMethod(){ *// your code here * } * */ }

通过如下更新springrest-servlet.xml来启用它:
... < ehcache:annotation-driven cache-manager="customCacheManager" /> < bean id="customCacheManager" class="com.srcmini.blog.cache.CustomCacheManager" scope="singleton"> < /bean> ...

步骤3:配置EhCache
最后, 在类路径中创建EhCache配置文件ehcache.xml。默认情况下, Eclipse将在类路径中包含src / main / resources, 我们将文件放在此处。该文件是EhCache正常运行所必需的。它定义了缓存名称和每个缓存的一些属性, 例如timeToLiveSeconds:
< ehcache xmlms:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> < diskStore path="cache" /> < cache name="messageCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="0" timeToLiveSeconds="10" overflowToDisk="false" memoryStoreEvictionPolicy="LFU" /> < /ehcache>

步骤4:测试缓存
现在, 一切就绪并准备就绪, 使用EhCache应该变得轻松而愉快。我们可以简单地将@Cacheable添加到要缓存的方法或类中。例如, 我在MessageService的getMessage方法中添加了@Cacheable。就这么简单!
@Cacheable( cacheName = "messageCache" ) public String getMessage( Integer id ) { System.out.println( "Getting data from SOR......" ); return messages.get( id ); }

为了测试缓存是否正常工作, 我们可以通过在http:// localhost:8080 / EhCacheExample / message / set / 1 / newMessage上发出HTTP POST请求来创建ID = 1的消息, 然后获取ID = 1次, 使用GET请求到http:// localhost:8080 / EhCacheExample / message / 1。从下面的控制台输出中可以看到, Web服务在我们第一次请求消息时要求SOR获取消息, 但接下来的两个请求则不要求, 而是返回缓存的消息。因为我们将timeToLiveSeconds定义为10, 所以Web服务会在10秒后调用SOR以再次获取消息:
set message [newMessage] at Sun Dec 06 23:55:39 MST 2015 get message [newMessage] at Sun Dec 06 23:55:42 MST 2015 Getting data from SOR...... get message [newMessage] at Sun Dec 06 23:55:47 MST 2015 get message [newMessage] at Sun Dec 06 23:55:49 MST 2015 get message [newMessage] at Sun Dec 06 23:55:54 MST 2015 Getting data from SOR......

刷新缓存 现在, 我们享受高速缓存给我们带来的速度和便利, 并且EhCache足以每10秒刷新一次。但是, 如果我们希望在SOR更新后立即刷新它怎么办? EhCache Spring Annotation提供了@TriggersRemove, 以便在调用带注解的方法时从缓存中删除指定的键。在我们的消息服务API中, 调用setMessage时应从缓存中删除缓存的消息。因此, 下次出现getMessage请求时, 缓存将从SOR中获取新记录:
@Cacheable( cacheName = "messageCache", keyGenerator = @KeyGenerator (// method name is not included in cache key to work with @TriggersRemove name = "HashCodeCacheKeyGenerator", properties = @Property( name="includeMethod", value="http://www.srcmini.com/false" ))) public String getMessage( Integer id ) { System.out.println( "Getting data from SOR......" ); return messages.get( id ); }@TriggersRemove( cacheName = "messageCache", keyGenerator = @KeyGenerator ( name = "HashCodeCacheKeyGenerator", properties = @Property( name="includeMethod", value="http://www.srcmini.com/false" ))) public void setMessage( @PartialCacheKey Integer id, String message ) { messages.put( id, message ); }

高速缓存管理器使用密钥生成器来生成高速缓存密钥。可以在此处找到预定义的缓存密钥生成器的列表。默认情况下, @ KeyGenerator使用方法名称和传入的参数来生成缓存键。但是, 由于我们希望setMessage方法生成与getMessage相同的键并删除与该键关联的缓存值, 因此我们必须仅使用消息ID作为键, 并消除用于键生成的方法名称。因此, 我们将两种方法的密钥生成器的includeMethod属性设置为false。另外, 由于setMessage有两个参数, 因此我们在id参数上使用EhCache的@PartialCacheKey批注来指定它是密钥生成器应使用的唯一参数。最后, 回想一下, 我们为此资源类型配置了专用的缓存messageCache, 因此, 仅将键的ID用作ID不会带来与其他资源类型发生冲突的危险。
现在, 如果我们对ID = 1的消息执行几个HTTP请求, 如下所示:
HTTP POST:http://localhost:8080/EhCacheExample/message/set/1/newMessage1 HTTP GET:http://localhost:8080/EhCacheExample/message/1 HTTP POST: http://localhost:8080/EhCacheExample/message/set/1/newMessage2 HTTP GET:http://localhost:8080/EhCacheExample/message/1

控制台将显示:
set message [newMessage1] at Tue Dec 08 17:53:44 MST 2015 get message [newMessage1] at Tue Dec 08 17:53:47 MST 2015 Getting data from SOR...... set message [newMessage2] at Tue Dec 08 17:53:50 MST 2015 get message [newMessage2] at Tue Dec 08 17:53:53 MST 2015 Getting data from SOR......

总结 最终的项目结构如下所示:
使用EhCache注解在Spring中进行缓存

文章图片
在此示例中, 我们首先创建了一个简单的Spring MVC RESTful Web应用程序。然后, 我们甚至无需修改现有应用程序代码中的任何一行, 就可以使用EhCache Spring注解将EhCache无缝集成到应用程序中。我们已经证明, EhCache Spring Annotations既易于安装(通过添加其Maven依赖项), 又易于使用(通过向方法中添加注解)。
进一步阅读
可以在这里找到EhCache文档, 在这里可以找到EhCache Spring注解文档。
另外, 在GitHub上查看本文描述的示例项目。

    推荐阅读