如何在 JSF ajax 监听器方法中导航/重定向

Posted

技术标签:

【中文标题】如何在 JSF ajax 监听器方法中导航/重定向【英文标题】:How to navigate / redirect in JSF ajax listener method 【发布时间】:2015-08-08 00:10:19 【问题描述】:

我的 index.xhtml 中有这个可选择的 PrimeFaces 树,带有一个 Ajax 侦听器:

<p:tree value="#seccionesArbolView.root" var="node" selectionMode="single" >
    <p:treeNode>
        <h:outputText value="#node.nombre" />
    </p:treeNode>
    <p:ajax event="select" listener="#seccionesArbolView.onNodeSelect"></p:ajax>
</p:tree>                    

侦听器方法位于会话范围的命名 bean 上,并且应该使用一些 GET 参数重定向到另一个页面 (grupal.xhtml)。我试过这个:

public String onNodeSelect(NodeSelectEvent event) throws IOException 
    Seccion sec = (Seccion) event.getTreeNode().getData();
    String enlace = "grupal.xhtml?faces-redirect=true&id=" + sec.getId() + "&nombre=" + sec.getNombre();
    return enlace;

但什么也没发生。我在另一个问题中读到可能是因为 Ajax 请愿,所以我尝试使用 ExternalContext:

public String onNodeSelect(NodeSelectEvent event) throws IOException 
    Seccion sec = (Seccion) event.getTreeNode().getData();
    FacesContext context = FacesContext.getCurrentInstance();
    String enlace = "faces/grupal.xhtml?id=" + sec.getId() + "&nombre=" + sec.getNombre();
    context.getExternalContext().redirect(enlace);
    context.responseComplete();

这种方法的问题在于链接的构建。它的完成方式(带有“faces”前缀)有效,但是每次单击树时,URL 都会变得越来越大,并添加另一个“faces/”(例如http://localhost:8080/MyApp/faces/faces/faces/grupal.xhtml?...)并且 Glassfish 发出警告 请求路径“/faces/faces/grupal.xhtml”以一次或多次出现的 FacesServlet 前缀路径映射“/faces”开始

如果链接的构造没有“faces/”前缀:

String enlace = "grupal.xhtml?id=" + sec.getId() + "&nombre=" + sec.getNombre();

只要通过 URL http://localhost:8080/MyApp/faces/index.xhtml 访问 index.html,它就可以工作。但是当通过基本 URL http://localhost:8080/MyApp/ 访问 index.html 时,显然找不到 grupal.xhtml。

我不确定在这种情况下最好的解决方案是什么。

有没有办法通过 JSF 2.0 导航来做到这一点(第一种方法,我无法开始工作)?

有没有办法获取整个基本 URL 以使用绝对路径进行重定向?

有没有办法告诉 Glassfish 将基本 URL http://localhost:8080/MyApp/ 重定向到 http://localhost:8080/MyApp/faces/index.xhtml ?

【问题讨论】:

【参考方案1】:

我试过这个:

return enlace;

但什么也没发生。

您确实可以listener/actionListener 方法导航。您只能从 action 方法导航。

另见:

Differences between action and actionListener

有没有办法通过 JSF 2.0 导航来做到这一点(第一种方法,我无法开始工作)?

您可以使用NavigationHandler#handleNavigation() 以编程方式执行导航。

public void onNodeSelect(NodeSelectEvent event) 
    // ...
    String outcome = "grupal.xhtml?faces-redirect=true&id=" + sec.getId() + "&nombre=" + sec.getNombre();
    FacesContext context = FacesContext.getCurrentInstance();
    context.getApplication().getNavigationHandler().handleNavigation(context, null, outcome);

另见:

How to make redirect using navigation-rule

有没有办法获取整个基本 URL 以使用绝对路径进行重定向?

您可以使用ExternalContext#getRequestContextPath() 以编程方式获取上下文路径。

public void onNodeSelect(NodeSelectEvent event) throws IOException 
    // ...
    String uri = "/faces/grupal.xhtml?id=" + sec.getId() + "&nombre=" + sec.getNombre();
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    ec.redirect(ec.getRequestContextPath() + uri);

另见:

ExternalContext#redirect() does not redirect to parent directory

有没有办法告诉 Glassfish 将基本 URL http://localhost:8080/MyApp/ 重定向到 http://localhost:8080/MyApp/faces/index.xhtml ?

index.xhtml 上的web.xml 中使用&lt;welcome-file&gt;,并将/faces/* 的尴尬JSF 1.0 样式FacesServlet 映射替换为JSF 2.0 样式*.xhtml

另见:

JSF welcome file is not recognized Sometimes I see JSF URL is *.jsf, sometimes *.xhtml and sometimes /faces/*. Why?

【讨论】:

谢谢,我试试。两种方式之间有任何技术差异,还是只是风格问题? 导航处理程序是抽象的,因此可以使用自定义处理程序进行配置,也可以通过 faces 配置覆盖。重定向是“硬编码”的。

以上是关于如何在 JSF ajax 监听器方法中导航/重定向的主要内容,如果未能解决你的问题,请参考以下文章

JSF AJAX和正常重定向登录并返回上一页

在 servlet 过滤器中使用请求参数将 JSF ajax 请求重定向到 URL

当发送的请求是 Ajax 请求时,如何从 ManagedBean 重定向?

JSF2 <h:selectOneMenu 和 <f:ajax 侦听器在 PrettyFaces 过滤器导航之后未调用

JSF 2 - 如何将 Ajax 侦听器方法添加到复合组件接口?

将 PrimeFaces 与 JSF 一起使用时 Shiro 重定向到错误的位置