如何为所有 UIInput 注册(组件)SystemEventListener [英] How to register a (Component)SystemEventListener for all UIInputs

查看:19
本文介绍了如何为所有 UIInput 注册(组件)SystemEventListener的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用一个自定义 SystemEventListener 来注册 UIInput 类型的所有实例并对它们的 postValidate-Events 做出反应.根据我在网上找到的一个例子,我设法通过在 faces-config.xml 中注册它来运行 HtmlInputText ,如下所示:

I am trying to have a custom SystemEventListener that registers for all instances of type UIInput and reacts to their postValidate-Events. Based on an example I found on the web I managed to get one running for HtmlInputText by registering it in the faces-config.xml as follows:

<system-event-listener>
   <source-class>javax.faces.component.html.HtmlInputText</source-class>
   <system-event-class>javax.faces.event.PostValidateEvent</system-event-class>
   <system-event-listener-class>com.ourcompany.ourproduct.validators.inputPostValidationListener</system-event-listener-class>
 </system-event-listener>

然后我尝试 1) 将其扩展到一般适用于 UIInputs 和 2) 使用 @ListenerFor 注释,但我似乎无法让其中任何一个工作.

I then tried to 1) broaden this to work for UIInputs in general and to 2) use the @ListenerForannotation, but I just can't seem to get either of it to work.

对于 1) 我真的找不到任何示例或文档,所以我只是尝试了 a) 定义多个源类标签或 b) 使用 javax.faces.component.UIInput 作为源类.都没有用.

for 1) I couldn't really find any examples or documentation, so i just tried around by a) defining multiple source-class-tags or by b) using javax.faces.component.UIInput as source-class. Neither worked.

对于 2) 我尝试过

@ListenerFor(systemEventClass = PostValidateEvent.class, sourceClass = UIInput.class)

既不适用于 UIInput,也不适用于 html.HtmlInputText.

which worked neither for UIInput nor for html.HtmlInputText.

现在,当我为所有其他类型的 HTML 输入复制相同的 XML 配置时,这确实有效,但它只会使 xml 变得混乱,而且对我来说似乎很烦人.

Now, when I duplicate the same XML-configuration for all the other types of HTML-Inputs, this does the trick, but it just clutters up the xml and altogether seems quite annoying to me.

所以问题是:我通常在@ListenerFor 注释上做错了什么吗?对哪些源类可能有限制,即为什么我不能使用更通用的 UIInput?有没有比重复 XML 更有效的方法来为所有这些不同的输入注册监听器?最后:我宁愿实现 ComponentSystemEventListener.假设上述问题已经解决,我只需更改implements-Statement 并相应地实现抽象processEvent,对吗?在这种情况下,它会工作相同还是注册/xml-config 不同(例如,可能 而不是 ?

So the question is: Am I generally doing something wrong with the @ListenerFor annotation? Is there a restriction on which source-classes are possible, i.e. why can't I use the more generic UIInput? Is there a more efficient way to register the listener for all those different inputs than repeating the XML? And finally: I'd rather like to implement ComponentSystemEventListener. Assuming that the above problem was resolved, I'd just change the implements-Statement and implement the abstract processEvent accordingly, right? Would that work just the same or is the registration/xml-config different in this case (e.g. maybe <component-system-event-listener> instead of just <system-event-listener>?

(以及作为后记:是我个人还是很难在网络上找到此类内容的任何非平凡示例?)

(and as an after-note: is it just me or is it kind of hard to find any non-trivial examples for this kind of stuff on the web?)

推荐答案

@ListenerFor 应该设置在 UIComponentRenderer 上> 实现,而不是独立的 SystemEventListener 实现.另请参阅 javadoc(重点是我的):

The @ListenerFor is supposed to be set on an UIComponent or Renderer implementation, not on a standalone SystemEventListener implementation. See also the javadoc (emphasis mine):

默认实现必须支持将此注释附加到 UIComponentRenderer 类. 在这两种情况下,此处描述的注释处理必须在Application.createComponent() 的任何变体的实现,并且必须在从 createComponent() 返回 UIComponent 实例之前完成.注释处理必须根据语义等价于以下的算法进行.

The default implementation must support attaching this annotation to UIComponent or Renderer classes. In both cases, the annotation processing described herein must commence during the implementation of any variant of Application.createComponent() and must complete before the UIComponent instance is returned from createComponent(). The annotation processing must proceed according to an algorithm semantically equivalent to the following.

...

为了拥有一个不特定于 UIComponentRenderer 的全局监听器,最好的办法是创建和注册一个 PhaseListener将侦听器订阅到视图根目录.

In order to have a global listener, not specific to an UIComponent or Renderer, your best bet is creating and registering a PhaseListener which subscribes the listener to the view root.

public class PostValidateListener implements PhaseListener {

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.PROCESS_VALIDATIONS;
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        event.getFacesContext().getViewRoot()
            .subscribeToViewEvent(PostValidateEvent.class, new InputPostValidationListener()); // Capitalize class name?
    }

    @Override
    public void afterPhase(PhaseEvent event) {
        // NOOP.
    }

}

要使其运行,请在 faces-config.xml 中按如下方式注册:

To get it to run, register it as follows in faces-config.xml:

<lifecycle>
    <phase-listener>com.example.PostValidateListener</phase-listener>
</lifecycle>

您甚至可以将 InputPostValidationListener 本身设为 PhaseListener.

You can even make your InputPostValidationListener itself a PhaseListener.

public class InputPostValidationListener implements PhaseListener, SystemEventListener {

    @Override
    public void beforePhase(PhaseEvent event) {
        event.getFacesContext().getViewRoot().subscribeToViewEvent(PostValidateEvent.class, this);
    }

    // ...
}

这篇关于如何为所有 UIInput 注册(组件)SystemEventListener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆