1

有没有办法根据请求 URL 显示特定的 JSF 页面?

假设我有一个 JSF 页面“ details.xhtml”。托管 bean " detailsBean" 有一个对象列表,其中每个对象都有自己的 ID。现在,如果用户请求页面“ ../details.xhtml?id=1”,则应在列表中查询 ID 为 1 的对象,并显示该对象的结果详细信息页面。

我已经写了一个转换器实现类,它可以从对象转换为ID,反之亦然,但我不知道如何正确使用它。我是否必须通过 JAX-RS 规范才能工作,还是有更简单的解决方案?

4

2 回答 2

4

在 JSF 中,您可以通过使用所谓的视图参数来做到这一点。metadata您在Facelet 的部分中声明这些:

<f:metadata>         
    <f:viewParam name="id" value="#{yourBean.yourObject}" label="id" 
        converter="yourObjectConverter" 
    />
</f:metadata>

这将从id请求 URL 中获取 URL 参数。例如,如果您请求与 一起出现的页面localhost:8080/mypage.jsf?id=1,那么1将被交给yourObjectConverter并且该转换器返回的任何内容都将设置在 中yourBean.yourObject

因此,您的支持 bean 将获得转换后的对象。无需使用相同的查询代码一遍又一遍地污染您的支持 bean。

@ManagedBean
public class YourBean {

    private SomeObject someObject;

    public void setYourObject(SomeObject someObject) {
        this.someObject = someObject;
    }
}

如果您的支持 bean 是视图范围的,您可能希望使用OmniFaces变体viewParam,否则它将在每次回发后进行不必要的转换(如果您的转换器执行数据库查询,您肯定不希望这样做)。

完整的工作示例:

进一步阅读:

于 2012-11-11T15:47:56.110 回答
-1

You can achieve this with plain JSF with the following steps

  1. Capture the ID in the request to determine what object is being queried for in your DetailsBean from the request parameter. There are many ways to achieve this, one of which is adding the following annotation to your managed bean (this is currently only permitted for a @RequestScoped bean, see why here).

       @ManagedProperty(value="#{param.id}")
       int requiredObjectId;
    

    The annotation above will capture the id parameter from the request and assign it to the requiredObjectId variable.

  2. Using the captured Id, setup your object in your bean in a @PostConstruct method

       @PostConstruct
       public void queryForObject(){
    
       //use the requiredObjectId variable to query and setup the object in the backing bean
    
       }
    

    The object retrieved should be assigned as an instance variable of your managed bean

  3. In your view, you could then reference the queried object that has been setup in the backing bean

      <h:panelGrid columns="2">
         <h:outputText value="Title"/>
         <h:outputText value="#{detailsBean.selectedObject.title}"/>
      </h:panelGrid>
    

If your bean is in a scope broader than the request scope, you'll need a combination of constructs to cleanly pull that request parameter before view rendering.

  1. Capture the request parameter within the JSF view itself using

    <f:metadata>
     <f:viewParam name="id" value="#{detailsBean.requiredObjectId}" required="true" requiredMessage="You must provide an Object Id"/>         
    </f:metadata>
    
        **OR**
    
  2. Due to the nature of JSF Lifecycle processing, doing the above alone may not make the value available for your use in time for object setup. You could use the following instead.

     <f:metadata>
        <f:event type="preRenderView" listener="#{detailsBean.setObjectId}" />         
    </f:metadata>
    

    What we've done here is specify a method (that captures the id) in the backing bean that must be executed before the view is rendered, ensuring that the id parameter is available as at the time you need it. Proceed with step 3, only if you're using <f:event/> above.

  3. In the backing bean, you now define the setObjectId method

      public void setObjectId(){
    
      Map<String,String> requestParams =      FacesContext.getExternalContext().getRequestParameterMap();
      requiredObjectId =  Integer.parseInt(requestParams.get("id"));
    
      }
    

Note that the above option is generally a work around/hack and not a clean solution as such

于 2012-11-11T15:28:52.810 回答