如果您的 Servlet 容器支持最低 Servlet 3.0 / EL 2.2,则只需将其作为 UICommand
组件或 AjaxBehavior
标记的 action/listener 方法的参数传递即可。例如:
<h:commandLink action="#{bean.insert(item.id)}" value="insert" />
结合以下内容:
public void insert(Long id) {
}
这仅需要在表单提交请求时保留数据模型。最好的方法是通过@ViewScoped
将bean放置在视图范围内。
你甚至可以传递整个item对象:
<h:commandLink action="#{bean.insert(item)}" value="insert" />
使用:
public void insert(Item item) {
}
如果您提供支持此功能的EL实现,例如JBoss EL,则在Servlet 2.5容器上也可以实现这一点。有关配置详细信息,请参见此答案。
在UICommand
组件中使用<f:param>
,它会添加一个请求参数。
<h:commandLink action="#{bean.insert}" value="insert">
<f:param name="id" value="#{item.id}" />
</h:commandLink>
如果你的bean是请求作用域,让JSF通过@ManagedProperty
来设置它。
@ManagedProperty(value="#{param.id}")
private Long id
或者,如果您的Bean具有更广泛的范围或者您想要更细粒度的验证/转换,请在目标视图上使用<f:viewParam>
,另请参见f:viewParam vs @ManagedProperty:
<f:viewParam name="id" value="#{bean.id}" required="true" />
无论如何,这样做的好处是数据模型不一定需要在表单提交时保留(当您的bean是请求范围时)。
在UICommand
组件中使用<f:setPropertyActionListener>
。优点是当bean具有比请求范围更广泛的范围时,这可以消除访问请求参数映射的需求。
<h:commandLink action="#{bean.insert}" value="insert">
<f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
</h:commandLink>
与...相结合
private Long id; // +setter
在操作方法中,它将仅通过属性 id
可用。这只需要在表单提交请求中保持数据模型的完整性。最好使用 @ViewScoped
将 bean 放入视图作用域。
将数据表值绑定到 DataModel<E>
,然后再将其包装为项目。
<h:dataTable value="#{bean.model}" var="item">
使用
private transient DataModel<Item> model;
public DataModel<Item> getModel() {
if (model == null) {
model = new ListDataModel<Item>(items);
}
return model;
}
(如果你在视图或会话作用域的Bean中使用,则必须将其设置为transient
并在getter方法中延迟实例化,因为没有实现Serializable
)
然后,你可以通过DataModel#getRowData()
访问当前行,无需传递任何内容(JSF根据点击命令链接/按钮的请求参数名称确定行)。
public void insert() {
Item item = model.getRowData();
Long id = item.getId();
}
这还需要保留数据模型以进行表单提交请求。最好使用 @ViewScoped
将Bean放在视图范围内。
使用 Application#evaluateExpressionGet()
方法以编程方式评估当前的 #{item}
。
public void insert() {
FacesContext context = FacesContext.getCurrentInstance();
Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
Long id = item.getId();
}