2

我为一个应用程序编写了一个小型 CMS,它提供了基本的站点管理功能,如所见即所得的内容和模板编辑。页面作为 facelets 存储在数据库中,并使用自定义 url 解析器呈现给客户端(请参阅https://community.jboss.org/message/495515#495515上的最后一篇文章),在我开始支持不同的页面之前效果非常好由同一应用程序服务的不同域的树(有点像 apache 的虚拟主机)。

所以http://firstdomain/cms/page.xhtml应该导致不同于http://seconddomain/cms/page.xhtml. 这里的问题是,由我的自定义 DefaultResourceResolver(以及任何其他解析器)解析的 URL 仅由 JSF 使用路径 (/cms/page.xhtml) 缓存。因此,无论首先查询哪个域,都会为所有到同一路径的请求提供缓存的 URL,而与请求的域无关。

我花了很长时间才将这个问题归结为缓存,但现在我被卡住了。有什么方法可以更改/覆盖/禁用 JSF 的 URL 缓存以尊重请求的域名?

更新 1:我刚刚阅读了 FaceletCacheImpl.java 的 myfaces 实现,并注意到 URL 本身就是它们缓存的关键,而不仅仅是它们的路径。这导致了这里讨论的问题:为什么 java.net.URL 的哈希码将主机解析为 IP?- URL 使用其 IP 地址而不是主机名进行比较。所以仍然,我必须改变 Facelets 的缓存行为。

更新 2:对 URL 参数的试验使我确信,除了我在 FaceletCacheImpl.java 中看到的内容之外,它们确实只通过路径缓存,因此可以忽略更新 1。

4

1 回答 1

0

更多研究将我指向 DefaultFaceletFactory.java,它负责调用注册的 url 解析器并缓存解析的 URL。由于该类是最终的,因此无法扩展它,因此我从 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 回答