Play框架拾遗之五:其他知识点

不羁岁月 提交于 2019-12-10 08:57:20

1、Job异步处理

Job可以有结果返回:

package jobs;
import play.jobs.*;

public class MyJob extends Job<String> {
  public String doJobWithResult() {
    // 执行一些业务逻辑
    return result;
  }
}

Job不仅可以设置启动调用(用@OnApplicationStart),还停止时调用:

import play.jobs.*;

@OnApplicationStop
public class Bootstrap extends Job {
  public void doJob() {
    Fixture.deleteAll();
  }
}

如果希望Web应用启动后,能够在执行Bootstrap Job的同时,又能很快地处理到来的请求,可以为@OnApplicationStart注解添加async=true属性:@OnApplicationStart(async=true)。这样应用程序开启后,Bootstrap Job就会作为后台程序异步执行了。不仅如此,所有的异步Job(async=true)也会在Web应用开启之后同时运行。

@OnApplicationStart(async=true)
public class Bootstrap extends Job {
  public void doJob() {
    if(Page.count() == 0) {
      new Page("root").save();
      Logger.info("A root page has been created.");
    }
  }
}

Play的Job调度是使用Quartz库的CRON表达式,后续会详细介绍

2、HTTP异步编程

Play允许临时挂起HTTP请求。挂起的HTTP请求仍然保持连接,但是该请求的执行会被移出线程池并稍后进行尝试。根据需要,Play可以在一段固定的延时后恢复现场,继续执行请求。

public static void generatePDF(Long reportId) {
  Promise<InputStream> pdf = new ReportAsPDFJob(report).now();
  InputStream pdfStream = await(pdf);
  renderBinary(pdfStream);
}

Play还提供了waitAll() ,waitAny(),waitEither()等方法。

public static void usePromise(){
  F.Promise<WS.HttpResponse> promise1=WS.url("http://domain1.com").getAsync();
  F.Promise<WS.HttpResponse> promise2=WS.url("http://domain2.com").getAsync();
  F.Promise<List<WS.HttpResponse>> promises = F.Promise.waitAll(promise1, promise2);
  await(promises);
  renderText("Execute finished");
}

3、验证码

Play中的play.libs.Images类提供了生成验证码的支持,操作也非常简单。我们可以通过静态方法Images.captacha()快速生成默认大小为150*50的验证码图片,也可以使用Images.captacha(int width, int height)方法生成指定大小的验证码图片。

public static void captcha(){
  Images.Captcha captcha=Images.captcha(); //生成验证码图片
  captcha.addNoise(); //增加澡点
  String code = captcha.getText("#ABCDEF"); //获取文本内容
  captcha.setBackground("#E4EAFD"); //设置背景颜色
  renderBinary(captcha);
}

4、缓存

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前缀的方法是阻塞的,而标准方法是非阻塞的,delete方法会立即返回结果,并没有等待缓存对象是否被真正地物理删除。因此,如果程序执行期间发生了错误(例如IO错误),缓存对象可能仍然存在,并没有被删除。如果操作需要确保缓存对象被删除,可以使用safeDelete方法:

Cache.safeDelete("product_"+id);

配置Memcached

memcached=enabled
memcached.host=127.0.0.1:11211
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!