2

我有一个页面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" />

我期望的是当我单击此链接时获得的 URL 类似于"/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,但是当我现在尝试单击链接时,我只看到一个设置为 0 的席位参数。seatsTripBean"/customer/booking.jsf?seats=0"

有谁知道为什么当我尝试使用另一个 bean 来存储它们时,我似乎无法将视图参数传递到另一个页面?如果无法将其存储在另一个 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>
4

2 回答 2

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>
于 2011-08-25T10:38:09.390 回答
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 运行时将调用getTripId并将getSeats视图参数的值包含tripIdseats结果 URL 中,因此您还应该验证这些方法的行为。

您关于为什么无法bookingBean在 EL 表达式中指定 的问题booking.xhtml,而是要求您指定所谓的意外值,tripBean是因为标签的includeViewParams属性link将包括的参数to-view而不是from-view. 简单地说,JSF 运行时将调用bookingBean.getTripId()andbookingBean.getSeats()而不是tripBean.getTripId()and tripBean.getSeats()

虽然这可能看起来有悖常理,但您应该了解 JSF 规范对这种情况的处理方式完全不同。在用户执行的大多数交互中,组件的操作 URL 是在用户执行操作时生成的,直到那时才生成。另一方面,link标签需要对 URL 进行抢先计算,因此 JSF 运行时将其视为“抢先导航”。在构建 URL 时,与目标视图的视图参数相关的对象必须是可访问的,这样 URL 才有意义。URL 中的值为 0 的原因是,BookingBean在此评估期间创建了一个新实例,并且正在使用默认值。你可以很明显地通过使用TripBean取而代之(大多数 includeViewParams 示例都证明了这一点),或者您可以在BookingBean对象的构造过程中设置值。

于 2011-08-25T10:28:21.527 回答