26

明確に定義されたインターフェースを持つアプリケーションがあります。モジュールの解決に CDI を使用し (具体的には、API インターフェイスで Instance<> 注入ポイントを使用してモジュールを解決します)、インターフェイスを介してさまざまなデータを問題なくやり取りします。私は意図的に API と実装を分離し、密結合を避けるためにモジュールは API からのみ継承し、アプリケーションは実行時の依存関係と API を介して行われるデータの受け渡しを通じてのみモジュールを認識します。アプリケーションは、jar を WEB-INF/lib フォルダーにドロップしてアプリ サーバーを再起動するだけで追加できるモジュールがなくても正常に動作します。

私が問題に直面しているのは、モジュールにビューの一部を作成させたいということです。そのため、ポータブルな方法で JSF コンポーネントを呼び出すか、モジュールからインクルードを実行して、それを取得します。そのビューをレンダリングします。呼び出したいモジュールは既に解決しており、モジュールのインターフェースへの参照が用意されています。私が最初に考えた方法は、モジュールにビュー テンプレートの場所を提供するように要求する ui:include を実行することでしたが、ビューの解決はアプリケーションから行われるため、意味のある方法でそのクエリに答える方法がわかりません。ライブラリルートではなく、ルート。

エグゼクティブ サマリーは、.xhtml (テンプレート/コンポーネント) ファイルに JSF を使用して、アプリケーションからライブラリへのギャップをジャンプする方法がわからないということです。

CC を使用するのはよいことですが、実行時に特定の CC インスタンスが必要であることをページにハード コードするのではなく、どのように指定すればよいでしょうか?

もちろん、アプリケーション コードを直接呼び出してマークアップを要求することもできますが、これは非常に強引な方法のように思えます。また、マークアップを取得すると、それを評価するように JSF に指示する方法が正確にはわかりません。とはいえ、リソース パスを取得し、マークアップを取得して評価し、完成したマークアップを返すコンポーネントを想像することはできますが、それを実装する方法がわかりません。

可能であれば、モジュール開発者に負荷の高い UIComponent アプローチを強制することは避けたいと思います。つまり、動的な方法で ui:include (または同等のもの) を実行するか、動的な方法で CC を呼び出します。(モジュール開発者の生活を楽にするために必要な場合は、アプリケーションでUIComponentアプローチを一度コーディングしてもかまいません)

これを理解するためにどこを見るべきかについての提案はありますか? (最初に見つけたら、ここに答えを投稿します)

4

3 に答える 3

34

あなたの質問は基本的に、FaceletsビューをJARに含めるにはどうすればよいですか?

ResourceResolverこれを行うには、JARにカスタムを配置します。

public class FaceletsResourceResolver extends ResourceResolver {

    private ResourceResolver parent;
    private String basePath;

    public FaceletsResourceResolver(ResourceResolver parent) {
        this.parent = parent;
        this.basePath = "/META-INF/resources"; // TODO: Make configureable?
    }

    @Override
    public URL resolveUrl(String path) {
        URL url = parent.resolveUrl(path); // Resolves from WAR.

        if (url == null) {
            url = getClass().getResource(basePath + path); // Resolves from JAR.
        }

        return url;
    }

}

これを webappweb.xmlで次のように構成します。

<context-param>
    <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
    <param-value>com.example.FaceletsResourceResolver</param-value>
</context-param>

/META-INF/resources/foo/bar.xhtmlinを持っていると想像してください。random.jarその後、通常の方法でそれを含めることができます

<ui:include src="/foo/bar.xhtml" />

または動的に

<ui:include src="#{bean.path}" />

注: Servlet 3.0 以降の JBoss/JSF 2.0 バージョンでは、ファイルをフォルダーResourceResolverに保持する場合、全体のアプローチは必要ありません。/META-INF/resources上記は、リソース解決ResourceResolverにバグがあるため、Servlet 2.5 以前の JBoss/JSF バージョンでのみ必須です。META-INF

以下も参照してください。

于 2011-06-01T12:21:35.717 に答える
2

ちなみに、CDI (典型的な Java EE 6 コンポーネント モデル) を補完する非常に便利なライブラリである seam はんだ (現在、apache deltaspike に統合されています) を使用している場合は、独自のリソース リゾルバーの実装を避けることができます。

私も jsf アプリケーションのモジュール性を試しました。基本的に、各モジュールが提供するボタンでいっぱいになるツールバーを備えたテンプレート インターフェイスを作成しました。通常、名前付きオブジェクトとして文字列のリストを提供することでこれを行います。

@Produces
@SomethingScoped
@Named("topMenuItems")
public List<String> getTopMenuItems(){
return Arrays.asList("/button1.xhtml", "/button2.xhtml", "/button3.xhtml");
}

各ボタンが jsf アプリケーションの異なるモジュールからどのように取得されるかに注目してください。テンプレート インターフェイスにはパネルが含まれています。

次の方法でマークアップで使用できます(自己責任で;)):

....
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
....
<xy:toolbar>
  <xy:toolbarGroup>
    <c:forEach items="#{topMenuItems}" var="link">
      <ui:include src="#{link}" />
    </c:forEach>
  </xy:toolbarGroup>
</xy:toolbar>
<xy:panel>
  <ui:include src="#{contentPath}"/>
</xy:panel>

これはツールバーとコンテンツ パネルでした。

単純なボタンまたはビューの定義は次のようになります。

<ui:composition ...>
    <xy:commandButton actionListener="#{topMenuController.switchContent()}"
        value="Test" id="testbutton" />
</ui:composition>

このアーティファクトにview1.xhtmlという名前を付けましょう

このボタンが押されると (actionListener を使用してポストバックをトリガーしないため、ajax を使用してコンテンツをリロードする必要があります)、コントローラーの switchContentMethod が getContentPath によって返される文字列を変更する場合があります。

public void switchContent(){
    contentPath = "/view1.xhtml";
}

@Produces
@SomethingScoped
@Named("contentPath")
public String getContentPath(){
    return contentPath;
}

メニューバーのボタンを使用して、パネルに表示されるビューを変更できるようになりました。これにより、ページをリロードせずにナビゲーションできます。

いくつかのアドバイス (または「私が学んだこと」) :

  1. getTopMenuItems メソッドに大きなスコープを選択したい場合があります
  2. ui:include タグをネストしないでください。残念ながら、これは不可能です (たとえば、view1.xhtml に別のコンポジションを含めることはできません)。ポートレットなしでポートレットのみのような、本当にモジュール化されたjsfビューを構築できるので、このようなことが可能になることを本当に望んでいます.. =D
  3. tabviews のようなコンテナー コンポーネントで ui:include を実行することも問題があることがわかります。
  4. 一般に、JSTL (c:forEach) と JSF を混在させることはお勧めできません。それでも、含まれているコンテンツが表示されないなど、 ui:repeat の評価が遅すぎるため、これが機能する唯一の方法であることがわかりました。
于 2013-06-06T22:52:21.020 に答える