我有一个名为trip.xhtml
的页面,我使用以下代码从URL中获取参数:
<f:metadata>
<f:viewParam name="tripid" value="#{tripBean.tripId}" />
<f:viewParam name="seats" value="#{tripBean.seats}" />
<f:event type="preRenderView" listener="#{tripBean.processParams}" />
</f:metadata>
TripBean
看起来像这样(简化):
@ManagedBean
@RequestScoped
public class TripBean implements Serializable {
private static final long serialVersionUID = -4885781058258859229L;
private Long tripId;
private int seats;
// Getters and setters for tripId and seats
在trip.xhtml
页面的底部,我有h:link
:
<h:link outcome="/customer/booking.xhtml" value="Book this trip"
includeViewParams="true" />
我期望点击此链接时获得的网址类似于"/customer/booking.jsf?tripid=2&seats=1"
。仅当我将以下代码放在booking.xhtml
页面上时才会出现这种情况:
<f:metadata>
<f:viewParam name="tripid" value="#{tripBean.tripId}" />
<f:viewParam name="seats" value="#{tripBean.seats}" />
</f:metadata>
虽然我真正想要的是使用另一个bean。将代码更改为:
<f:metadata>
<f:viewParam name="tripid" value="#{bookingBean.tripId}" />
<f:viewParam name="seats" value="#{bookingBean.seats}" />
</f:metadata>
BookingBean
还有2个属性tripId
和seats
与TripBean
相同,但是当我尝试点击此链接时,我只看到一个席位 - 参数设置为0.("/customer/booking.jsf?seats=0"
)
当我尝试使用另一个bean存储它们时,有没有人知道为什么我似乎无法将viewparams传递给另一个页面?如果无法将其存储在另一个bean中,我如何将TripBean
中的值放在BookingBean
中?
我使用的快速解决方法:
不使用includeViewParams="true"
,但手动向链接添加参数(见下文)“修复”了问题。虽然我仍然想知道为什么它不适用于includeViewParams
!
<h:link outcome="/customer/booking.xhtml" value="#{msg['page.trip.booking']}">
<f:param name="tripid" value="#{tripBean.tripId}" />
<f:param name="seats" value="#{tripBean.seats}" />
</h:link>
答案 0 :(得分:2)
f:viewParam
的工作原理与h:inputText
完全相同。这意味着它使用相同的表达式作为源(渲染时)和目标(更新模型时)。如果你有:
<h:inputText value="#{a.test}" />
你永远不会问“如何从inputText
读取b.foo
并写入a.test
”,但是每个人似乎都期望f:viewParam
出现这种行为。
无论如何,有一个简单的答案。要附加任何值以进行链接,您只需使用f:param
:
<h:link outcome="/customer/booking.xhtml" value="Book this trip" >
<f:param name="tripid" value="#{bookingBean.tripId}" />
<f:param name="seats" value="#{bookingBean.seats}" />
</h:link>
答案 1 :(得分:1)
与以下标记对应的链接内容:
<h:link outcome="/customer/booking.xhtml" value="Book this trip"
includeViewParams="true" />
是在trip.xhtml
视图请求的呈现 - 响应阶段生成的。如果需要URL包含视图参数值,则必须在用于访问视图的URL中提供这些值,或者必须在渲染响应阶段完成之前在模型中设置这些值。如果您不执行其中任何一项,则生成的超链接将包含视图参数的默认值。
简单来说,你必须:
trip.xhtml
访问trip.xhtml?tripid=x&seats=y
视图,特别是如果要始终使用参数访问视图。BookingBean
类的构造函数或类中的@PostConstruct
注释方法将是设置值的理想位置。如果在视图中执行操作,您还可以在托管bean的其他方法中重置/更新bean的值。请注意,JSF运行时将调用getTripId
和getSeats
以在结果URL中包含视图参数tripId
和seats
的值,因此您应该验证这些方法也是如此。您的问题是,为什么您无法在bookingBean
的EL表达式中指定booking.xhtml
,而是要求您指定tripBean
的所谓意外值,这是因为includeViewParams
标记的link
属性将包含to-view
而非from-view
的参数。简而言之,JSF运行时将调用bookingBean.getTripId()
和bookingBean.getSeats()
而不是tripBean.getTripId()
和tripBean.getSeats()
。
虽然这看似违反直觉,但您应该理解JSF规范对此方案的处理方式完全不同。在用户执行的大多数交互中,当用户执行动作时生成组件的动作URL,而不是在此之前。另一方面,link
标记需要抢先计算URL,因此JSF运行时将此视为“先发制人导航”。在构造URL时,必须可以访问与目标视图的视图参数有关的对象,以使URL有意义。 URL中值为0的原因是在此评估期间创建了新的BookingBean
实例,而是使用默认值。您可以通过使用TripBean
代替(并且大多数includeViewParams示例演示此内容)来避免这种情况,或者您可以在构造BookingBean
对象期间设置值。