【问题标题】:Add items to List in Request Scoped Bean将项目添加到请求范围 Bean 中的列表
【发布时间】:2013-01-04 14:21:21
【问题描述】:

我有一个如下的支持 bean:

@Named
@RequestScoped
public class ClientNewBackingBean {

    @Inject
    private ClientFacade facade;
    private Client client;

Client 类具有 List<Child> childrenList 属性等。当使用new ArrayList() 设置childrenList 时,我可以创建一个新的Client

在视图中,我有一个输入文本字段和一个Add Child 按钮。该按钮的属性actionListener=#{clientNewBackingBean.addChild()} 实现为:

public void addChild() {

    if(client.getChildrenList() == null) {
        client.getChildrenList(new ArrayList());
    }

    Child c = new Child("John Doe");

    client.getChildrenList().add(c);
}

每次单击 Add Child 按钮时,都会重新创建 bean,并且视图只显示一个 John Doe 孩子(我相信,由于它是 Request 范围的)。除了将bean范围更改为Session之外,还有其他方法可以解决这个问题吗?

【问题讨论】:

    标签: jsf scope cdi


    【解决方案1】:

    如果您使用标准 JSF bean 管理注释 @ManagedBean,您可以通过将 bean 放置在 @ViewScoped 的视图范围内来解决它。

    @ManagedBean
    @ViewScoped
    public class ClientNewBackingBean implements Serializable {
    
        @EJB
        private ClientFacade facade;
    
        // ...
    

    在 CDI 中,@ViewScoped 不存在,但最接近的替代是 @ConversationScoped。您只需要自己启动和停止即可。

    @Named
    @ConversationScoped
    public class ClientNewBackingBean implements Serializable {
    
        @Inject
        private Conversation conversation;
    
        // ...
    
        @PostConstruct
        public void init() {
            conversation.begin();
        }
    
        public String submitAndNavigate() {
            // ...
    
            conversation.end();
            return "someOtherPage?faces-redirect=true";
        }
    
    }
    

    您还可以使用 CDI 扩展 MyFaces CODI,它将透明地桥接 JSF @ViewScoped 注释以与 @Named 一起正常工作:

    @Named
    @ViewScoped
    public class ClientNewBackingBean implements Serializable {
    
        @Inject
        private ClientFacade facade;
    
        // ...
    

    CODI 替代方法是使用@ViewAccessScoped,只要后续请求引用同一个托管 bean,它就会一直存在,而与使用的物理视图文件无关。

    @Named
    @ViewAccessScoped
    public class ClientNewBackingBean implements Serializable {
    
        @Inject
        private ClientFacade facade;
    
        // ...
    

    另见:

    【讨论】:

    • 已更改为 MyFaces CODI 方法并且可以正常工作。我会坚持下去的。
    • MyFaces CODI 将 @ViewScoped 连接到 CDI。因此,您不必使用不同的注释。 @ViewAccessScoped 是一个完全不同的范围,具有不同的行为。 CODI 范围 99% 是更好的选择!
    • 只是 JSF 标准注释,是的。
    • #1 我不是 CODI 开发人员之一(只是“超级用户”)#2 这是 @ViewScoped 的正确行为(在 JSF 规范中定义)#3 恕我直言 @ViewScoped仅对一些非常罕见的情况有用。 @ViewAccessScope 符合您的预期
    • @ViewScoped 由 JSF 规范指定。并且绑定到一个视图。您不能在不同页面上使用存储的值 -> 如果您有一个页面并且对同一页面有很多 AJAX 请求,并且您不需要下一页上的值,则应该使用它。 @ViewAccessScoped 是 CODI 发明的自定义 CDI 范围。您的 bean 存在于 next 逻辑(不是 HTTP - 如果您触发带有重定向的导航,则可能是 2 个 HTTP 请求)请求,只要它们在逻辑请求期间被触及。如果需要,您也可以提前(手动)销毁它们。
    【解决方案2】:

    如果您使用的是 JSF 2,则应使用 ViewScoped bean。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-13
      • 2013-01-21
      • 2011-11-11
      • 2015-08-16
      • 1970-01-01
      • 2012-05-26
      • 1970-01-01
      相关资源
      最近更新 更多