我为应用程序编写了一个小型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的缓存URL。
我花了相当长的时间将这个问题归结到缓存上,但是现在我被卡住了。有什么方法可以更改/覆盖/禁用JSF的URL缓存以尊重所请求的域名吗?
更新1:我刚刚阅读了FaceletCacheImpl.java的myfaces实现,并注意到URL本身是其缓存的关键,而不仅仅是其路径的关键。这导致这里讨论的问题:Why does java.net.URL's hashcode resolve the host to an IP?-使用URL的IP地址而不是主机名来比较URL。因此,我仍然必须更改Facelets缓存行为。
更新2:尝试使用URL参数使我确信,除了FaceletCacheImpl.java中看到的内容之外,它们确实仅通过其路径进行了缓存,因此可以忽略更新1。
最佳答案
更多的研究将我指向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的实现没有任何变化,因此更新应该不是问题。