Play framework 1.2.3 使用缓存、Memcached集成

2024-06-20 03:18

本文主要是介绍Play framework 1.2.3 使用缓存、Memcached集成,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • play框架包含一个缓存lib,这个lib是用来和Memcached集成做分布式缓存用的。 

如果不配置Memcached,play框架将会使用单独的缓存(EhCache),其数据存储在JVM的堆中。把数据存储在JVM的堆中 违反了play框架“不共享任何东西”的原则,这也导致了你不能把应用程序同时部署到多个机器,即不能在多个机器上负载均衡以保证应用的可用性、高性能(即使在多个机器部署了相同的应用,但是由于不同机器的JVM是相互独立的,会导致不同机器的缓存数据不同,即不同机器对同一请求的响应可能不同!不一致性!) 

理解缓存的应用环境是很重要的:当你把数据放到缓存中, 你不能期望数据在缓存中一直存在。实际上,你不应该这样想。缓存中存取数据很快,但是缓存是有有效期的、并且缓存数据是存放在内存中(并没有做持久化备份)。 

因此最佳使用缓存的方式是当发现缓存的数据不存在时,直接从数据源重新抓取。 
Java代码   收藏代码
  1. public static void allProducts() {  
  2.     List<Product> products = Cache.get("products", List.class);  
  3.     if(products == null) {  
  4.         products = Product.findAll();  
  5.         Cache.set("products", products, "30mn");  
  6.     }  
  7.     render(products);  
  8. }  

缓存API: 
play框架中的缓存类 play.cache.Cache,其包含了从缓存中取值,设值,替换值的方法。 
例子: 
Java代码   收藏代码
  1. public static void showProduct(String id) {  
  2.     Product product = Cache.get("product_" + id, Product.class);  
  3.     if(product == null) {  
  4.         product = Product.findById(id);  
  5.         Cache.set("product_" + id, product, "30mn");  
  6.     }  
  7.     render(product);  
  8. }  
  9.    
  10. public static void addProduct(String name, int price) {  
  11.     Product product = new Product(name, price);  
  12.     product.save();  
  13.     showProduct(product.id);  
  14. }  
  15.    
  16. public static void editProduct(String id, String name, int price) {  
  17.     Product product = Product.findById(id);  
  18.     product.name = name;  
  19.     product.price = price;  
  20.     Cache.set("product_" + id, product, "30mn");  
  21.     showProduct(id);  
  22. }  
  23.    
  24. public static void deleteProduct(String id) {  
  25.     Product product = Product.findById(id);  
  26.     product.delete();  
  27.     Cache.delete("product_" + id);  
  28.     allProducts();  
  29. }  

上面的delete, set等标准方法都是 非阻塞的。也就是说,当你调用 
Java代码   收藏代码
  1. Cache.delete("product_" + id);  

时,delete方法不等缓存对象真的被删除就直接返回。所以,如果在删除缓存对象时发生错误(譬如IO错误),那么缓存对象是仍然存在的。 
sateDelete方法: 阻塞的,在缓存对象真的被删除后,方法才会返回,方法有bool型的返回值来表明操作是否成功。 

注意: 
  • 由于是阻塞方法,使用safe前缀的方法会降低应用的响应速度。因此,只在需要时才那么使用。
  • 当指定参数expiration == "0s"(0秒)时,缓存实际的失效时间可能由于不同的缓存实现相差很大。

不要把Session当缓存使用! 
当你用过基于内存Session实现的框架的话、如Servlet中的HTTP  Session( play框架中的session是以Cookie形式存储在客户端的),你可能会对play框架中只允许在session中以String的形式存储少量数据感到不习惯。在play框架中,session并不是你存储应用数据的地方。 

基于内存的Session,使用例子: 
Java代码   收藏代码
  1. httpServletRequest.getSession().put("userProducts", products);  
  2. ...  
  3. // and then in subsequent requests  
  4. products = (List<Product>)httpServletRequest.getSession().get("use  
  5. rProducts");  

play框架等效实现: 
Java代码   收藏代码
  1. Cache.set(session.getId(), products);  
  2. ...  
  3. // and then in subsequent requests  
  4. List<Product> products = Cache.get(session.getId(), List.class)  

这里我们使用唯一的UUID来作为每个用户缓存的key。注意:和session不同的是, 缓存并不会绑定到任何一个用户中,缓存在整个应用中是共享的。 

集成Memcached缓存配置(application.conf文件): 
memcached:时候启用Memcached缓存,如果不配置,那么play默认使用单独的缓存EhCache,其数据存储在JVM的堆中。可能值:disabled(默认),enabled 

memcached.host:启用Memcached时,指定memcached host地址,默认值:127.0.0.1:11211。 
memcached.host=127.0.0.1:11211 
多个host做分布式缓存时,如下配置: 
memcached.1.host=127.0.0.1:11211 
memcached.2.host=127.0.0.1:11212 



Unmi 注: EhCachePlugin 的注册方式可以查看 play_x.x.x.jar(比如 $PLAY_HOME/repository/local/play/play_2.9.1/2.0.4/jars/play_2.9.1.jar) 包中的 play.plugins 中的内容:

1
2
3
4
5
6
7
8
100:play.api.i18n.MessagesPlugin
200:play.api.db.BoneCPPlugin
300:play.db.ebean.EbeanPlugin
400:play.db.jpa.JPAPlugin
500:play.api.db.evolutions.EvolutionsPlugin
600:play.api.cache.EhCachePlugin
1000:play.api.libs.concurrent.AkkaPlugin
10000:play.api.GlobalPlugin

这是 Play2.0.4 默认注册的插件,其中就包含了 600:play.api.cache.EhCachePlugin 插件。

使用下面简单的 API,你就可以往缓存中存数据了:

1
Cache.set( "item.key" , connectedUser)

之后获取它:

1
val maybeUser : Option[User]  = Cache.getAs[User]( "item.key" )
本文原始链接 http://unmi.cc/play2-0-tutorials-cn-cache-api/, 来自 隔叶黄莺 Unmi Blog

当缓存数据不存在时,还有一个帮助方法在你获取或设置缓存数据给你带来了便利:

1
2
3
val user : User  = Cache.getOrElseAs[User]( "item.key" ) {
   User.findById(connectedUser)
}

缓存 HTTP 响应数据

你可以用标准的 Action 组合简单的创建一个聪明的具体缓存特性的 Action.

注: Play HTTP Result 实例可安全的被缓存并被重用.

Play 提供了默认, 内建的方式来应对标准的情况:

1
2
3
4
5
def index  = Cached( "homePage" ) {
   Action {
     Ok( "Hello world" )
   }
}

或者甚至是这样:

1
2
3
4
5
6
7
def userProfile  = Authenticated { user  = >
   Cached(req  = "profile." + user) {     
     Action {
       Ok(views.html.profile(User.find(user)))
     }  
   }
}

这篇关于Play framework 1.2.3 使用缓存、Memcached集成的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1076950

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

使用Python构建智能BAT文件生成器的完美解决方案

《使用Python构建智能BAT文件生成器的完美解决方案》这篇文章主要为大家详细介绍了如何使用wxPython构建一个智能的BAT文件生成器,它不仅能够为Python脚本生成启动脚本,还提供了完整的文... 目录引言运行效果图项目背景与需求分析核心需求技术选型核心功能实现1. 数据库设计2. 界面布局设计3

使用IDEA部署Docker应用指南分享

《使用IDEA部署Docker应用指南分享》本文介绍了使用IDEA部署Docker应用的四步流程:创建Dockerfile、配置IDEADocker连接、设置运行调试环境、构建运行镜像,并强调需准备本... 目录一、创建 dockerfile 配置文件二、配置 IDEA 的 Docker 连接三、配置 Do

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali