查看不同bean中的参数

时间:2011-08-25 09:34:27

标签: jsf navigation viewparams

我有一个名为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个属性tripIdseatsTripBean相同,但是当我尝试点击此链接时,我只看到一个席位 - 参数设置为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>

2 个答案:

答案 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视图,特别是如果要始终使用参数访问视图。
  • 或者必须在JSF运行时呈现链接之前执行的方法中设置值。 BookingBean类的构造函数或类中的@PostConstruct注释方法将是设置值的理想位置。如果在视图中执行操作,您还可以在托管bean的其他方法中重置/更新bean的值。请注意,JSF运行时将调用getTripIdgetSeats以在结果URL中包含视图参数tripIdseats的值,因此您应该验证这些方法也是如此。

您的问题是,为什么您无法在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对象期间设置值。