相同视图的会话范围 bean

Posted

技术标签:

【中文标题】相同视图的会话范围 bean【英文标题】:Conversation Scoped bean for same view 【发布时间】:2012-08-28 01:45:30 【问题描述】:

我有一个 DTO,它有一个列表。当用户单击添加按钮时,我想向数据表添加新行。但是当我单击 add 时,dto 即构造函数被调用并且值被初始化并且列表大小为 0。该 bean 是对话范围的。我应该在使用会话范围 bean 时开始和结束相同视图的会话吗?我正在使用相同的 bean 进行编辑,它运行良好。使用richfaces 4和jsf 2和ajax时如何解决初始化问题。

查看:

                    <rich:panel id ="dataPnl">
                        <rich:dataTable value="#legendbean.legendDTO.list" var="legend" style="width:100%">

                            <rich:column>
                                <f:facet name="header">
                                    <h:outputText value="SN"/>
                                </f:facet>
                                <h:inputText value="#legend.sn"/>
                            </rich:column>

                            <rich:column>
                                <f:facet name="header">
                                    <h:outputText value="Description"/>
                                </f:facet>
                                <h:inputText value="#legend.desc"/>
                            </rich:column>


                            <rich:column>
                                <a4j:commandLink value="Add" actionListener="#legendbean.addLegendRange()" render="nisForm:dataPnl"/>
                                <h:outputText value=" / "/>
                                <a4j:commandLink value="Remove" actionListener="#legendbean.removeLegendRange(legend)" render="nisForm:dataPnl"/>
                            </rich:column>

                        </rich:dataTable>
                    </rich:panel>                 

豆:

@Named("legendbean")
@ConversationScoped
public class LegendController implements Serializable 

    LegendDTO legendDTO = new LegendDTO();
    String selectedLegend;
    boolean edit;
    @Inject
    private Conversation conversation;

    public boolean isEdit() 
        return edit;
    

    public void setEdit(boolean edit) 
        this.edit = edit;
    

    public LegendController() 
        Logger.getLogger(LegendController.class.getName()).warning("The value of Edit is : " + edit);
        if (!edit) 
            legendDTO.getList().add(new Legend());
            Logger.getLogger(LegendController.class.getName()).warning("The size of list" + legendDTO.getList().size());
        
    

    public LegendDTO getLegendDTO() 
        return legendDTO;
    

    public void setLegendDTO(LegendDTO legendDTO) 
        this.legendDTO = legendDTO;
    

    public void addLegendRange() 
        Logger.getLogger(LegendController.class.getName()).warning("List Size " + legendDTO.getList().size());
        legendDTO.getList().add(new Legend());
        Logger.getLogger(LegendController.class.getName()).warning("List Size " + legendDTO.getList().size());
    

    public void removeLegendRange(Legend legend) 
        if (legendDTO.getList().size() != 1) 
            legendDTO.getList().remove(legend);
        
    

    public String saveLegend() 
        Logger.getLogger(LegendController.class.getName()).warning("Save Legend Edit" + edit);
        LegendDAO dao = new LegendDAO();
        if (dao.addLegend(legendDTO, edit)) 
            if (edit) 
                conversation.end();
                edit = false;
                Logger.getLogger(LegendController.class.getName()).warning("Save Legend Edit" + edit);
                return "VIEWLEGEND";
             else 
                legendDTO = new LegendDTO();
                legendDTO.getList().add(new Legend());              
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Saved !"));
                return "";
            
         else 
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Could Not Save Confim if you have already defined Legend " + legendDTO.getLegendName() + "!"));
            return "";
        
    

    public List<LegendDTO> getLegends() 
        LegendDAO dao = new LegendDAO();
        return dao.getLegendDTO();
    

    //All function from here are for legend  delete
    public void deleteLegendType(LegendDTO dto) 
        LegendDAO dao = new LegendDAO();
        if (dao.deleteLegendType(dto.getLegendName())) 
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Deleted !"));
         else 
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Deleted Error !"));
        
    

    //All function from here is to legend edit
    public String editLegendType(LegendDTO dto) 
        conversation.begin();
        edit = true;
        legendDTO = dto;
        LegendDAO dao = new LegendDAO();
        dto.getList().clear();
        try 
            List<Legend> legends = dao.getDetailForEditLegend(dto.getLegendName());
            dto.setList(legends);
         catch (SQLException ex) 
            Logger.getLogger(LegendController.class.getName()).warning("SQL EXception has occoured");
        
        Logger.getLogger(LegendController.class.getName()).warning("The size of list" + dto.getList().size());
        return "addLegend";
    

    public String cancel() 
        conversation.end();
        return "VIEWLEGEND";
    

【问题讨论】:

您使用的是 RichFaces 2 吗?也许你的意思是 JSF 2 和 RichFaces 4.x @LuiggiMendoza 是的 JSF 2 richfaces 4.x 使用这些组合有什么问题吗?? 不,只是澄清您帖子中的条款。 【参考方案1】:

是的,您需要start 一个长时间运行的对话,以使您的对话(和对话范围的 bean)跨越多个请求。否则会话在 JSF 请求结束时被终止(默认情况下会话是短暂的:请参阅 ConversationScoped javadoc)。

在这种情况下,一个常见的解决方案是使用ViewScoped bean,但注释是 JSF2 特定的,不在 CDI 中呈现(你可以将它移植到 CDI 或使用 seam-faces 模块,更多细节:@ 987654324@).

【讨论】:

感谢您的回复,我将其转换为查看范围,但我的添加页面仍有问题:(我已添加添加页面代码 @Kitex 什么问题?和以前一样:每次请求都会重新创建 bean? 感谢您的回复 :) 现在可以了。对话范围的bean不可能吗?我不得不为 Add 重新创建新的 bean 和页面。我希望全部由单个 bean 控制。 @Kitex 这种行为可以使用会话范围来模拟,例如在加载要显示的实体列表时需要调用Conversation.begin,在离开页面时调用Conversation.end(例如在您返回"VIEWLEGEND"时的情况。【参考方案2】:

如果您不受限于使用 CDI/Seam 注释,您可以将 bean 更改为使用 javax.faces.bean.ManagedBean 包中的 @ManagedBean(name="legendbean"),然后在您的类上使用 @ViewScoped 注释,以保证只要用户在同一页面上,您将使用托管 bean 的同一实例。您的设置无需更改任何其他内容,所有@Injects 都将正常工作。要初始化支持 legendDTO.list,请使用 @PostConstruct JSF 注释在 ViewScoped JSF bean 中注释一个方法,并将列表填充逻辑放入其中。您可以安全地添加/删除列表,而无需将其重新初始化为空。但是您必须记住将对此列表的更改提交回数据库。

只是一个想法,作为安全做法,您可能希望显示一个弹出窗口,让您的用户确认他们想要从您的数据库中删除任何内容。干杯

【讨论】:

JSF 2.0 中没有 reReder 标签

以上是关于相同视图的会话范围 bean的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何从会话中检索登录用户并将其传递给我的业务层?

未使用 URL 参数时在 POST 上重新创建视图范围的 bean

您如何在当前视图(范围)中找到 CDI bean?

从视图范围的托管 bean JSF 填充数据表

当会话在 websphere 中失效时,Spring 视图范围不会被破坏

返回支持 bean 中的相同视图,我应该返回 null 或空字符串还是视图 ID?