为纯 AJAX 构建 JSF 2 应用程序

Posted

技术标签:

【中文标题】为纯 AJAX 构建 JSF 2 应用程序【英文标题】:Structuring a JSF 2 app for pure AJAX 【发布时间】:2012-03-15 17:34:58 【问题描述】:

我非常熟悉如何在 JSF 2 中使用 AJAX。但是,JSF 2 在设计时考虑到了传统的页面到页面导航,并抛出了 AJAX 以防止完全重新加载同一页面。

我想弄清楚的是一种使用 JSF 2 构建纯 AJAX Web 应用程序的好方法。也就是说,每个用户会话只需要一个初始完整页面加载的 Web 应用程序。

现在,如果有足够的时间,我相信我可以自己解决这个问题,但我担心解决方案可能会很尴尬,我可能会将自己逼入绝境。

一个想法是创建复合组件而不是页面,然后拥有一个包含每个复合组件的实例的页面,其 rendered 属性的值通过将唯一页面名称与包含当前的会话范围变量进行比较来计算页面名称。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:page="http://java.sun.com/composite/components/pages">
<h:head>
    <title>MyApp | #pageBean.title</title>
</h:head>
<h:body>
    <!-- Header, sidebars, etc. go here -->

    <!-- Pages -->
    <page:home id="home" rendered="#pageBean.name == 'home'"/>
    <page:search id="search" rendered="#pageBean.name == 'search'"/>
    <page:profile id="profile" rendered="#pageBean.name = 'profile'"/>
    <!-- etc... -->
</h:body>

不过,这只是图片的一部分。该页面必须是可收藏的,这需要 hash-bangs 和 javascript 哈希更改处理程序。事实上,页面导航可能会通过在 javascript 中设置锚点来实现,让哈希更改处理程序来处理其余部分。

想法?

【问题讨论】:

我认为你正在经历它。对于可添加书签的页面,您可以通过 url 传递参数并在 servlet 或 @SessionScoped 托管 bean 中接收它。解析它(它可以是纯文本或哈希编码)并显示你想要的页面。 为什么不采用 PrimeFaces Mobile 等现有技术:primefaces.org/showcase-labs/mobile/index.jsf 因为 1. 我没有问过关于编写移动网络应用程序的问题 2. PrimeFaces Mobile 是一个可怕的废话。 【参考方案1】:

我尝试使用动态加载的布局和模板来做到这一点。 我有一个页面布局,其中一些是根据菜单加载的内容。 看看它的样子:

<h:body>

        <p:layout fullPage="true">

            <p:layoutUnit position="north" size="80" resizable="true" closable="true" collapsible="true">
                <h:form id="form3">  
                    <ui:include src="./templates/template.xhtml" />  
                </h:form> 
            </p:layoutUnit>

            <p:layoutUnit position="south" size="100" closable="true" collapsible="true">
                Footer
            </p:layoutUnit>

            <p:layoutUnit position="west" header="Opciones" size="175">
                <h:form id="form1">
                    <p:panelMenu style="width:200px">   
                        <p:submenu label="Clientes" >
                            <p:menuitem value="Adicionar" update=":form2" actionListener="#templateMB.templateAddCliente" />
                            <p:menuitem value="Modificar" update=":form2" actionListener="#templateMB.templateConfigCliente" />
                            <p:menuitem value="Listado" update=":form2" actionListener="#templateMB.templateListadoCliente" />
                        </p:submenu> 
                        <p:submenu label="Contratos">  
                            <p:menuitem value="Adicionar" update=":form2" actionListener="#templateMB.templateAddContrato" />
                        </p:submenu>  
                        <p:separator/>  
                        <p:submenu label="Suplementos" >  
                            <p:menuitem value="Adicionar" icon="ui-icon-signal"/>  
                        </p:submenu>  
                    </p:panelMenu>
                </h:form>
            </p:layoutUnit>

            <p:layoutUnit position="center" id="centerlayout">
                <h:form id="form2">  
                    <ui:include src="#templateMB.centerTemplate" />  
                </h:form> 
                </p:layoutUnit>

        </p:layout>

    </h:body>

支持bean:

    public String templateAddCliente() 
    try 
        this.centerTemplate = "./templates/addCliente.xhtml";
         return null;

     catch (Exception e) 
        JsfUtil.addErrorMessage("Ha ocurrido un error: " + e.getMessage());
        return null;
    


  public String templateConfigCliente() 
    try 
        this.centerTemplate = "./templates/configCliente.xhtml";
         return null;

     catch (Exception e) 
        JsfUtil.addErrorMessage("Ha ocurrido un error: " + e.getMessage());
        return null;
    

  public String templateHome() 
    try 
        this.centerTemplate = "./templates/hometemplate.xhtml";
         return null;

     catch (Exception e) 
        JsfUtil.addErrorMessage("Ha ocurrido un error: " + e.getMessage());
        return null;
    


  public String templateListadoCliente() 
    try 
        this.centerTemplate = "./templates/listadoCliente.xhtml";
         return null;

     catch (Exception e) 
        JsfUtil.addErrorMessage("Ha ocurrido un error: " + e.getMessage());
        return null;
    


  public String templateAddContrato() 
    try 
        this.centerTemplate = "./templates/addContratos.xhtml";
         return null;

     catch (Exception e) 
        JsfUtil.addErrorMessage("Ha ocurrido un error: " + e.getMessage());
        return null;
    

【讨论】:

只是一个关于如何实现它的思想,但我需要弄清楚如何在单个方法中生成支持 bean 中的负载,识别调用哪个菜单项。¿?

以上是关于为纯 AJAX 构建 JSF 2 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

JSF 2.0 AJAX:使用 jsf.ajax.request(或其他方式)从 javascript 调用 bean 方法

JSF 2.0 有比 Icefaces 更好的 Ajax Push

JSF,用ajax定期刷新一个组件?

使用 JSF 2.2 动态加载表单

Ajax4Jsf 简单介绍

与 JSF 相比,React 如何具有更好的性能