2

wysiwyg コンテンツやテンプレート編集などの基本的なサイト管理機能を提供するアプリケーション用の小さな CMS を作成しました。ページはデータベースに facelets として保存され、カスタム URL リゾルバー ( https://community.jboss.org/message/495515#495515の最後の投稿を参照) を使用してクライアントに提示されます。これは、別のページのサポートを開始するまでは非常にうまく機能していました。同じアプリケーションによって提供される異なるドメインのツリー (apache の仮想ホストに少し似ています)。

したがってhttp://firstdomain/cms/page.xhtml、 とは異なるページにつながるはずですhttp://seconddomain/cms/page.xhtml。ここでの問題は、カスタム DefaultResourceResolver (およびその他のリゾルバー) によって解決された URL が、パス (/cms/page.xhtml) のみを使用して JSF によってキャッシュされることです。そのため、最初に照会されたドメインが何であれ、要求されたドメインに関係なく、同じパスへのすべての要求に対してキャッシュされた URL を提供します。

この問題をキャッシングに突き止めるのにかなりの時間がかかりましたが、今は立ち往生しています。要求されたドメイン名を尊重するために JSF の URL キャッシュを変更/上書き/無効にする方法はありますか?

更新 1: FaceletCacheImpl.java の myfaces 実装を読んだところ、URL 自体がキャッシュのキーであり、パスだけではないことに気付きました。これは、ここで説明する問題につながります: java.net.URL のハッシュコードがホストを IP に解決するのはなぜですか? - URL は、ホスト名ではなく IP アドレスを使用して比較されます。それでも、Facelets のキャッシュ動作を変更する必要があります。

更新 2: URL パラメーターを試してみたところ、FaceletCacheImpl.java で見たもの以外のパスによってのみ実際にキャッシュされているため、更新 1 は無視できることがわかりました。

4

1 に答える 1

0

さらに調査したところ、登録済みの URL リゾルバーを呼び出し、解決された URL をキャッシュする DefaultFaceletFactory.java が見つかりました。クラスは final であるため、拡張することはできませんでした。そのため、jboss から最新の jsf-facelets ソースをダウンロードし、現在のリクエスト ホストをキャッシュ キーに追加して直接変更しました。これは私の代替品ですpublic Facelet getFacelet(String uri)

public static HttpServletRequest getRequest() {
    return (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
}

/**
 * Returns the host name from the current request.
 *
 * @return
 */
public static String getRequestHost() {
    HttpServletRequest request = getRequest();
    if (request == null) {
        return null;
    }
    String result = request.getHeader("x-forwarded-host");
    if (result == null || result.isEmpty()) {
        result = request.getHeader("host");
    }
    return result;
}


/*
 * (non-Javadoc)
 * 
 * @see com.sun.facelets.FaceletFactory#getFacelet(java.lang.String)
 */
public Facelet getFacelet(String uri) throws IOException, FaceletException,
        FacesException, ELException {
    String key = getRequestHost() + ":" + uri;
    URL url = (URL) this.relativeLocations.get(key);
    if (url == null) {
        url = this.resolveURL(this.baseUrl, uri);
        if (url != null) {
            Map newLoc = new HashMap(this.relativeLocations);
            newLoc.put(key, url);
            this.relativeLocations = newLoc;
        } else {
            throw new IOException("'" + uri + "' not found.");
        }
    }
    return this.getFacelet(url);
}

私は認めなければなりません、この解決策はかなり汚いですが、それは仕事を成し遂げます. また、facelets の実装にはしばらくの間変更がなかったので、更新は問題になりません。

于 2012-10-11T19:13:29.030 に答える