关于在父页面中使用JSF 2.0复合组件,我有一个概念性的思维模块 . 我理解如何为复合组件的操作实现ActionListener(和其他),但是如何为父页面使用它?例如,我希望我的登录复合组件执行身份验证,完成后,通过一个事件(ActionListener?)通知父页面的辅助bean来进行一些UI初始化工作 . 这里的关键是登录组件会说,“嘿,我已经完成了,用户也很好 . 轮到你了 . ”
在此先感谢您的帮助 .
和平 .
克里斯
我发现你可以通过 composite component + custom component type + ActionSource2 + system events 找到一种方法 .
在组合集的接口中,组件类型(未定义时,实现(Mojarra或MyFaces)使用默认组件类型 .
<cc:interface componentType="example.Login"> <cc:attribute name="text" type="java.lang.String"/> <cc:attribute name="actionExpression" method-signature="void method()"/> </cc:interface> <cc:implementation> <p> <h:outputLabel value="User"/> <h:inputText id="user"/> </p> <p> <h:outputLabel value="Password"/> <h:inputSecret id="password"/> </p> </cc:implementation>
此组件类型是实现NamingContainer的java类(UINamingContainer是实现此接口的组件的子类) . 接下来,您必须实现ActionSource2,以便在验证用户时生成操作事件 .
验证必须在验证用户和密码组件之后(不是您的验证,而是JSF PROCESS VALIDATIONS) . 为了知道验证何时发生,我们使用系统事件 .
这是自定义组件的代码示例 . 该类实现ActionSource2接口的方法并覆盖广播以处理ActionEvent . 我在Mojarra中使用了一些特定的类(因为ActionSource和ActionSource2之间的遗留问题) .
@FacesComponent("example.Login") //Component type in the composite @ListenerFor(systemEventClass=PostValidateEvent.class) //Event to listen for user and password verification public class LoginComponent extends UINamingContainer implements ActionSource2{ @Override public void processEvent(ComponentSystemEvent event) throws AbortProcessingException { if(event instanceof PostValidateEvent){ System.out.println("post validate"); } super.processEvent(event); String user=(String) ((HtmlInputText)findComponent("user")).getValue(); String password=(String) ((HtmlInputSecret)findComponent("password")).getValue(); System.out.println("user: "+user); System.out.println("password: "+password); //a simple logic for verification if(user != null && user.equals("victor") && password != null && password.equals(user)){ System.out.println("user ok"); queueEvent(new ActionEvent(this)); } } private MethodExpression exp; @Override public MethodExpression getActionExpression() { return exp; } @Override public void setActionExpression(MethodExpression action) { exp=action; } @Override public MethodBinding getAction() { return exp != null ? new MethodBindingMethodExpressionAdapter(exp): null; } @Override public void setAction(MethodBinding action) { setActionExpression(new MethodExpressionMethodBindingAdapter(action)); } private MethodBinding actionListener; @Override public MethodBinding getActionListener() { return actionListener; } @Override public void setActionListener(MethodBinding actionListener) { this.actionListener=actionListener; } private boolean i; @Override public boolean isImmediate() { return i; } @Override public void setImmediate(boolean immediate) { this.i=immediate; } List<ActionListener> listeners=new LinkedList<ActionListener>(); @Override public void addActionListener(ActionListener listener) { listeners.add(listener); } @Override public ActionListener[] getActionListeners() { return listeners.toArray(new ActionListener[0]); } @Override public void removeActionListener(ActionListener listener) { listeners.remove(listener); } @Override public void broadcast(FacesEvent event) throws AbortProcessingException { super.broadcast(event); if (event instanceof ActionEvent) { FacesContext context = getFacesContext(); MethodBinding binding = getActionListener(); if (binding != null) { binding.invoke(context, new Object[] { event }); } ActionListener listener = context.getApplication().getActionListener(); if (listener != null) { listener.processAction((ActionEvent) event); } } } }
这是使用页面中的代码:
<ez:login actionExpression="#{bean.logged}"/>
1 回答
我发现你可以通过 composite component + custom component type + ActionSource2 + system events 找到一种方法 .
在组合集的接口中,组件类型(未定义时,实现(Mojarra或MyFaces)使用默认组件类型 .
此组件类型是实现NamingContainer的java类(UINamingContainer是实现此接口的组件的子类) . 接下来,您必须实现ActionSource2,以便在验证用户时生成操作事件 .
验证必须在验证用户和密码组件之后(不是您的验证,而是JSF PROCESS VALIDATIONS) . 为了知道验证何时发生,我们使用系统事件 .
这是自定义组件的代码示例 . 该类实现ActionSource2接口的方法并覆盖广播以处理ActionEvent . 我在Mojarra中使用了一些特定的类(因为ActionSource和ActionSource2之间的遗留问题) .
这是使用页面中的代码: