2

我正在努力解决一个问题,我试图使用 JSF 2.1 和 Primefaces 为一种 CMS 项目动态生成页面。我的问题是我正在尝试使用自定义 ResourceResolver 动态包含一个存在于数据库中的页面(该部分效果很好)。问题是我正在使用请求参数来确定要服务的页面(即:http: //xxx.xxx.com/context/public/ ?p=2 )。在我想使用任何 Ajax 或更具体的 Primefaces(在我的情况下是我需要使用 actionListeners 的调度组件)之前,这工作正常。我发现在发出 ajax 请求时我的视图没有得到解决,可能是因为它是请求范围的。下面是一段代码:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui" 
  xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="/WEB-INF/view/public/templates/public-template.xhtml">
    <ui:define name="body"> 
        <p:outputPanel autoUpdate="false" rendered="#{empty publicBean.site}">
            <div>No site found!</div>
        </p:outputPanel>

        <p:outputPanel autoUpdate="false" rendered="#{! empty publicBean.page and empty publicBean.page.pageTemplate}">
            <div>No valid page template found!</div>
        </p:outputPanel>

        <ui:include src="#{publicBean.view}" />
    </ui:define>
</ui:composition>
</html>

视图的数量是未知的并且是动态创建的,所以我不能只做一个丑陋的 ui:includes 块然后有条件地渲染。

所以我看到的是,当我这样做时,我的基于 ajax 的表单(例如使用 p:commandButton)不起作用。我从来没有看到在我的 bean 上执行的操作。但是,如果我对从“#{publicBean.view}”返回的视图进行硬编码,使其始终返回相同的视图,那么一切正常。所以我假设在 ajax 调用期间 publicBean.view 可能返回 null 或者在我的情况下是 AgoraConstants.CUSTOM_VIEW_NOT_FOUND。这是我的支持 bean 中的代码:

public String getView()
{
     // If this below is uncommented, the form with ajax/primefaces works
    //if ( 1 == 1 )
    //{
    //    return "/X-AGORA-VIEW/districtOfficeCalendarTemplate.xhtml";
    //}
    if ( page != null && page.getPageTemplate() != null )
    {
        return AgoraConstants.CUSTOM_VIEW_PREFIX + page.getPageTemplate().getName() + ".xhtml";
    }
    else if ( site != null && site.getLandingPage() != null && site.getLandingPage().getPageTemplate() != null )
    {
        return AgoraConstants.CUSTOM_VIEW_PREFIX + site.getLandingPage().getPageTemplate().getName()+".xhtml";
    }
    return AgoraConstants.CUSTOM_VIEW_NOT_FOUND;
}

所以这是我的问题,我怎样才能绕过请求参数,以便我可以使用 ajax 和 primefaces 以我想要的方式工作?我可以把它扔到会话中,但是如果用户在两个具有不同视图的选项卡中打开站点,事情可能会变得混乱并且无法正常运行。基本上,我应该如何保留请求变量,以便我可以确保 getView() 为 ajax 请求返回相同的视图?似乎应该有一个简单的解决方案来解决这个问题,但我没有看到任何帮助,将不胜感激。

** 编辑 **

我还尝试将我的支持 bean 更改为查看范围(来自请求),但这似乎没有帮助(但我不知道为什么)。下面是更多的支持 bean 代码。我添加了 init 方法,该方法在使用 @PostConstruct 创建 bean 时调用。

public void init()
{       
    site = null;
    page = null;

    logger.info("Loading public view...");

    if (  getFacesContext().getExternalContext().getRequestParameterMap().containsKey(AgoraConstants.PUBLIC_PAGE_REQUEST_VAR) )
    {
        logger.info("Restoring Page...");
        long value = parseLong((String)getFacesContext().getExternalContext().getRequestParameterMap().get(AgoraConstants.PUBLIC_PAGE_REQUEST_VAR));
        if ( value >= 0 )
        {
            logger.info("Attempting to restore: {}", value);    
            try
            {
                page = pageService.getItem(value);
                if ( page != null )
                {
                    if ( ! page.isEnabled() )
                    {
                        page = null;
                    }
                }
            }
            catch(Exception e)
            {
                logger.warn("Failed to load site: {}", e.getLocalizedMessage());
            }
        }
    }

    if (  page == null && getFacesContext().getExternalContext().getRequestParameterMap().containsKey(AgoraConstants.PUBLIC_SITE_REQUEST_VAR) )
    {
        logger.info("Restoring Site...");
        long value = parseLong((String)getFacesContext().getExternalContext().getRequestParameterMap().get(AgoraConstants.PUBLIC_SITE_REQUEST_VAR));
        if ( value >= 0 )
        {
            logger.info("Attempting to restore: {}", value);    
            try
            {
                site = siteService.getItem(value);
            }
            catch(Exception e)
            {
                logger.warn("Failed to load site: {}", e.getLocalizedMessage());
            }
        }
    }

    if ( page != null && page.getSite() != null)
    {
        site = page.getSite();
    }

    if ( site == null )
    {
        site = siteService.getDefaultSite();
    }
}

public String getView()
{
//        if ( 1 == 1 )
//        {
//            return "/X-AGORA-VIEW/districtOfficeCalendarTemplate.xhtml";
//        }
    if ( page != null && page.getPageTemplate() != null )
    {
        logger.info("a" + AgoraConstants.CUSTOM_VIEW_PREFIX + page.getPageTemplate().getName() + ".xhtml");
        return AgoraConstants.CUSTOM_VIEW_PREFIX + page.getPageTemplate().getName() + ".xhtml";
    }
    else if ( site != null && site.getLandingPage() != null && site.getLandingPage().getPageTemplate() != null )
    {
        logger.info("b" + AgoraConstants.CUSTOM_VIEW_PREFIX + site.getLandingPage().getPageTemplate().getName()+".xhtml");
        return AgoraConstants.CUSTOM_VIEW_PREFIX + site.getLandingPage().getPageTemplate().getName()+".xhtml";
    }
    logger.info("c");
    return AgoraConstants.CUSTOM_VIEW_NOT_FOUND;
} 
4

2 回答 2

0

在这种情况下你应该使用 view scoped bean,但是在使用 view scope 和动态 ui:include 时会出现问题。您可以对其进行测试,例如在构造函数中放置断点,您将看到在每个请求中都创建了 bean。如果您使用例如 c:if 或 c:for,也存在问题。

于 2012-12-29T17:46:50.743 回答
0

好吧,我的整个问题是因为回发不包括 ajax 请求的请求参数,所以我正在使用漂亮的面孔来解决这个问题。有了漂亮的面孔,我设置了映射以在回发时包含请求参数,这解决了我的问题。这可能不适用于所有情况,但对我来说似乎效果很好。

于 2012-12-30T14:25:41.550 回答