- 浏览: 79931 次
- 性别:
- 来自: 重庆
最新评论
-
禀圣含华:
怎么弄空格呢?___________然后我固定这些空格,怎么弄 ...
第18章. iText PDF 生成 -
super0555:
managed
第13章 Seam 应用程序框架 -
Javakeith:
代码呢?共享下代码呗!
第18章. iText PDF 生成 -
tonyshen277:
同感啊。还在做Win32下的开发,楼主所说的一个都不能少啊。
转自baidu wqqq 给软件开发初学者 -
kdboy:
的确,把人放在宇宙中去看,从上帝的眼中去看,人的确是非常渺小, ...
人生是什么
第22章. 异步和消息
Seam 使异步执行来自网页请求的工作变得非常容易。在多数人在Java EE中考虑异步时,他们想到的是使用JMS。在Seam中,这的确是一种解决问题的方法,并且在你有严格和明确定义的服务质量需求时,这是正确的方法。 Seam利用Seam组件使发送和接收JMS消息变得非常容易。
但是对多数用例而言,用JMS就太夸张了。Seam在你的调度器(dispatchers) 选择层之上分层了一个简单的异步方法和事件机能:
- java.util.concurrent.ScheduledThreadPoolExecutor (默认)
- the EJB timer service (对 EJB 3.0 环境)
- Quartz
22.1. 异步
异步事件和方法调用具有与基本的分配器机制一样期望的相同服务质量。基于ScheduledThreadPoolExecutor的默认分配器(dispatcher)能有效地完成任务,但不提供对持久化异步任务的支持,因此不能保证一个任务总会被真正地执行。如果你工作在支持EJB3的环境,增加下列行到components.xml:
<async:timer-service-dispatcher/>
那么,你的异步任务会被容器的EJB定时器服务处理。如果你不熟悉定时器服务,不用担心,假如你想在Seam中使用异步方法,你不必直接与它交互。知道的重要事情是任何好的EJB3实现都会有使用持久化定时器的选项,它将保证任务最终会被处理。
另外的一个选择是使用开源Quartz库来管理异步方法。你需要捆绑Quartz库JAR (在lib目录会找到) 在你的EAR中,并application.xml声明它作为一个Java 模块。Quartz分配器可以通过增加一个Quartz 性文件到类目录被配置。它必须被命名为seam.quartz.properties。 此外,你需要增加下列行到components.xml,安装Quartz分配器。
<async:quartz-dispatcher/>
Seam API使用ScheduledThreadPoolExecutor、 EJB3定时器和Quartz调度器(Scheduler)为默认值很大程度上是相同的。他们可以通过增加一行到components.xml中实现“即插即用”
22.1.1. 异步方法
最简单的形式,一个异步调用仅让来自调用者的方法被异步执行(以不同的线程)。在我们想即时响应客户端时,我们常使用一个异步调用,并让一些费时的工作在后台处理。在使用AJAX的应用程序中这个模式运行良好,客户端可以自动轮询服务器的工作成果。
对EJB组件,我们注释本地接口来指定一个方法被异步执行。
@Local
public interface PaymentHandler
{
@Asynchronous
public void processPayment(Payment payment);
}
(对JavaBean组件 ,如果我们喜欢,我们可以注释组件实现类)
对bean类而言,异步的使用是透明的:
@Stateless
@Name("paymentHandler")
public class PaymentHandlerBean implements PaymentHandler
{
public void processPayment(Payment payment)
{
//do some work!
}
}
并对客户端也是透明的:
@Stateful
@Name("paymentAction")
public class CreatePaymentAction
{
@In(create=true) PaymentHandler paymentHandler;
@In Bill bill;
public String pay()
{
paymentHandler.processPayment( new Payment(bill) );
return "success";
}
}
异步方法在一个全新的事件(event)上下文中被执行,并且没有访问调用者的会话(session)或对话( conversation)上下文的状态,业务流程(business process)上下文被传播。
异步方法调用可以使用@Duration、 @Expiration和 @IntervalDuration 注释来预定计划稍后执行。
@Local
public interface PaymentHandler
{
@Asynchronous
public void processScheduledPayment(Payment payment, @Expiration Date date);
@Asynchronous
public void processRecurringPayment(Payment payment, @Expiration Date date, @IntervalDuration Long interval)'
}
@Stateful
@Name("paymentAction")
public class CreatePaymentAction
{
@In(create=true) PaymentHandler paymentHandler;
@In Bill bill;
public String schedulePayment()
{
paymentHandler.processScheduledPayment( new Payment(bill), bill.getDueDate() );
return "success";
}
public String scheduleRecurringPayment()
{
paymentHandler.processRecurringPayment( new Payment(bill), bill.getDueDate(), ONE_MONTH );
return "success";
}
}
客户端和服务都可以访问与调用相关联的定时器对象。显示在下面的定时器对象是EJB3定时器,在你使用EJB3分配器(dispatcher)时。对于默认的ScheduledThreadPoolExecutor,返回的对象是JDK的Future。对于Quartz 分配器(dispatcher), 它返回 QuartzTriggerHandle,我们在下节讨论它。
@Local
public interface PaymentHandler
{
@Asynchronous
public Timer processScheduledPayment(Payment payment, @Expiration Date date);
}
@Stateless
@Name("paymentHandler")
public class PaymentHandlerBean implements PaymentHandler
{
@In Timer timer;
public Timer processScheduledPayment(Payment payment, @Expiration Date date)
{
//do some work!
return timer; //注意返回的值完全被忽略
}
}
@Stateful
@Name("paymentAction")
public class CreatePaymentAction
{
@In(create=true) PaymentHandler paymentHandler;
@In Bill bill;
public String schedulePayment()
{
Timer timer = paymentHandler.processScheduledPayment( new Payment(bill), bill.getDueDate() );
return "success";
}
}
异步方法不能返回任何其它值给调用者。
22.1.2. 使用Quartz分配器的异步方法
Quartz分配器(如何安装它见前文)允许使用上文的@Asynchronous, @Duration, @Expiration, 和 @IntervalDuration注释。 然而它有一些超强的附加功能。Quartz分配器支持三个新的注释。
@FinalExpiration注释为经常性的任务指定一个结束日期。注意,你可以注入 QuartzTriggerHandle。
@In QuartzTriggerHandle timer;
// 在" processor "组件中定义方法
@Asynchronous
public QuartzTriggerHandle schedulePayment(@Expiration Date when, @IntervalDuration Long interval, @FinalExpiration Date endDate, Payment payment)
{
// 做重复或长期运行的任务,直到结束日期(endDate)
}
... ...
// 在业务逻辑处理代码中制定计划任务
// 现在开始, 每隔一小时重复,2010年5月10号结束
Calendar cal = Calendar.getInstance ();
cal.set (2010, Calendar.MAY, 10);
processor.schedulePayment(new Date(), 60*60*1000, cal.getTime(), payment);
注意,这个方法返回QuartzTriggerHandle对象,稍后你可以用它来停止、暂停和重新开始日程安排程序(scheduler)。QuartzTriggerHandle对象被系列化,所以,如果你需要保持它一段较长的时间,你可以存储它到数据库。
QuartzTriggerHandle handle =processor.schedulePayment(payment.getPaymentDate(), payment.getPaymentCron(),payment);
payment.setQuartzTriggerHandle( handle );
// 存 payment到数据库
// 稍后 ...
// 从数据库取回 payment
// 取消剩余的计划任务
payment.getQuartzTriggerHandle().cancel();
@IntervalCron支持任务行程安排的Unix cron工作语法。例如,下面的异步方法运行在3月的每个星期三的下午2点10分到下午2点44分。
// 定义方法
@Asynchronous
public QuartzTriggerHandle schedulePayment(@Expiration Date when, @IntervalCron String cron, Payment payment)
{
// 做重复或长期运行的任务
}
... ...
//在业务逻辑处理代码中制定计划任务
QuartzTriggerHandle handle = processor.schedulePayment(new Date(), "0 10,44 14 ? 3 WED", payment);
@IntervalBusinessDay注释支持在“第N营业日”调用的情形。例如,下面的异步方法运行在每月的第2个营业日的14:00点。默认时,它从营业日中排除了直到2010年之前的所有周末和美国联邦假期。
// 定义
@Asynchronous
public QuartzTriggerHandle schedulePayment(@Expiration Date when, @IntervalBusinessDay NthBusinessDay nth, Payment payment)
{
// 做重复或长期运行的任务
}
... ...
// 在业务逻辑处理代码中制定计划任务
QuartzTriggerHandle handle = processor.schedulePayment(new Date(), new NthBusinessDay(2, "14:00", WEEKLY), payment);
NthBusinessDay对象包含调用触发器的配置。 你可以通过additionalHolidays属性指定更多的假日(例如,公司假日,非美国假日等等)。
public class NthBusinessDay implements Serializable
{
int n;
String fireAtTime;
List <Date> additionalHolidays;
BusinessDayIntervalType interval;
boolean excludeWeekends;
boolean excludeUsFederalHolidays;
public enum BusinessDayIntervalType { WEEKLY, MONTHLY, YEARLY }
public NthBusinessDay ()
{
n = 1;
fireAtTime = "12:00";
additionalHolidays = new ArrayList <Date> ();
interval = BusinessDayIntervalType.WEEKLY;
excludeWeekends = true;
excludeUsFederalHolidays = true;
}
... ...
}
@IntervalDuration, @IntervalCron, 和 @IntervalNthBusinessDay注释是互斥的。 如果使用它们在同一个方法中,会抛出RuntimeException。
22.1.3. 异步事件
组件驱动事件也可以是异步的。为引发一个异步处理事件,简单调用Events 类的raiseAsynchronousEvent()方法就行了。 要安排一个定时事件,调用 raiseTimedEvent()方法, 传递一个schedule对象给它(对默认分配器或定时器服务分配器,使用TimerSchedule)。 组件可以用通常的方法观察异步事件,但是要记着只有业务流程(business process)上下文被传播到异步线程。
22.1.4. 根据异步调用处理异常
当一个异常通过异步分配器传播时,每种异步分配器的行为表现不同。例如,java.util.concurrent 分配器会暂停一个重复调用的进一步执行,而EJB3定时服务会取消(swallow)异常。因此,Seam 捕获异步调用产生的所有异常,在它达到分配器之前。
默认时,异步执行产生的任何异常将被捕获,并记录在错误级别。你可以自定义这种全局行为,通过覆盖org.jboss.seam.async.asynchronousExceptionHandler组件:
@Scope(ScopeType.STATELESS)
@Name("org.jboss.seam.async.asynchronousExceptionHandler")
public class MyAsynchronousExceptionHandler extends AsynchronousExceptionHandler {
@Logger Log log;
@In Future timer;
@Override
public void handleException(Exception exception) {
log.debug(exception);
timer.cancel(false);
}
}
这里,例如, 使用java.util.concurrent 分配器,我们注入它的控制(control)对象,并且在遭遇一个异常时,取消以后所有调用。
对个别组件你也可以改变这种行为,通过在这个组件中实现方法public void handleAsynchronousException(Exception exception); 例如 :
public void handleAsynchronousException(Exception exception) {
log.fatal(exception);
}
22.2. 在Seam中的消息
Seam可轻松在Seam组件间发送和接收JMS消息。
22.2.1. 配置Configuration
为配置发送JMS消息的Seam的基础设施,你需要告诉Seam你想发送消息去的所有topics(主题)和queues(队列) ,并也要告诉Seam在什么地方找到QueueConnectionFactory(队列连接工厂)和 TopicConnectionFactory(主题连接工厂)。
Seam默认使用UIL2ConnectionFactory, 一个使用JBossMQ(一个实现了JMS 1.1 规范的JMS服务器)的通用连接工厂。如果你使用了一些其他JMS供应者,你需要在seam.properties,web.xml或components.xml中设置一个或两个queueConnection.queueConnectionFactoryJndiName 和topicConnection.topicConnectionFactoryJndiName。
你也需要在components.xml列出topics和queues,安装Seam管理的 TopicPublishers和 QueueSenders:
<jms:managed-topic-publisher name="stockTickerPublisher" auto-create="true" topic-jndi-name="topic/stockTickerTopic"/>
<jms:managed-queue-sender name="paymentQueueSender" auto-create="true" queue-jndi-name="queue/paymentQueue"/>
22.2.2. 发送消息
现在,你可以注入一个JMS TopicPublisher 和TopicSession到任何组件:
@In
private TopicPublisher stockTickerPublisher;
@In
private TopicSession topicSession;
public void publish(StockPrice price) {
try
{
stockTickerPublisher.publish( topicSession.createObjectMessage(price) );
}
catch (Exception ex)
{
throw new RuntimeException(ex);
}
}
或者, 使用队列:
@In
private QueueSender paymentQueueSender;
@In
private QueueSession queueSession;
public void publish(Payment payment) {
try
{
paymentQueueSender.send( queueSession.createObjectMessage(payment) );
}
catch (Exception ex)
{
throw new RuntimeException(ex);
}
}
22.2.3. 使用消息驱动bean接收消息
你也可能使用任何EJB3消息驱动bean处理消息。消息驱动bean甚至可以是Seam组件,在这种情况下,注入其它事件和应用程序作用域的Seam组件成为可能。
22.2.4. 在客户端接收消息
Seam远程让你根据客户边JavaScript订阅一个JMS主题。这在第25章 远程描述。
发表评论
-
第31章. Seam内建组件
2009-05-28 11:51 1462第31章. Seam内建组件 本章描述Seam内建组件 ... -
第30章. Seam注释
2009-05-26 20:21 1597第30章. Seam注释 在你编写一个Seam应用程 ... -
第31章. Seam内建组件
2009-05-26 20:21 1424第31章. Seam内建组件 本章描述Seam内建组件 ... -
第29章. 配置Seam和打包Seam应用程序
2009-05-26 20:19 1540第29章. 配置Seam和打包Seam应用程序 配置 ... -
第28章. Hibernate搜索
2009-05-26 20:17 152028.1. 介绍 如Apache Lucen ... -
第27章. Spring框架集成
2009-05-26 20:16 1398第27章. Spring框架集成 Spring集成 ... -
第26章. Seam和Google网页工具
2009-05-26 20:15 1216第26章. Seam和Google网页工具 ... -
第25章. 远程
2009-05-26 20:15 1269第25章. 远程 Seam 提供了一个从网页远程访 ... -
第24章. Web服务
2009-05-26 20:15 1677第24章. Web服务 Seam 集成了JBossWS, ... -
第23章. 缓存
2009-05-26 20:14 1416第23章. 缓存 在 ... -
第21章. Email
2009-05-26 20:11 1311现在Seam包含一个用于模板和发送邮件的可选组件。 Emai ... -
第 20章. RSS支持
2009-05-26 20:10 820第 20章. RSS支持 20.1. 安装 20.2. ... -
第19章. 微软的Excel 电子表格应用程序支持
2009-05-26 20:07 1822第19章. 微软的Excel 电子表格应用程序支持 S ... -
第18章. iText PDF 生成
2009-05-26 20:01 6474第18章. iText PDF 生成 18.1. 使用PDF ... -
第17章. Seam文本
2009-05-26 19:59 1024第17章. Seam文本 面向协作站点需要一种更有友好的 ... -
第16章. 国际化、本地化和主题
2009-05-26 19:57 1388第16章. 国际化、本地化和主题 Seam使构建国际化应用程 ... -
第15章 安全(2)
2009-05-26 19:56 932第15章 安全(2) 15.5. 错误消息 安全 ... -
第15章 安全(1)
2009-05-26 19:53 98215.1. 概述 Seam安全API为你基于Seam的 ... -
第14章 Seam 和 JBoss 规则
2009-05-26 19:50 1431第14章 Seam 和 JBoss 规则 Seam使从 ... -
第13章 Seam 应用程序框架
2009-05-26 19:49 1403第13章 Seam 应用程序框架 Seam真正地使通过 ...
相关推荐
第1章 Windows应用程序开发入门..........................................................................................16 1.1 第一个实例程序...............................................................
三相异步电动机的起动通常包括直接起动和降压起动,如Y-Δ起动、自耦变压器降压起动等,以减小起动电流。反转可以通过改变定子绕组的相序实现。 【调速方法】 调速方法包括改变电源频率(变频调速)、改变定子电压...
第十一章.事件和委托 #### 核心概念:事件与委托 本章节重点介绍了面向对象编程语言C#中的两个关键概念——事件和委托。这两个概念对于构建复杂的软件系统尤其重要,它们能够帮助开发者实现对象间的通信,同时确保...
第 1 章 初识 Express .......................................................................................................................1 1.1 JavaScript 革命 .........................................
第 6 章 创建和管理用户数据库 第 7 章 装入和卸下数据库 第 8 章 分布式事务管理 第 9 章 创建和使用段 第 10 章 使用 reorg 命令 第 11 章 检查数据库一致性 第 12 章 制定备份和恢复计划 第 13 章 备份和恢复用户...
【计算机网络第3章知识点详解】 1. 物理层是计算机网络的底层,它不直接涉及具体的物理设备,如电缆或接口,而是提供一个在物理媒体上传输原始比特流的逻辑连接。这个物理媒体可以是双绞线、光纤、无线等。 2. ...
第二章 SOPC Builder开发环境......................................................................................................8 2.1 创建Quartus II工程..................................................
第二章 缓冲区 ...................................................................................................................... 22 2.1 缓冲区基础 ....................................................
《数字电子技术基础》第七章主要探讨了集成计数器这一关键主题,集成计数器在现代电子系统中扮演着重要角色,因其功能多样、通用性好、能耗低、速度快和可扩展性强等特点,被广泛应用于各种数字电路设计中。...
第1 章Linux操作系统概述................... .......................................................................... 2 1.1 Linux发展历史........................................................ 2 ...
这一技术在多种应用中都有所应用,如电炉温度控制、灯光亮度调节以及异步电机的软启动和速度控制。 相控式交流调压电路主要利用晶闸管等半导体器件的相位控制来调整输出电压。例如,在异步电机的软启动中,这种电路...
如果你希望更深入地学习或复习这四章内容,可以依次查看压缩包内的“第一章.pdf”、“第二章.pdf”、“第三章.pdf”和“第四章.pdf”。通过仔细研究这些思维导图,你可以巩固已学知识,查漏补缺,并为后续章节的学习...
第一章概论 ..............1 ...第十二章远程过程调用.............249 12.1 引言........249 12.2 远程过程调用模型......249 12.3 传统过程调用和远程过程调用的比较.....250 12.4 远程过程调用的...
第二十二章 重复中断定时器0~3 第二十三章 系统节拍定时器0~3 第二十四章 脉宽调制器 第二十五章 电机控制PWM 第二十六章 正交编码接口(QEI) 第二十七章 实时时钟和备用寄存器 第二十八章 看门狗定时器 第二十九章 ...
第十二章HPL程序实例剖析. . . . . . . . . . . . . . . . . . 117 参考文献. . . . . . . . . . . . . . . . . . . . . . . . . .119 附录一并行程序开发工具与高性能程序库. . . . . . . . . . . .121 A.1 BLAS...
JavaScript和jQuery是Web开发中的重要工具,用于创建交互式的网页和动态内容。在这个18级在校生的上机作业中,我们看到他正通过实践来深入理解和应用这两门技术。以下将详细介绍JavaScript和jQuery的一些核心知识点...
2. 第二章无线技术协议............... PAGEREF _TOC120615571 \H 27 2.1 概述........ PAGEREF _TOC120615572 \H 27 2.2 频段及信道分配.... PAGEREF _TOC120615573 \H 27 2.3 发射机特性............. PAGEREF _...