@Inject 通过 URL 将参数传递给 CDI @Named bean [英] @Inject to pass params to a CDI @Named bean via URL

查看:28
本文介绍了@Inject 通过 URL 将参数传递给 CDI @Named bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我不能将@ManagedProperty 注释与@Named 一起使用,因为@ManagedProperty 在CDI(?) 中不起作用,那么您如何将URL 中的参数传递给facelets 客户端?在我的代码中,我想通过后退"和前进"按钮将 javax.mail.getMessageNumber() 传递给 details.xhtml.

If I cannot use the @ManagedProperty annotation with @Named, because @ManagedProperty doesn't work in CDI(?), then how do you pass params in the URL to the facelets client? In my code, I want to pass javax.mail.getMessageNumber() to details.xhtml through the "back" and "forward" buttons.

我知道应该使用@Inject,但是注入的是什么以及如何注入?

I understand that @Inject should be used, but what is being injected and how, please?

从 glassfish 日志中,id 始终为 0,这很奇怪.即使单击前进",无论单击多少次按钮,id 也永远不会超过 1.当然,这只是问题的一个症状.期望的输出当然是前进到下一个消息.

From the glassfish logs, id is always 0, which is quite odd. Even when "forward" is clicked, id never gets above 1 no matter how many times the button is clicked. Of course, that's merely a symptom of the problem. The desired output, of course, is to advance to the next Message.

也许将 Message 或至少是 int 放入会话中?

Perhaps put the Message, or at least the int, into the session?

客户如下:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                template="./template.xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:c="http://java.sun.com/jsp/jstl/core"
                xmlns:f="http://java.sun.com/jsf/core">
    <ui:define name="top">
        <h:form>
            <h:form>
                <h:outputLink id="link1" value="detail.xhtml">
                    <f:param name="id" value="#{detail.back()}" />
                    <h:outputText value="back" />
                </h:outputLink>
            </h:form>
        </h:form>
        <h:form>
            <h:outputLink id="link1" value="detail.xhtml">
                <f:param name="id" value="#{detail.forward()}" />
                <h:outputText value="forward" />
            </h:outputLink>
        </h:form>
    </ui:define>
    <ui:define name="content">
        <h:outputText value="#{detail.content}"></h:outputText>
    </ui:define>
</ui:composition>

和豆子一样:

package net.bounceme.dur.nntp;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.RequestScoped;
import javax.faces.bean.ManagedProperty;
import javax.inject.Named;
import javax.mail.Message;

@Named
@RequestScoped
public class Detail {

    private static final Logger logger = Logger.getLogger(Detail.class.getName());
    private static final Level level = Level.INFO;
    @ManagedProperty(value = "#{param.id}")
    private Integer id = 0;
    private Message message = null;
    private SingletonNNTP nntp = SingletonNNTP.INSTANCE;

    public Detail() {
        message = nntp.getMessage(id);
    }

    public int forward() {
        logger.log(level, "Detail.forward.." + id);
        id = id + 1;
        logger.log(level, "..Detail.forward " + id);
        return id;
    }

    public int back() {
        logger.log(level, "Detail.back.." + id);
        id = id - 1;
        logger.log(level, "..Detail.back " + id);
        return id;
    }

    public Message getMessage() {
        return message;
    }

    public String getContent() throws Exception {
        return message.getContent().toString();
    }
}

推荐答案

这仅适用于在 JSF 2.3 中引入的 javax.faces.annotation.ManagedProperty.

This works only with the in JSF 2.3 introduced javax.faces.annotation.ManagedProperty.

@Inject @ManagedProperty("#{param.id}")
private String id;

现已弃用的javax.faces.bean.ManagedProperty 注释仅适用于 JSF @ManagedBean 类.IE.在由 JSF 管理的实例中.它不适用于由 CDI @Named 管理的实例.此外,您还犯了另一个错误:您试图根据构造函数中的托管属性准备 Message.如果它是一个真正的 @ManagedBean,那也是行不通的.在构造过程中托管属性不可用,仅仅是因为在调用构造函数之前无法调用 setter 方法.您应该为此使用 @PostConstruct 方法.

The now deprecated javax.faces.bean.ManagedProperty annotation works only in JSF @ManagedBean classes. I.e. in instances which are managed by JSF. It does not work in instances which are managed by CDI @Named. Further, you've made another mistake: you're trying to prepare the Message based on the managed property in the constructor. If it were a real @ManagedBean, that would also not have worked. The managed property is not available during construction, simply because it's not possible to call the setter method before the constructor is called. You should have used a @PostConstruct method for this.

如果您无法升级到 JSF 2.3,则需要创建自定义 CDI 注释.此博客中发布了一个具体示例.以下是相关性的摘录:

If you cannot upgrade to JSF 2.3, you'd need to create a custom CDI annotation. A concrete example is posted in this blog. Here's an extract of relevance:

自定义@HttpParam注解:

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface HttpParam {
    @NonBinding
    public String value() default "";
}

注解值生产者:

public class HttpParamProducer {

    @Inject
    FacesContext facesContext;

    @Produces
    @HttpParam
    String getHttpParameter(InjectionPoint ip) {
        String name = ip.getAnnotated().getAnnotation(HttpParam.class).value();
        if ("".equals(name)) name = ip.getMember().getName();
        return facesContext.getExternalContext()
                .getRequestParameterMap()
                .get(name);
    }
}

使用示例:

@Inject @HttpParam
private String id;

JSF 实用程序库 OmniFaces 有一个 @Param 正是为了这个目的,内置对 JSF 转换和验证的支持.

JSF utility library OmniFaces has a @Param for exactly this purpose, with builtin support for JSF conversion and validation.

或者,您也可以从 Detail 托管 bean 中的外部上下文中手动获取请求参数.推荐的托管 bean 初始化方法是使用 @PostConstruct 方法,而不是构造函数,因为构造函数可以用于与托管 bean 创建完全不同的目的:

Alternatively, you can also manually grab the request parameter from the external context in the Detail managed bean. The recommended way to do managed bean initialization is to use a @PostConstruct method, not the constructor, as the constructor could be used for completely different purposes than managed bean creation:

@PostConstruct
public void init() {
    String id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");
    // ...
}

<小时>

另一种方式,IMO 也更适合这种特殊情况,是使用 这也允许您直接将 ID 转换为 Message自定义转换器.


Another way, IMO also more suitable for this particular case, is to use <f:viewParam> which also allows you to convert the ID to Message directly by a custom converter.

<f:metadata>
    <f:viewParam name="id" value="#{detail.message}" converter="messageConverter" />
</f:metadata>

只要

@Named
public class Detail {

    private Message message;

    // Getter+setter
}

和一个

@FacesConverter("messageConverter")
public class MessageConverter implements Converter {

    // Convert string id to Message object in getAsObject().
    // Convert Message object to string id in getAsString().

}

另见

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆