从doHeaders()中删除重复的标头条目

时间:2013-11-05 18:34:26

标签: java jsp portlet jsr286

我有几个portlet,每个portlet在一个Web应用程序中使用池化的CSS和JS文件的聚合。目前,每个portlet都会在doHeaders()中添加适当的头标记。但是,当多个portlet位于同一页面上时,这会导致头部内出现重复的标记。

目前,portlet部署在运行在GateIn上的eXo上。 eXo拥有自己的JS AMD框架和portlet皮肤系统,但我们使用doHeaders()添加head元素,以尽可能地与平台无关,以降低风险。

以下列方式添加头元素:

@Override
public void doHeaders(RenderRequest request, RenderResponse response)
{
    Element element = response.createElement("link");
    element.setAttribute("type", "text/css");
    element.setAttribute("rel", "stylesheet");
    element.setAttribute("href", request.getContextPath() + "/service/resource/themes/stylesheet.css");
    response.addProperty(MimeResponse.MARKUP_HEAD_ELEMENT, element);
}

我需要从头部删除重复的条目,或者防止重复写入。

我正在尝试编写一个可以删除重复头元素的常见RenderFilter。但我似乎无法从RenderResponse访问当前的Element属性;我只能setProperty()或addProperty()。

我还可以编写RenderFilter来替换每个单独的portlet的doHeaders()方法,并将整个CSS和JS池添加到头部。但我无法确保此逻辑仅针对每个用户会话页面呈现运行。

1 个答案:

答案 0 :(得分:2)

我目前实现的解决方案是RenderFilter,如果尚未编写池,则将整个JS和CSS资源池写入头部。这在某种程度上是次优的,因为检测待处理的头元素不是我发现的可以以独立于平台的方式完成的。但是,决定如何处理冗余头元素完全取决于平台委派,因为JSR-286没有规定在这种情况下应该做什么。

通过使用eXo的PortalRequestContext,可以获得待处理头元素的列表。通过添加元素来标识资源池,RenderFilter可以决定是否需要写入池或者是否已经写入了池。

这是基本的检测逻辑:

boolean addHeaderElements = true;
if (Util.getPortalRequestContext() != null && Util.getPortalRequestContext().getExtraMarkupHeaders() != null)
{
    for (Element markupHeaderElement : Util.getPortalRequestContext().getExtraMarkupHeaders())
    {
        if (markupHeaderElement.getTagName().equalsIgnoreCase("meta") &&
            markupHeaderElement.getAttribute("name") != null &&
            markupHeaderElement.getAttribute("name").equalsIgnoreCase("project-name"))
        {
            addHeaderElements = false;
            break;
        }
    }
}

这也可以编写为基于文件操作,但我的portlet资源池通常共享,可以使用全有或全无的方法。