2011-08-25 77 views
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个属性tripIdseats这是相同的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> 

回答

1

链接内容对应于以下标记:

<h:link outcome="/customer/booking.xhtml" value="Book this trip" 
      includeViewParams="true" /> 

过程中为trip.xhtml视图请求的渲染响应阶段中产生。如果您需要URL来包含视图参数值,则必须在用于访问视图的URL中提供这些值,或者您必须在呈现响应阶段完成之前在模型中设置这些值。如果您不执行其中任何一项,则生成的超链接将包含视图参数的默认值。

在简单的话,你必须:

  • 要么确保trip.xhtml观点与必要的参数访问:​​,特别是如果观点是在任何时候的参数进行访问。
  • 或者您必须设置JSF运行时呈现链接之前执行的方法中的值。类中的BookingBean类或@PostConstruct注释方法的构造函数将是设置值的理想位置。在视图中执行操作的情况下,您还可以重置/更新托管bean的其他方法中的bean值。请注意,JSF运行时将调用getTripIdgetSeats以将视图参数tripIdseats的值包含在生成的URL中,因此您还应该验证这些方法的行为。

你,为什么你不能在EL表达式booking.xhtml指定bookingBean,而不是要求你指定的tripBean的所谓意想不到的价值问题是由于一个事实,即link标签的includeViewParams属性,将包括​​的参数而不是from-view。简而言之,JSF运行时将调用bookingBean.getTripId()bookingBean.getSeats()而不是tripBean.getTripId()tripBean.getSeats()。尽管这看起来可能与直觉相反,但您应该明白,JSF规范对待这种情况的方式完全不同。在用户执行的大多数交互中,组件的操作URL是在用户执行操作时生成的,而不是在此之前生成的。另一方面,link标签需要对URL进行抢先计算,因此JSF运行时将其视为“抢先导航”。在构造URL时,必须可以访问与目标视图的视图参数有关的对象,以使URL有意义。在URL中值为0的原因是在此评估过程中创建了一个新的BookingBean实例,并且正在使用默认值。通过使用TripBean代替(并且includeViewParams的大多数示例演示了这一点),您可以非常明显地避免这种情况,或者可以在构建BookingBean对象期间设置值。

+0

trip.xhtml页面可以获取参数tripid和座位。如果我理解的很好,参数可以在Apply Request Values阶段读取。这些被放入更新模型值的TripBean中,并且在渲染 - 响应阶段生成链接。因此,当我将这两个参数提供给trip.xhtml时,预订链接应该生成正确的,对吧?但是,这似乎只发生在booking.xhtml也使用tripBean来捕获参数,而不是当我尝试使用另一个(bookingBean)bean时! – StefK

+0

@Trinorae:你误解了f:paramView。您描述的行为完全是它应该如何工作的,这不是一个错误或问题,因此它不需要解决方法。 f:paramView不是意味着在两个bean之间移动值。它旨在保持源与目标相同。这种行为与其他JSF组件的工作方式是一致的。从任意源生成参数的优雅方式是f:param ...基本上,你试图将一个精心设计的JSF轻松地压缩成你认为“好”的错误,同时拒绝学习。唷。 – fdreger

+0

我想我误解了viewParams的使用!感谢您给我启发。 – StefK

2

f:viewParam的工作方式与h:inputText完全相同。这意味着它使用与源(渲染时)和目标(更新模型时)相同的表达式。如果您有:

<h:inputText value="#{a.test}" /> 

你从来不问“如何从b.foo使inputText读写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> 
+0

我发现这是一个解决方法。但是,在加载trip.xhtml时,您将tripid和座位的值放在tripBean中。您可以使用includeViewParams传递viewParams。那么为什么我不能通过链接尝试用另一个bean来捕获这些参数的值传递给另一个页面? – StefK

+0

@Trinorae:什么“解决方法”?解决什么问题? – fdreger

+0

使用f:param而不是includeViewParams属性 – StefK