gpt4 book ai didi

没有 @ViewScoped 的 JSF

转载 作者:行者123 更新时间:2023-12-03 16:35:19 26 4
gpt4 key购买 nike

我已经使用 JSF 很多年了,在下一个项目中,我们的目标是使 Web 层尽可能无状态。我正在探索的一种可能性是删除 @ViewScoped bean 类支持@RequestScoped (根据需要加上一两个 @SessionScoped bean )。这对于具有 AJAX、数据表和条件渲染的复杂页面来说是很麻烦的。我的问题是:JSF(和 PrimeFaces)与无状态 Web bean 的工作情况如何?这是我应该继续探索的东西,还是@ViewScope现在如此基本以至于不值得努力?

在我写这个问题时,我很感激它可能会因为“主要基于意见”而被关闭,但是我希望它不是,我对 @ViewScope 的具体问题感兴趣已解决,以及我必须通过忽略 @ViewScoped 重新引入哪些历史解决方法.

最佳答案

How well does JSF (and PrimeFaces) work with stateless web beans?


这在技术上是可行的。
JSF 主要使用 View 状态来跟踪 UIInput 的“禁用”、“只读”和“渲染”属性。和 UICommand组件以及“提交值”、“本地值”和“是否有效?” EditableValueHolder 的状态组件(由 UIInput 等实现)。
在“disabled”、“readonly”和“rendered”属性的情况下,如果它们代表一个EL表达式,那么JSF会在处理表单提交请求时重新检查它。下面是一个基本示例:
<h:form>
<h:commandButton value="toggle" action="#{bean.toggle}">
<f:ajax render="panel" />
</h:commandButton>
<h:panelGroup id="panel">
<h:commandButton value="submit" action="#{bean.submit}" rendered="#{bean.toggled}">
<f:ajax />
</h:commandButton>
</h:panelGroup>
</h:form>
@Named
@ViewScoped
public class Bean implements Serializable {

private static final long serialVersionUID = 1L;

private boolean toggled;

public void toggle() {
this.toggled = !toggled;
}

public void submit() {
System.out.println("Submitted");
}

public boolean isToggled() {
return toggled;
}
}
首先单击“切换”按钮,然后单击“提交”按钮。如果是 View 范围的 bean,它会工作得很好。但是,如果您更换 @ViewScoped通过 @RequestScoped在这里,它会失败,因为 toggled默认返回 false目前 JSF 需要在回发请求期间解码“提交”按钮,因此它的 rendered属性将评估 false最终 JSF 不会将 Action 事件排队。
在这种情况下,您需要确保自己在请求范围 bean 的(后)构造期间将属性预初始化为预期值。一种方法是在 ajax-updated 组件中为此使用隐藏的输入字段。这是调整后的示例:
<h:form>
<h:commandButton value="toggle" action="#{bean.toggle}">
<f:ajax render="panel" />
</h:commandButton>
<h:panelGroup id="panel">
<input type="hidden" name="toggled" value="#{bean.toggled}" />
<h:commandButton value="submit" action="#{bean.submit}" rendered="#{bean.toggled}">
<f:ajax />
</h:commandButton>
</h:panelGroup>
</h:form>
@Named
@RequestScoped
public class Bean {

@Inject @ManagedProperty("#{param.toggled}")
private boolean toggled;

public void toggle() {
this.toggled = !toggled;
}

public void submit() {
System.out.println("Submitted");
}

public boolean isToggled() {
return toggled;
}
}

NOTE: a <h:inputHidden> will unfortunately not work as it updates the model value only after the action event is to be queued. Even not with a immediate="true" on it. This brings me by the way on the idea for a new <o:inputHidden> for OmniFaces.


通过这些更改,它会正常工作。
然而,由于最初是 View 范围的状态( toggled 属性)现在已成为请求参数,因此它完全暴露给世界,因此也可以被黑客篡改。想要调用“提交”按钮而不首先调用“切换”按钮的黑客现在可以简单地手动添加请求参数 toggled=true .这是否可取取决于您的应用程序的业务需求,但通常情况下它是完全不可取的。
这就是 JSF 试图通过提供将这些敏感属性放在 @ViewScoped 中的可能性来保护您免受伤害的原因。而是 bean 。

This is proving troublesome for complex pages with AJAX, datatables and conditional rendering


没错,但在技术上仍然不是不可能的。您只需通过手动填充的隐藏输入字段手动执行分页、排序和过滤状态,如上所示。 <p:dataTable>支持将这些状态绑定(bind)到 bean 属性。例如:
<p:dataTable ...
first="#{bean.first}"
sortField="#{bean.sortField}"
sortOrder="#{bean.sortOrder}"
filterBy="#{bean.filterBy}">
...
</p:dataTable>
您可以将它们复制到 <input type="hidden">之前演示的字段(您确保被 <p:ajax update> 覆盖!),最后通过 @ManagedProperty 获取它们和/或 @PostConstruct .
实际上,您的这种方式基本上是对 javax.faces.ViewState 目前已经完成的工作进行了改造。与 @ViewScoped 组合的隐藏输入字段 bean 。那么为什么不马上使用呢? :)
如果您主要关心的是内存使用,那么您需要仔细设计您的 bean,使 仅限 View 范围状态存储在 @ViewScoped bean 和那个 仅限 请求范围状态存储在 @RequestScoped bean 。例如,将数据模型放在请求范围 bean 中,将分页/排序/过滤状态放在 View 范围 bean 中是非常好的。您可能还想考虑 OmniFaces @ViewScoped 相反,当页面被卸载时,它会立即破坏 View 状态和物理 bean。
也就是说,考虑到这个问题,我已经 just a few hours ago验证和改进了 OptimusFaces库以确保它也完全支持具有 <f:view transient="true"> 的无状态 View ,以及新的集成测试。 OptimusFaces 的优点之一是您不再需要手动担心携带分页/排序/过滤状态。 OptimusFaces 会为您担心。
也可以看看:
  • Why JSF saves the state of UI components on server?
  • JSF: Mojarra vs. OmniFaces @ViewScoped: @PreDestroy called but bean can't be garbage collected
  • How to choose the right bean scope?
  • What is the usefulness of statelessness in JSF?
  • 关于没有 @ViewScoped 的 JSF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61621240/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com