@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.
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?
从玻璃鱼的日志中,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.
也许将消息或至少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 @ManagedProperty
注释仅在JSF @ManagedBean
类中有效. IE.在由JSF管理的实例中.它在由CDI @Named
管理的实例中不起作用.此外,您犯了另一个错误:您正在尝试根据构造函数中的托管属性准备Message
.如果它是真实的@ManagedBean
,那也就行不通了.托管属性在构造期间不可用,仅是因为无法在调用构造函数之前调用setter方法.您将为此使用@PostConstruct
方法.但这不是解决方案,因为@ManagedProperty
无论如何都不能在@Named
中工作.
The JSF @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 would have used a @PostConstruct
method for this. But this isn't the solution as the @ManagedProperty
don't work in a @Named
anyway.
要真正替代@ManagedProperty
,您需要创建一个自定义CDI批注.一个具体示例发布在此博客中.这是相关的摘录:
To have a real replacement for @ManagedProperty
, 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 具有
JSF utility library OmniFaces has a @Param
for 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也更适用于此特定情况,它是使用<f:viewParam>
,它还允许您通过自定义转换器将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().
}
另请参见
- ViewParam与@ManagedProperty(值=#{param.id}"")
- JSF 2.0中的通信-处理GET请求参数
- ViewParam vs @ManagedProperty(value = "#{param.id}")
- Communication in JSF 2.0 - processing GET request parameters
See also
这篇关于@Inject通过URL将参数传递给CDI @Named bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!