【问题标题】:JSF/Primefaces - CommandButton: open new browser tab without ViewScoped bean getting killedJSF/Primefaces - 命令按钮:打开新的浏览器选项卡,而没有 ViewScoped bean 被杀死
【发布时间】:2013-09-06 17:06:03
【问题描述】:

我正在尝试从ViewScoped bean 支持的视图中打开一个带有 JSF 视图(在 portlet 中,部署在 Liferay 中)的新浏览器选项卡。使用正常动作重定向会杀死 bean。 我试过herehere提供的方法,可惜没有成功。

按钮看起来或多或少像这样:

<p:commandButton value="#{msg.label}" onclick="target='_blank'" 
                 action="#{sessionScopedBean.action(param)}" ajax="false" />

target='_blank' 移动到表单属性没有帮助。我已经尝试过返回nullvoid 都没有成功。将 ajax 更改为 true 破坏了导航,没有打开新标签,但也没有杀死 ViewScoped bean。

action 方法内容如下所示:

public void action(String param) throws IOException {
   //some business logic

   FacesContext.getCurrentInstance().getExternalContext().redirect("viewName.xhtml");
}

视图不包含&lt;c:if test="..."&gt;&lt;ui:include src="..."&gt; 等标记处理程序。它确实包含一个<ui:repeat id="..." value="#{viewScopedBean.collection}" var="..." varStatus="..."> 标签,但删除它改变了注释。 表单包含在&lt;ui:composition&gt;&lt;ui:define&gt; 标记中。

我重定向到的视图与 ViewScoped bean 没有任何联系。有任何想法吗? :)

【问题讨论】:

    标签: java jsf jsf-2 primefaces liferay


    【解决方案1】:

    视图范围中断,因为您使用的重定向操作基本上是指示客户端在给定 URL 上触发全新的 GET 请求。您应该返回 nullvoid 并有条件地在 same 视图中呈现结果。

    另见:


    您找到的链接中已经给出了解决方案:在重定向之前将感兴趣的数据放在闪存范围中,并从与目标视图关联的 bean 中的闪存范围中获取它们。如果由于某种原因这对您不起作用,另一种方法是生成一个唯一密钥(java.util.UUID 也许?)并将其存储在会话范围中,作为与您希望保留在重定向中的某些数据相关联的密钥请求,

    String key = UUID.randomUUID().toString();
    externalContext.getSessionMap().put(key, data);
    

    然后将该密钥作为重定向 URL 中的请求参数传递

    externalContext.redirect("nextview.xhtml?key=" + key);
    

    这样就可以在与目标视图关联的bean的postconstruct中获取数据:

    String key = externalContext.getRequestParameterMap().get("key");
    Data data = (Data) externalContext.getSessionMap().remove(key);
    // ...
    

    【讨论】:

    • Thx 那么,这是否意味着我误解了我提供的链接的问题/答案?即,如果不从第一个视图中“杀死” ViewScoped bean,就不可能打开一个具有不同视图的新选项卡?似乎这是问题的用例。至于你回答的第二部分,我对传递数据没有问题。我只想保留原始视图(我尽量避免对一些有缺陷的遗留代码进行重大更改)。用例如下:用户填写表单(查看一-有未提交的数据),可以查看之前上传过的文档(查看二)
    • 我没有看到这些链接。这些链接中的答案建议为此使用闪存范围。使用 flash 范围确实也是一种方法,这与上述会话方法的效果基本相同。但经过一段时间后,我知道闪存范围与某些 Mojarra 版本结合使用时存在一些问题,并且由于您使用的是 portlet(这是一个非常严格的环境),我只是想排除闪存范围的问题。
    • 好的,所以不可能欺骗系统并使 ViewScoped bean 在新选项卡中的重定向中幸存下来?我有这个想法是因为你写了“事实上,初始选项卡/窗口中的视图范围 bean 通过返回 String 导航案例结果而被杀死。你想返回 nullvoid 以使其保持活力。”人们最初在返回第一个选项卡时写了有关丢失数据的文章:)
    • 视图范围的 bean 与 JSF 视图一样长。只要您回发到同一个视图(通过返回null/void),JSF 视图就会存在。一旦您发送重定向(这完全不管目标是在同一个标​​签还是新标签中),视图就会被破坏。只需返回 nullvoid 并有条件地在同一视图中呈现结果。它会起作用(这也完全不管目标是在同一个标​​签还是新标签中)。
    • 所以总结一下:如果 Faces.redirect() 指向相同的视图,则 void/null 方法将起作用,但如果它指向不同的视图则不会。所以这不是绕过 ViewScoped bean 行为的方法。我会尝试一些其他方法来处理遗留代码中的这个错误(就像你建议的那样)。感谢您的回答。至于您(现在已编辑)答案的第二部分,这不是我想要做的(将数据传递到新视图/bean 不是问题)。问题是丢失了第一个视图中的数据,从用户的角度来看,该视图仍然处于活动状态。
    猜你喜欢
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 2018-06-03
    相关资源
    最近更新 更多