如果我不能将@ManagedProperty注释与@Named一起使用,因为@ManagedProperty在CDI(?)中不起作用,那么如何将URL中的参数传递给Facelets客户端?在我的代码中,我想通过“后退”和“前进”按钮将javax.mail.getMessageNumber()传递给details.xhtml。
我知道应该使用@Inject,但是请注入什么以及如何注入?
从玻璃鱼的日志中,id始终为0,这很奇怪。即使单击“前进”,无论单击多少次,id都不会大于1。当然,这仅仅是问题的征兆。当然,所需的输出是前进到下一条消息。
也许将消息或至少int放入会话中?
客户本身:
<?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 2.3中引入的javax.faces.annotation.ManagedProperty
。
javax.faces.annotation.ManagedProperty
现在不推荐使用的@Inject @ManagedProperty("#{param.id}")
private String id;
注释仅在JSF javax.faces.bean.ManagedProperty
类中有效。即在由JSF管理的实例中。它在由CDI javax.faces.bean.ManagedProperty
管理的实例中不起作用。此外,您犯了另一个错误:您试图基于构造函数中的托管属性准备@ManagedBean
。如果它是真实的@Named
,那也将不起作用。托管属性在构造期间不可用,仅因为无法在调用构造函数之前调用setter方法。您应该为此使用Message
方法。
如果无法升级到JSF 2.3,则需要创建一个自定义CDI批注。 @ManagedBean
中张贴了一个具体示例。以下是相关摘录:
自定义@PostConstruct
批注:
this blog
注释值生成器:
@HttpParam
用法示例:
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface HttpParam {
@NonBinding
public String value() default "";
}
JSF实用程序库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受管Bean中的外部上下文中手动获取请求参数。推荐的进行托管bean初始化的方法是使用@Param
方法,而不是构造函数,因为构造函数could的用途与托管bean的创建完全不同:
@Param
另一种方式,IMO也更适合这种情况,是使用Detail
,它还允许您通过自定义转换器将ID直接转换为@PostConstruct
。
@PostConstruct
public void init() {
String id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");
// ...
}
with just
<f:viewParam>
和一个
Message
<f:metadata>
<f:viewParam name="id" value="#{detail.message}" converter="messageConverter" />
</f:metadata>
@Named
public class Detail {
private Message message;
// Getter+setter
}
首先,解释外来部分-Glassfish使用JBoss Weld作为其CDI实现,Oracle并未开发自己的实现。
并涉及错误消息的含义:FacesContext根本无法通过@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}"),我认为Seam或Solder提供了一个生产者。但是,无需为此专门集成任何一个库。通过Communication in JSF 2.0 - processing GET request parameters,可以像访问普通托管bean一样访问Face上下文。
我在问一种复杂的方法来做一件简单的事情。在CDI中,要传递参数,您不能使用@ManagedProperty,如上文BalusC所述。相反,您只需这样设置xhtml文件: