0

假设以下场景:

  • 在 Web 应用程序中,我在页面上有一个简单的表单,用户可以在其中更新数据库中的值;支持豆Controller@ViewScoped。当使用 GET 参数加载页面时,将在自定义转换器中从数据库中读取保存该值的对象。
<!-- The details page for editing an object -->
<f:metadata>
  <o:viewParam name="id" value="#{controller.myObject}" required="true">
    <f:converter converterId="myObjectConverter" />
  </o:viewParam>
</f:metadata>
<o:form includeViewParams="true">
  <h:inputText id="desc" value="#{controller.myObject.myValue}" validatorMessage="Input invalid">
    <f:validateRequired />
    <f:validateLength minimum="1" />                        
  </h:inputText>
  <p:message for="desc" />
  <h:commandButton action="#{controller.updateValue()}">
    Save
  </h:commandButton>
</o:form>
@Named
@ViewScoped
public class Controller implements Serializable {

  // Getter/setter omitted
  private MyObject myObject;

  @PostConstruct
  public void onPostConstruct() {

  } 

  public String updateValue() {
    // Persist myObject and return to list page
    return "objects.xhtml?faces-redirect=true&id=" + myObject.getId();
  }
}

  • 现在用户导航到此页面,但没有单击按钮提交表单并保持浏览器窗口打开
  • 同时服务器重启(注意:javax.faces.STATE_SAVING_METHOD设置为client
  • 当服务器再次启动时,用户想要提交表单
  • 在这种情况下,@PostConstruct将调用控制器 bean,但正如预期的那样myObject,转换器不会设置成员,从而导致 NullPointer 访问。

那么是否有任何建议的 JSF 方式来处理这种情况?我希望我已经清楚地表达了自己...

4

1 回答 1

0

是的,@SessionScoped bean 上的行为相同,并且服务器被清理并重新启动。感谢您的链接,它有很大帮助。

在我看来,唯一的解决方案是挂钩@PostConstruct并检查成员是否为空。在这种情况下,我只需要自己重新初始化视图(默认情况下使用转换器完成)。

@PostConstruct
public void onPostConstruct() {

  if (Faces.isPostback() && this.myObject == null) {
    // Load object from database
    final long requestId = Long.valueOf(Faces.getRequestParameter("id"));
    setMyObject(objectService.get(requestId));
  }
}

这是一个正确的假设吗:当我在 view 参数上有一些额外的验证器时,id他们没有明确签入,@PostConstruct因为回发请求传输“原始” id-value,所以这必须是以前验证过的值,所以它不能被用户篡改?

于 2019-12-13T05:17:52.630 回答