2

私は JSF に比較的慣れておらず、現在の JSF 2 アプリケーションがどのように設計されているかを学ぼうとしています。ajax を使用する単一ページ アプリケーションへの参照を見てきました。誰かが使用されたテクニックのいくつかについて私に記入したり、モデルや本を紹介したりできますか? 私が見た本 (JSF Complete Reference など) は、基本的な技術問題には適していますが、現在の設計手法の情報源を見つけることができません。

ありがとうデイブ

4

1 に答える 1

5

シングル ページ アプリケーションを実装するには、ページのどの部分をレンダリングするかを指定する必要があります。これは、作成、編集、リストなどのブール フラグを使用して実行できます。たとえば、次を参照してください(関連するコードのみ

<h:body>
    <h:form rendered="#{userController.stateManager.create}">
        <h:panelGroup rendered="#{not empty facesContext.messageList or userController.stateManager.failure}">
            <!--render error message right here-->
        </h:panelGroup>
        <div>
            <label>#{messages['br.com.spa.domain.model.User.name']}</label>
            <h:inputText value="#{user.name}"/>
        </div>
        <h:commandButton action="#{userController.create}">
             <f:ajax execute="@form" render="@all"/>
             <f:actionListener type="br.com.spa.web.faces.listener.StateManagerActionListener" />
             <f:setPropertyActionListener target="#{userController.stateManager.create}" value="true"/>
             <f:setPropertyActionListener target="#{userController.user}" value="#{user}" />
        </h:commandButton>
    </form>
</h:body>

フラグ create が true の場合にフォームがレンダリングされることに注意してください - 上記の 2 行目を参照してください。フラグをラップするには、次のように StateManager という名前のクラスを作成します

/**
  * I am using lombok, which takes care of generating our getters and setters. For more info, please refer http://projectlombok.org/features/index.html
  */
@Setter @Getter
public class StateManager {

    private boolean create;
    private boolean edit;
    private boolean list;

}

ここでは、1 つのページのみを使用しているため、ViewScoped マネージド Bean を使用する必要があります。これにより、同じビューにいる限りマネージド Bean のスコープがアクティブに保たれます。それはシングル ページ アプリケーションですか? したがって、ナビゲーションはありません。これを念頭に置いて、マネージド Bean を作成しましょう。

@ManagedBean
@ViewScoped
public class UserController implements StateManagerAwareManagedBean {

    private @Inject UserService service;

    private @Getter @Setter stateManager = new StateManager();

    private @Getter @Setter List<User> userList = new ArrayList<User>();
    private @Getter @Setter User user;

    @PostConstruct
    public void initialize() {
        list();
    }

    public void create() {
        service.persist(user);

        stateManager.setCreate(false);
        stateManager.setList(true);
        stateManager.setSuccess(true);
    }

    public void edit() {
        service.merge(user);

        stateManager.setEdit(false);
        stateManager.setList(true);
        stateManager.setSuccess(true);
    }

    public void list() {
        userList = service.list();

        stateManager.setList(true);
    }

}

アクション メソッドごとに、ページのどの部分をレンダリングするかを定義します。たとえば、フォームが処理され、JSF ライフサイクル全体がカバーされたとします。これは、値が正常に変換および検証され、アクション メソッドが呼び出されたことを意味します。例として作成アクション メソッド (上記参照) を使用すると、フォームが変換および検証されたため、作成フラグを false に設定します。さらに、リストと成功フラグの両方を true に設定します。これは、ページのリストをレンダリングする必要があり、フォームが正常に処理されたことを示します。このフラグを使用して、次のような「ユーザー作成」などを表示できます。

<h:panelGroup rendered="#{userController.stateManager.success}">
    #{messages['default.created.message']}
</h:panelGroup>

ここで、最初に呼び出されたときにページのどの部分をレンダリングする必要があるかについて説明しましょう。ご存じないかもしれませんが、@PostConstruct アノテーションが付けられた void メソッドが最初に呼び出されます。したがって、ページのどの部分をレンダリングするかを定義します。この例では、リスト フラグを true に設定してバッキング リストを設定する list メソッドを呼び出します。

@PostConstruct
public void initialize() {
    list();
}

最後に、 h:commandButton 内にネストされた次の順序を確認しましょう。

<h:commandButton action="#{userController.create}">
    <f:ajax execute="@form" render="@all"/>
    <f:actionListener type="br.com.spa.web.faces.listener.StateManagerActionListener" />
    <f:setPropertyActionListener target="#{userController.stateManager.create}" value="true"/>
    <f:setPropertyActionListener target="#{userController.user}" value="#{user}" />
</h:commandButton>

まず、ActionListener (ここでは StateManagerActionListener と呼びます) を呼び出す必要があります。これは、StateManager のリセットを処理します (以下のコード)。h:commandButton 内で定義された順序が呼び出される順序であるため、フラグを制御するように設計された他の setPropertyActionListener の前に最初に呼び出す必要があります。これを覚えておいてください。

public class StateManagerActionListener implements ActionListener {

    public void processAction(ActionEvent e) throws AbortProcessingException {
        Map<String,Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
        for(Map.Entry<String,Object> entry: viewMap.entrySet()) {
            if(entry.getValue() instanceof StateManagerAwareManagedBean) {
                ((StateManagerAwareManagedBean) entry.getValue()).setStateManager(new StateManager());
            }
        }
    }

}

StateManagerAwareManagedBean - ViewScoped Managed Bean で使用されます。これにより、 ActionListener で1 つずつリセットする代わりに、任意の ManagedBean の StateManager をリセットできます。次のように定義されます。

public interface StateManagerAwareManagedBean {

    StateManager getStateManager();
    void setStateManager(StateManager stateManager);

}

次に、ActionListener を定義した後、setPropertyActionListener を使用して、ビューの囲み部分を制御するフラグを true に設定します。フォームは変換および検証されないはずなので、これが必要です。したがって、アクション メソッドでは、前に説明したように、このフラグを false に設定します。

いくつかのメモ

  • ユーザーは RequestScoped ManagedBean としてマークされているため、スコープが短いため、ManagedProperty を使用して ViewScoped に注入することはできません。この問題を克服するために、 <f:setPropertyActionListener target="#{userController.user}" value="#{user}"> を使用して値を設定しました - フォームを参照してください
  • この例では、適切なアプリケーション サーバーを必要とする JEE 機能を使用しています。詳細については、http://docs.oracle.com/javaee/6/tutorial/doc/ を参照してください
  • ManagedBean は、コントローラー、DTO などのさまざまな役割を果たすことができます。それがコントローラーの役割を果たすとき、私はその名前のサフィックスにコントローラーを付けることを好みます。詳細については、http://java.dzone.com/articles/making-distinctions-betweenを参照してください。
于 2014-03-30T05:04:47.610 に答える