簡體   English   中英

@Inject 通過 URL 將參數傳遞給 CDI @Named bean

[英]@Inject to pass params to a CDI @Named bean via URL

如果我不能將 @ManagedProperty 注釋與 @Named 一起使用,因為 @ManagedProperty 在 CDI 中不起作用(?),那么如何將 URL 中的參數傳遞給 facelets 客戶端? 在我的代碼中,我想通過“后退”和“前進”按鈕將 javax.mail.getMessageNumber() 傳遞給 details.xhtml。

我知道應該使用@Inject,但是注入了什么以及如何注入?

從 glassfish 日志中,id 始終為 0,這很奇怪。 即使單擊“前進”,無論單擊按鈕多少次,id 都不會超過 1。 當然,這只是問題的表象。 想要的output,當然是為了前進到下一條Message。

也許將消息或至少是 int 放入 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

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

現在已棄用的javax.faces.bean.ManagedProperty注釋僅適用於 JSF @ManagedBean類。 即在由 JSF 管理的實例中。它在由 CDI @Named管理的實例中不起作用。 此外,您還犯了另一個錯誤:您試圖根據構造函數中的托管屬性准備Message 如果它是一個真正的@ManagedBean ,那也不會奏效。 托管屬性在構造期間不可用,原因很簡單,因為在調用構造函數之前不可能調用 setter 方法。 您應該為此使用@PostConstruct方法。

如果無法升級到 JSF 2.3,則需要創建自定義 CDI 注釋。 此博客中發布了一個具體示例。 這是相關的摘錄:

自定義@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 轉換和驗證。


或者,您也可以從Detail托管 bean 的外部上下文中手動獲取請求參數。 進行托管 bean 初始化的推薦方法是使用@PostConstruct方法,而不是構造函數,因為構造函數用於與創建托管 bean 完全不同的目的:

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

另一種方法,IMO 也更適合這種特殊情況,是使用<f:viewParam> ,它還允許您通過自定義轉換器直接將 ID 轉換為Message

<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().

}

也可以看看

首先,解釋外來部分——Glassfish 使用 JBoss Weld 作為它的 CDI 實現,Oracle 沒有開發自己的實現。

關於錯誤消息的含義:FacesContext 根本無法通過@Inject注入。 對此有一個相當古老的功能請求,我認為 Seam 或 Solder 提供了一個生產者。 但是沒有必要為此集成任何一個庫。 通過FacesContext.getCurrentInstance()訪問面上下文,就像在普通托管 bean 中一樣。

我問的是做一件簡單事情的復雜方法。 在 CDI 中,要傳遞參數,您不能使用 @ManagedProperty,正如 BalusC 上面所解釋的那樣。 相反,您只需按如下方式設置您的 xhtml 文件:

<?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:commandButton action="#{messages.back()}" value="..back" />
        </h:form>
        <h:form>
            <h:commandButton action="#{messages.forward()}" value="forward.." />
        </h:form>
    </ui:define>
    <ui:define name="content">
        <h:dataTable value="#{messages.model}" var="m">
            <h:column>
                <f:facet name="id">
                    <h:outputText value="id" />
                </f:facet>
                <h:outputLink id="hmmm" value="detail.xhtml">
                    <f:param name="id" value="#{m.getMessageNumber()}" />
                    <h:outputText value="#{m.getMessageNumber()}" />
                </h:outputLink>
            </h:column>
            <h:column>
                <f:facet name="subject">
                    <h:outputText value="subject" />
                </f:facet>
                <h:outputText value="#{m.subject}"></h:outputText>
            </h:column>
            <h:column>
                <f:facet name="content">
                    <h:outputText value="content" />
                </f:facet>
                <h:outputText value="#{m.sentDate}"></h:outputText>
            </h:column>
            <h:column>
                <f:facet name="date">
                    <h:outputText value="date" />
                </f:facet>
                <h:outputLink value="#{messages.getUrl(m)}">#{messages.getUrl(m)}</h:outputLink>
            </h:column>
        </h:dataTable>
    </ui:define>
</ui:composition>

到:

<?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:outputLink id="back" value="detail.xhtml">
                <f:metadata>
                    <f:viewParam name="id" value="#{detail.id}"  />
                </f:metadata>
                <f:param name="id" value="#{detail.back()}" />
                <h:outputText value="back" />
            </h:outputLink>
        </h:form>
        <h:form>
            <h:outputLink id="forward" value="detail.xhtml">
                <f:metadata>
                    <f:viewParam name="id" value="#{detail.id}"  />
                </f:metadata>
                <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>

我只為任何出現的人包括這個,以澄清,對於這個簡單的例子,你不需要一個轉換器,默認的工作正常。

最初的問題也有點混亂。 通過查看關於此的其他問題,我認為其他人可以從這樣的簡單示例中受益。 這么多例子過於復雜,或者涉及到EJB等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM