相同视图的会话范围 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 的同一实例。您的设置无需更改任何其他内容,所有@Inject
s 都将正常工作。要初始化支持 legendDTO.list
,请使用 @PostConstruct
JSF 注释在 ViewScoped JSF bean 中注释一个方法,并将列表填充逻辑放入其中。您可以安全地添加/删除列表,而无需将其重新初始化为空。但是您必须记住将对此列表的更改提交回数据库。
只是一个想法,作为安全做法,您可能希望显示一个弹出窗口,让您的用户确认他们想要从您的数据库中删除任何内容。干杯
【讨论】:
JSF 2.0 中没有 reReder 标签以上是关于相同视图的会话范围 bean的主要内容,如果未能解决你的问题,请参考以下文章
未使用 URL 参数时在 POST 上重新创建视图范围的 bean