@注入通过URL将parameter passing给CDI @Named bean

如果我不能在@Named中使用@ManagedProperty注释,因为@ManagedProperty在CDI(?)中不起作用,那么如何将URL中的params传递给facelets客户端呢? 在我的代码中,我想通过“后退”和“前进”button将javax.mail.getMessageNumber()传递给details.xhtml。

我知道@Inject应该被使用,但是什么被注入和如何,请吗?

从glassfish日志中,id始终是0,这很奇怪。 即使点击“前进”,无论点击多less次,ID也不会超过1。 当然,这只是问题的症状。 期望的输出当然是前进到下一个消息。

也许把这个消息,或者至less是int,join会话中?

客户端如此:

<?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> 

和bean一样:

 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 @ManagedProperty注释只能在JSF @ManagedBean类中使用。 即在由JSFpipe理的实例中。 它在由CDI @Namedpipe理的实例中不起作用。 此外,你犯了另一个错误:你正在尝试基于构造函数中的托pipe属性来准备Message 。 如果它是一个真正的@ManagedBean ,那也不会有效。 托pipe属性在构造过程中不可用,只是因为在构造函数被调用之前无法调用setter方法。 你会用这个@PostConstruct方法。 但是这不是@ManagedProperty不能在@Named工作的解决scheme。

要真正替代@ManagedProperty ,您需要创build一个自定义的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转换和validation。


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

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

另一种方式,国际海事组织也更适合这种特殊情况下,是使用<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 } 

和a

 @FacesConverter("messageConverter") public class MessageConverter implements Converter { // Convert string id to Message object in getAsObject(). // Convert Message object to string id in getAsString(). } 

也可以看看

  • ViewParam vs @ManagedProperty(value =“#{param.id}”)
  • JSF 2.0中的通信 – 处理GET请求参数

首先,解释外部的一部分 – Glassfish使用JBoss Weld作为它的CDI实现,Oracle不开发自己的实现。

关于错误信息的含义:FacesContext根本就不是通过@Inject注入的。 有一个相当古老的function要求 ,我觉得Seam或Solder提供了一个生产者。 但是没有必要为了这个而整合任何一个库。 通过FacesContext.getCurrentInstance()访问面向上下文的环境,就像在正常的托pipebean中一样。

我正在问一个复杂的方式来做一件简单的事情。 在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等等。