【问题标题】:JSF navigation parameter dependencyJSF 导航参数依赖
【发布时间】:2012-01-09 00:50:45
【问题描述】:

我正在尝试在 JSF 中实现这个简单的示例:有一个 user.xhtml 页面可以使用 id 参数(user.xhtml?id=3 / user.xhtml? id=12)。根据 id 页面应该显示具有指定 id 的用户的信息。

@ManagedBean
@RequestScoped
public class OverviewController extends BaseController{

private UserDetails details;

@PostConstruct
@SuppressWarnings("unused")
private void init(){
    Integer userId = getIntegerParam(Constants.PARAMETER_USER); //this brings the value of the user parameter as an Integer
    if (userId != null){
        UserService userService = new UserService();
        details = userService .getDetails(userId);
    }
}

//GET & SET

}

在 xhtml 文件中,我有以下内容:

<div>
    Name: #{overviewController.details.name}
    City: #{overviewController.details.city}
</div>

此处引导控件的链接:

<h:link outcome = "user.xhtml" value = "details">
    <f:param name = "user" value = "2">
</h:link>

我的印象是,当通过 EL 访问overviewController 时,ManagedBean 将被构造,而在@PostConstruct 中,details 将被初始化。但我没有得到任何结果,甚至没有构建overviewController。 我的问题更进一步,我问如何实现基于多个参数或排序的搜索?

【问题讨论】:

  • OverviewController 类是用@ManagedBean(name="overviewController") 还是@Named("overviewController") 注释的?
  • 另外,应该还有范围注解,比如@RequestScoped。
  • 也没有必要。如果名称未声明,JSF 将采用类名,将类的第一个字母转换为小写字母并将其作为 bean 的名称。
  • 好的,那么getIntegerParam方法定义在哪里?
  • 是的。定义了所有需要的方法。此外,我创建了一个 PhaseListener,我看到除了 restore (1) 和 render(6) 之外的任何阶段都没有被调用。也就是说,我相信,因为

标签: java jsf


【解决方案1】:

至于您的具体问题,您的@PostConstruct 被错误地声明为private 而不是public。

至于您的具体功能要求,这并不完全正确。您需要在目标页面中使用 &lt;f:viewParam&gt; 来将用户 ID 请求参数设置为支持 bean 中的 UserDetails 属性。

user.xhtml

<f:metadata>
    <f:viewParam id="param_id" name="id" value="#{overviewController.details}"
        converter="userDetailsConverter" converterMessage="Bad request, unknown user"
        required="true" requiredMessage="Bad request, use a link from within the system"
    />
</f:metadata>
<h:message for="param_id" />

UserDetailsConverter

@FacesConverter("userDetailsConverter")
public class UserDetailsConverter implements Converter {

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (!(value instanceof UserDetails) || ((UserDetails) value).getId() == null) {
            return null;
        }

        return String.valueOf(((UserDetails) value).getId());
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null || !value.matches("\\d+")) {
            return null;
        }

        UserDetails details = new UserService().getDetails(Integer.valueOf(value));

        if (details == null) {
            throw new ConverterException(new FacesMessage("Unknown user ID: " + value));
        }

        return details;
    }

}

OverviewController

private UserDetails details; // Getter+setter

另见:

【讨论】:

  • 谢谢!你知道为什么我的例子中的@PostConstruct 永远不会被调用吗?
  • 因为您声明它是 private 而不是 public。
  • 我还有一个问题。我放弃了您的示例,但收到以下警告:警告:JSF1090:组件 j_idt26 的导航案例未解决。我猜我没有正确使用 viewParam 标签对吗?
  • 页面中的某处&lt;h:link outcome&gt; 或&lt;h:button outcome&gt; 没有正确的outcome 值。相应的组件具有客户端 ID j_idt26。签入生成的 HTML 源代码以追溯 Facelet 源代码中的原始罪魁祸首。这与&lt;f:viewParam&gt; 无关。
【解决方案2】:

好吧,我不知道你的方法getIntegerParam实际上是如何工作的,但我通常是这样实现处理查询参数的。

编辑:我实际上不确定在设置userId 属性后是否真的会调用init()(我通常直接从setter 调用它),但它可能应该因为@PostConstruct方法是在依赖注入后调用的。

@ManagedBean
@RequestScoped
public class OverviewController extends BaseController {

    @ManagedProperty("#{param['userId']}")
    private String userId; // not sure if can automatically be parsed to Integer

    private UserDetails details;

    @PostConstruct
    private void init() {
        if (userId != null){
            UserService userService = new UserService();
            details = userService .getDetails(userId);
        }
    }

    // getter & setter for userId
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-08
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    相关资源
    最近更新 更多