基于jsf的项目_JSF基于事件的交流:新派方法

基于jsf的项目

在上一篇文章中 ,我们学习了基于Observer / Event Listener和Mediator模式的基于事件的通信。 由于它们的缺点,我想展示基于事件的通信的更有效方法。 我们将从Google Guava EventBus开始,最后以CDI (Java EE平台的上下文和依赖注入)结束。

番石榴EventBus

Google Guava库具有有用的package eventbus 。 EventBus类允许组件之间进行发布-订阅式通信,而无需组件之间进行显式注册。 因为我们开发Web应用程序,所以应该将此类的实例封装在有作用域的bean中。

让我们编写EventBusProvider bean。

public class EventBusProvider implements Serializable {private EventBus eventBus = new EventBus("scopedEventBus");public static EventBus getEventBus() {// access EventBusProvider beanELContext elContext = FacesContext.getCurrentInstance().getELContext();EventBusProvider eventBusProvider =(EventBusProvider) elContext.getELResolver().getValue(elContext, null, "eventBusProvider");return eventBusProvider.eventBus;}
}

我仅以一个示例来演示Guava EventBus的所有主要功能。 让我们编写以下事件层次结构:

public class SettingsChangeEvent {}public class LocaleChangeEvent extends SettingsChangeEvent {public LocaleChangeEvent(Object newLocale) {...}
}public class TimeZoneChangeEvent extends SettingsChangeEvent {public TimeZoneChangeEvent(Object newTimeZone) {...}
}
下一步很简单。 要接收事件,对象(bean)应公开一个公共方法,该方法以@Subscribe批注进行批注,该方法接受具有所需事件类型的单个参数。 该对象需要将自身传递给EventBus实例的register()方法。 让我们创建两个bean:
public MyBean1 implements Serializable {@PostConstructpublic void initialize() throws Exception {EventBusProvider.getEventBus().register(this);}@Subscribepublic void handleLocaleChange(LocaleChangeEvent event) {// do something}@Subscribepublic void handleTimeZoneChange(TimeZoneChangeEvent event) {// do something}
}public MyBean2 implements Serializable {@PostConstructpublic void initialize() throws Exception {EventBusProvider.getEventBus().register(this);}@Subscribepublic void handleSettingsChange(SettingsChangeEvent event) {// do something}
}

要发布事件,只需将事件对象提供给EventBus实例的post()方法。 EventBus实例将确定事件的类型,并将其路由到所有已注册的侦听器。

public class UserSettingsForm implements Serializable {private boolean changed;public void localeChangeListener(ValueChangeEvent e) {changed = true;        // notify subscribersEventBusProvider.getEventBus().post(new LocaleChangeEvent(e.getNewValue()));}public void timeZoneChangeListener(ValueChangeEvent e) {changed = true;        // notify subscribersEventBusProvider.getEventBus().post(new TimeZoneChangeEvent(e.getNewValue()));}public String saveUserSettings() {...if (changed) {// notify subscribersEventBusProvider.getEventBus().post(new SettingsChangeEvent());return "home";}}
}
Guava EventBus允许创建对许多不同事件做出React的任何侦听器,只需使用@Subscribe注释许多方法即可。 侦听器可以利用现有事件层次结构。 因此,如果侦听器A正在等待事件A,并且事件A具有名为B的子类,则此侦听器将接收两种类型的事件:A和B。在我们的示例中,我们发布了三个事件:SettingsChangeEvent,LocaleChangeEvent和TimeZoneChangeEvent。 MyBean1中的handleLocaleChange()方法将仅接收LocaleChangeEvent。 方法handleTimeZoneChange()将仅接收TimeZoneChangeEvent。 但是,请查看MyBean2中的handleSettingsChange()方法。 它将接收所有三个事件!
如您所见,仍然需要手动注册(EventBusProvider.getEventBus()。register(this)),并且在上一篇文章中提到的作用域bean的问题仍然存在。 我们应该注意EventBusProvider的作用域和发布/订阅者bean的作用域。 但是,正如您可能还会看到的,与Mediator模式相比,我们有了一些改进:不需要特殊的接口,没有固定定义订户的方法名,也可以进行多侦听器,不费力气来管理注册的实例,等等。但并非最不重要的是-异步AsyncEventBus和对DeadEvent的订阅(用于侦听没有侦听器调度的任何事件-便于调试)。 请按照本指南将现有的基于EventListener的系统转换为基于EventBus的系统。
CDI(上下文和依赖注入)
每个符合JEE 6的应用服务器均支持CDI(JSR-299规范)。 它定义了一组补充服务,可帮助改善应用程序代码的结构。 CDI的最著名实现是OpenWebBeans和JBoss Weld 。 CDI中的事件允许bean完全不依赖地进行交互。 事件生产者引发事件,这些事件由容器传递给事件观察者。 这个基本架构听起来像是熟悉的Observer / Observable模式,但是有很多好处。
  • 事件生产者和事件观察者彼此分离。
  • 观察者可以指定“选择器”的组合来缩小他们将接收的事件通知的范围。
  • 可以立即或延迟通知观察者,直到当前事务结束为止。
  • 使用条件观察者方法进行作用域定义时不会感到头痛(还记得作用域bean和Mediator / EventBus的问题吗?)。
条件观察者方法仅在声明观察者方法的bean范围当前处于活动状态时才允许获取已经存在的bean实例,而无需创建新的bean实例。 如果观察者方法不是有条件的,则将始终创建相应的bean。 您很灵活!
我认为,CDI事件机制是进行基于事件的交流的最佳方法。 这个问题很复杂。 让我们仅显示基本功能。 观察者方法是带有参数@Observes的bean方法。
public MyBean implements Serializable {public void onLocaleChangeEvent(@Observes Locale locale) {...}
}

如果观察者方法仅对限定的事件感兴趣,则事件参数也可以指定限定符-这些是具有那些限定符的事件。

public void onLocaleChangeEvent(@Observes @Updated Locale locale) {...
}

事件限定符只是使用@Qualifier定义的普通限定符。 这是一个例子:

@Qualifier
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface Updated {}

事件生产者使用参数化Event接口的实例来触发事件。 该接口的实例通过注入获得。 生产者通过调用Event接口的fire()方法并传递事件对象来引发事件。

public class UserSettingsForm implements Serializable {@Inject @Any Event<Locale> localeEvent;public void localeChangeListener(ValueChangeEvent e) {// notify all observerslocaleEvent.fire((Locale)e.getNewValue());}
}
容器调用所有观察者方法,并将事件对象作为事件参数的值传递。 如果任何观察者方法引发异常,则容器将停止调用观察者方法,并且该异常将由fire()方法重新抛出。 上面的@Any批注充当所有限定符的别名。 您会看到,无需手动注册观察员。 简单? 在注入点指定其他限定词也很简单:
// this will raise events to observers having parameter @Observes @Updated Locale
@Inject @Updated Event<Locale> localeEvent;
您还可以具有多个事件限定符。 该事件被传递给每个具有事件参数的观察者方法,该事件参数可以分配事件对象,并且除了与事件注入点指定的事件限定符匹配的事件限定符之外,没有任何事件限定符。 观察者方法可能具有其他参数,这些参数是注入点。 例:
public void onLocaleChangeEvent(@Observes @Updated Locale locale, User user) {...
}

动态指定限定符怎么办? CDI允许通过AnnotationLiteral获得适当的限定符实例。 这样,我们可以将限定符传递给Event的select()方法。 例:

public class DocumentController implements Serializable {Document document;@Inject @Updated @Deleted Event<Document> documentEvent;public void updateDocument() {...// notify observers with @Updated annotationdocumentEvent.select(new AnnotationLiteral<Updated>(){}).fire(document);}public void deleteDocument() {...// notify observers with @Deleted annotationdocumentEvent.select(new AnnotationLiteral<Deleted>(){}).fire(document);}
}
让我们谈谈“条件观察者方法”。 默认情况下,如果当前上下文中没有观察者实例,则容器将实例化观察者以向其传递事件。 这种行为并不总是令人满意的。 我们可能只想将事件传递给当前上下文中已经存在的观察者实例。 通过在@Observes批注中添加receive = IF_EXISTS来指定条件观察者。
public void onLocaleChangeEvent(@Observes(receive = IF_EXISTS) @Updated Locale locale) {...
}
在此处阅读有关范围和上下文的更多信息。 在这篇简短的文章中,我们不能再谈论更多功能,例如“具有成员的事件限定符”和“事务观察者”。 我想鼓励大家开始学习CDI。 玩得开心!
参考: JSF中基于事件的通信。 新学派的方法 。 来自我们的JCG合作伙伴 Oleg Varaksin,来自“软件开发思想”博客。

翻译自: https://www.javacodegeeks.com/2012/07/jsf-event-based-communication-new.html

基于jsf的项目

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/354015.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 天文软件,新闻|开源新闻速递:天文软件 Stellarium 0.15.0 发布

今日关注Stellarium 0.15.0 发布。这是一款全世界最棒的免费、开源、跨平台的天文软件应用&#xff0c;用户可以通过该软件来观看实时的星星、行星还有星云。最新版本进行了非常多的功能完善&#xff0c;修复了若干bug&#xff0c;新增了许多新特性。比如更新了AstroCalc工具&a…

linux javaweb环境单价,linux(centos)下Java Web环境开发

一、安装jdk百度搜索jdk&#xff0c;进入http://www.oracle.com/technetwork/java/javase/downloads/index.html找到自己需要版本的jdk的Linux压缩包&#xff1b;复制出这个压缩包的下载地址(尽量先点击下载&#xff0c;然后在下载的界面复制出资源的链接)在服务器的合适位置创…

带有Java Util日志记录的Java 8延迟调用

在博客文章“在Log4j2中更好地执行非日志记录器调用”中 &#xff0c;我介绍了可以在Log4j 2中使用的方法&#xff0c;这些方法可以减少或避免在基于指定日志级别实际上根本未记录的日志语句中调用方法。 作为讨论的一部分&#xff0c;我介绍了Log4j 2对使用lambda表达式的基于…

python对象分类

1 python对象分类 所有的Python对象都拥有三个特性&#xff1a;身份&#xff0c;类型和值 身份&#xff1a; 每一个对象都有一个唯一的身份标识自己。任何对象的身份可以使用内建函数id()来得到。这个值可以被认为是该对象的内存地址类型&#xff1a; 对象的类型决定了对象可以…

怎样用u盘linux安装ntp协议,电脑中怎么配置NTP服务

NTP服务器是用来使计算机时间同步化的一种协议&#xff0c;可提供高精准度的时间校正&#xff0c;而且能通过加密确认来防止恶毒的协议攻击。下面让学习啦小编为大家介绍如何在电脑中配置NTP服务来实现局域网内设备的时间同步。电脑中怎么配置NTP服务1、先关闭Windows系统自带的…

SetGID 权限

一、SetGID针对文件的作用 1、只有可执行的二进制程序才能设置SGID权限 2、命令执行者要对该程序拥有 x &#xff08;执行&#xff09;权限 3、命令执行在执行程序的时候&#xff0c;组身份升级为该程序的属组 4、SetGID权限同样只在该程序执行过程中有效&#xff0c;也就是说组…

nosql的数据服务_使用NoSQL实现实体服务–第2部分:合同优先

nosql的数据服务现在该开始使用NoSQL项目对SOA实体服务进行编码了&#xff0c;并且正如我所承诺的&#xff0c;我将从Web服务的合同开始。 看一下本系列的第1部分 。 这种从Web服务合同定义开始的技术是面向服务的体系结构实现的“合同优先”方法的核心&#xff0c;并具有许多技…

weblogic双机热备部署linux,WebLogic应用在集群环境下的一些基本知识【转载】

4.2.1 基本概念1&#xff0e;硬件的cluster和WebLogic的cluster不是一回事&#xff0c;硬件做的是冷备份&#xff0c;对用户的session&#xff0c;用户请求的负载均衡等的处理是做不到 的&#xff0c;而且一般硬件的双机热备也不是时时的备份&#xff0c;而是间隔一段时间再将主…

vmware中centos6.4突然无法进入图形界面解决方法

今天遇到vmvare中centos6.4进度条走完了仍然没有进入图形界面&#xff0c;在网上找到了解决方法记录如下&#xff1a; 1. 按CtrlAltF5并输入root账号密码进入命令界面 2. vim /etc/inittab 打开/etc/inittab文件&#xff0c;并将文件最后id:5改为id:3&#xff0c;即将运行等级…

教程:正确的SLF4J日志记录用法以及如何检查它

SLF4J是一个非常流行的日志记录外观&#xff0c;但是&#xff0c;就像我们使用的所有库一样&#xff0c;我们有可能以错误的方式或至少以非最佳方式使用它。 在本教程中&#xff0c;我们将列出常见的日志记录错误以及如何使用FindBugs检测到它们。 我们还将在相关时提及PMD和S…

linux逐行扫描,FFmpeg怎么区分识别视频是逐行扫描还是隔行扫描

最近遇到要识别隔行扫描的视频加以特殊转码处理的问题。google了一番以后找到两个解决的方式&#xff0c;记录一下。方法一&#xff1a;使用隔行扫描检查滤镜idet区分隔行扫描和逐行扫描ffmpeg -filter:v idet \ -frames:v 100 \ -an \ -f rawvideo -y /dev/null \ -i 351.mp4 …

JDBC学习笔记 day1

JDBC的基本概念&#xff1a; JDBC就是java database connectivity&#xff0c;即java数据库连接。 JDBC主要完成的几个任务分别为 与数据库建立一个连接  向数据库发送SQL语句  处理数据库返回的结果JDBC的作用&#xff1a; 将java程序语言编写出来的程序&#xff0c;与数据…

稀疏矩阵的转置c语言程序,程序有问题求大神,稀疏矩阵转置

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#include #define N 100typedef int DataType;typedef struct{int i,j;DataType v;}TriTupleNode;typedef struct{TriTupleNode data[N];int m,n;int t;}TriTupleTable;void TransMatrix(TriTupleTable *b,TriTupleTable *a);void …

jsf组件不显示_JSF组件库–质量不只是零缺陷

jsf组件不显示自从我上次查看三个主要JSF组件库的质量以来已经有一段时间了。 在2009年12月&#xff0c;我开始比较RichFaces&#xff0c;Primefaces和ICEfaces的整体软件质量 。 从那时起&#xff0c;事情发生了变化&#xff0c;从现在开始&#xff0c;我想重新评估和更新它。…

linux安装mysql(shell一键安装)

1. 相关文件&#xff08;install_mysql.sh、my.cnf、mysqld相关内容在文中最后面&#xff09; 2. 将上面的文件上传到linux服务器某一目录下 3.给install_mysql.sh赋执行权限 # chmod x instll_mysql.sj 4. 执行install_mysql.sh # ./install_mysql.sh 5. 验证 6. install_mysq…

c语言编译时检查逻辑错误吗,C语言陷阱与技巧20节,自定义“编译时”assert方法,在代码编译阶段检查“逻辑”错误...

在C语言程序开发中&#xff0c;程序员写代码时应该考虑的“面面俱到”&#xff0c;这样才能写出功能稳定的程序。例如&#xff0c;在实现 open() 函数时&#xff0c;先完成它的功能固然是重要的&#xff0c;但是程序员还需要考虑各种“意外”&#xff0c;比如下面这种情况。假设…

springboot 多个sevice类实现同一接口的调用

参考页面&#xff1a;http://blog.csdn.net/xiao190128/article/details/54890759/&#xff1b;感谢分享 service 是有用的相当于 xml配置中得bean id service 也可以不指定 不指定相当于 bean id com. service.service 就是这个类的全限定名,表示给当前类命名一个别名&a…

影场与属性访问器界面

卡尔迪亚&#xff08;Carl Dea&#xff09;最近跟踪了我的一篇名为“ 保存内存”的博客文章&#xff01; 为属性使用阴影字段 。 在他的博客中&#xff0c;他建议使用一个称为“属性访问器”的接口来消除使用阴影字段所需的大量样板代码。 卡尔还提到他尚未用大量数据测试他的方…

[ZJOI2012]数列

超级水的题还wa了一次 首先很容易发现其实就只有两个值并存 然后 要注意把数组初始化啊。。。可能后面有多余的元素&#xff08;对拍的时候由于从小到大就没跑出错&#xff09; #include <bits/stdc.h> using namespace std; int a[170],b[170],a1[170],a2[170],x1[170],…

在c语言中,可以使用动态内存分配技术定义元素个数可变的数组,C语言复制在线考题1精选.doc...

C语言复制在线考题1精选窗体顶端《C语言程序设计208304》综合测试返回测验列表大项 1 / 2 - 单项选择题60.0/ 70.0 分本大题共35道&#xff0c;每题2分&#xff0c;共计70分&#xff0c;答错、不答均不得分。题目 1 / 552.0/ 2.0 分有字符数组 a[80]和 b[80]&#xff0c;则正确…