これを達成できる 1 つの方法は、複合コンポーネント + カスタム コンポーネント タイプ + ActionSource2 + システム イベントを使用することです。
コンポジットのインターフェースでコンポーネントタイプを設定します (定義されていない場合、実装 (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 プロセスの検証)。検証がいつ行われたかを知るために、システム イベントを使用します。
これは、カスタム コンポーネントのコードの例です。このクラスは、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}"/>