play框架使用起来(16)

Posted zyhlal

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了play框架使用起来(16)相关的知识,希望对你有一定的参考价值。

1、缓存

缓存是用来避免频繁到服务器端获取数据而建立的一个存取更快的临时存储器。缓存的容量相对较小,但执行速度非常快,其主要作用为:

  • 存储系统经常访问的数据。
  • 存储耗时较长的计算结果。


      合理地缓存数据,可以提高系统的性能。Play内置了缓存库,并为分布式环境提供了Memcached缓存数据的支持。


补充:

Memcached是一套开源的分布式内存对象缓存系统,它通过在内存中缓存数据和对象来减少读取数据库的次数,从而大幅度降低数据库负载。


      如果项目中没有配置Memcached,Play将使用JVM堆中的独立缓存进行数据存储。但是将数据缓存在不同服务器的JVM堆中破坏了Play的share nothing原则:我们不能将应用程序运行在多个服务器上的同时,还期望数据保持一致,这样做只会导致每个程序实例都拥有各自不同的数据副本。

      当我们在使用缓存时,必须明确其自身特性:缓存存在于内存中(不进行持久化),只是用于存放暂时性的数据,时间一到就会过期。因此缓存并不是一个安全的存储器,不能保证数据可以永久存在。如果发现数据在缓存中已过期,需要重新获取数据,并再次放入缓存:

public static void allProducts() 
   
List<Product> products = Cache.get("products", List.class);
   
if(products == null)
        products
= Product.findAll();
       
Cache.set("products", products, "30mn");
   

    render
(products);


1.1 缓存 API#

      play.cache.Cache类提供了一系列访问缓存的API,包含了完整的设置、替换和获取数据的方法:

public static void showProduct(String id) 
   
Product product = Cache.get(id, Product.class);
   
if(product == null)
        product
= Product.findById(id);
       
Cache.set("product_"+id, product, "30mn");
   

    render
(product);

 
public static void addProduct(String name, int price)
   
Product product = new Product(name, price);
    product
.save();
    showProduct
(id);

 
public static void editProduct(String id, String name, int price)
   
Product product = Product.findById(id);
    product
.name = name;
    product
.price = price;
   
Cache.set("product_"+id, product, "30mn");
    showProduct
(id);

 
public static void deleteProduct(String id)
   
Product product = Product.findById(id);
    product
.delete();
   
Cache.delete("product_"+id);
    allProducts
();

      操作缓存的API中有很多方法是以safe作为前缀的,如safeDelete,safeSet等。带safe前缀的方法是阻塞的,而标准方法是非阻塞的,这意味当我们执行以下程序时:

Cache.delete("product_"+id);

      delete方法会立即返回结果,并没有等待缓存对象是否被真正地物理删除。因此,如果程序执行期间发生了错误(例如IO错误),缓存对象可能仍然存在,并没有被删除。

      如果操作需要确保缓存对象被删除,可以使用safeDelete方法:

Cache.safeDelete("product_"+id);
      该方法是阻塞式的,并返回一个布尔值标识对象是否被成功删除。确保缓存对象被删除的标准写法如下:
if(!Cache.safeDelete("product_" + id)) 
   
throw new Exception("Oops, the product has not been removed from the cache");

...


注意:

带safe前缀的方法是阻塞式的,会降低应用程序的性能。因此,在实际操作中需要酌情考虑,选择最佳方案。





1.2 避免使用Session作为缓存 #

      Play只允许将少量的数据以字符串形式储存在HTTP Session中。读者可能会感到非常不适应,但这样的设计确实更优雅,因为Session本来就不应该是缓存数据的地方!

      读者可能已经习惯于以下写法,将数据缓存在Session中:

httpServletRequest.getSession().put("userProducts", products);
...
// and then in subsequent requests
products
= (List<Product>)httpServletRequest.getSession().get("userProducts");

      但在Play中实现同样效果的方式却截然不同:

Cache.put(session.getId(), products);
...
// and then in subsequent requests
List<Product> products = Cache.get(session.getId(), List.class);

      我们可以通过UUID获取缓存中关联用户的信息。


注意:

与Session对象不同,缓存中的内容是独立的,不会绑定任何特定的用户。





1.3 配置Memcached#

      如果项目要启用Memcached,需要在application.conf中打开Memcached开关,并设置Memcached的守护进程地址:

memcached=enabled
memcached
.host=127.0.0.1:11211

      我们还可以指定多个守护进程地址,使之连接到同一个分布式缓存:

memcached=enabled
memcached
.1.host=127.0.0.1:11211
memcached
.2.host=127.0.0.1:11212


2、产品化


2.1 定义框架 ID#

  



首先需要给应用指定框架ID。例如,我们使用play id命令将框架ID设置为production,之后如果需要将Play框架设置为PROD模式只需在application.conf文件里进行如下配置:

 %production.application.mode=prod

      在该模式下启动应用,Play会预编译所有的Java文件和模版文件。如果在这一步出现了错误,应用是不能被成功启动的,此时对源文件的修改也不再会被热编译与加载。

2.2 设置数据库#

      如果应用还在使用开发数据库(例如内存数据库db=mem或者文件数据库db=fs,),显然不能满足产品化的需求,我们必须在产品化的时候选择更加健壮的数据库引擎。下例给出通用的JDBC连接方式,并以mysql为例:

%production.以上是关于play框架使用起来(16)的主要内容,如果未能解决你的问题,请参考以下文章

play框架使用起来(17)

play框架使用起来(11)

play框架使用起来

play框架使用起来(15)

play框架使用起来(15)

play框架使用起来(12)