向Request Scoped Bean中的List添加项目



我有一个支持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 bean管理注释@ManagedBean,那么您可以通过通过@ViewScoped将bean放置在视图范围内来解决这个问题。

@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;
    // ...

参见:

  • 如何选择合适的bean scope?
  • 推荐的JSF 2.0 CRUD框架

如果您正在使用JSF 2,您应该使用ViewScoped bean。

相关内容

  • 没有找到相关文章

最新更新