gpt4 book ai didi

jsf - 从 JSF @ManagedBean 迁移到 CDI @Named 后,多次调用构造函数并且提交的输入值始终为空

转载 作者:行者123 更新时间:2023-12-01 03:33:45 25 4
gpt4 key购买 nike

编辑:评论部分解决了我的问题!问题是我对范围使用了不正确的导入。

我有一个简单的 JSF 应用程序(登录,从数据库中提取数据,允许用户编辑数据)。它运作良好,我想更新代码以使用 CDI( Weld ),但我遇到了麻烦。
我正在关注/查看:http://docs.jboss.org/weld/reference/latest/en-US/html/example.html没有 Weld 的原始东西:

登录.xhtml

<h:form id="inputForm">
<h:panelGrid columns="2" cellpadding="5" cellspacing="1">
<h:outputText id="nameDesc" value="Name"></h:outputText>
<h:inputText id="nameInput" value="#{login.loginName}" binding="#{name}"></h:inputText>

<h:outputText id="passwordDesc" value="Password"></h:outputText>
<h:inputSecret id="passwordInput" value="#{login.password}" binding="#{password}"></h:inputSecret>

</h:panelGrid>
<h:commandButton value="Login" action="#{login.login(name.value, password.value)}"/>
</h:form>

登录Bean.java:
@ManagedBean(name="login")
@SessionScoped
public class LoginBean implements Serializable {
private static final long serialVersionUID = 1L;
@ManagedProperty(value="#{db}")
private DatabaseBean db;
private String password;
private String loginName;
// other stuff and functions

public String getLoginName () {
return loginName;
}

public void setLoginName (String name) {
this.loginName = name;
}

public String getPassword () {
return password;
}

public void setPassword (final String password) {
this.password = password;
}

public void setDb(DatabaseBean db) {
this.db = db;
}

数据库Bean.java:
@ManagedBean(name="db", eager=true)
@ApplicationScoped
public class DatabaseBean implements Serializable {
@PostConstruct
public void init() {
//... connect to database etc
}

}

---------我试图让它与 Weld 一起运行(仅从上面进行更改以使其更短):--------
LoginBean.java,从@ManagedBean改为@Named,为DatabaseBean添加@Inject
@Named("login")
@SessionScoped
public class LoginBean implements Serializable {
// stuff
private @Inject DatabaseBean db;
}

DatabaseBean.java,从@ManagedBean 改为@Named:
@Named("db")
@ApplicationScoped
public class DatabaseBean implements Serializable {
}

LoginBean 有一个功能:
public String login(String name, String password) {
System.out.println("login called"+name);
// other stuff

}

在我的第二个实现中(我尝试使用 Weld 的那个),打印被调用一次:“登录调用”,并且用户名是空的(我用 name.IsEmpty() 检查了这个)。

我也尝试过通过构造函数注入(inject)它:

loginBean.java
@Inject
public LoginBean(DatabaseBean db) {
System.out.println("constructor");
this.db = db;
}

当我这样做时,我得到很多“构造函数”打印,所以它被多次调用,但我不明白为什么 - 我想这是问题所在,只有一个 LoginBean 实例获得输入(用户名和密码)然后由于某种原因创建了许多新的。这是为什么?

我使用 Eclipse 和 Tomcat8 来运行它。
感谢您的阅读!

最佳答案

managed bean constructor called multiple times



在生成/创建增强的子类/代理时,CDI 可能比预期更频繁地调用构造函数。另见 Field.get(obj) returns all nulls on injected CDI managed beans, while manually invoking getters return correct values .只是不要记录构造函数调用,它只会让你自己感到困惑。 @PostConstruct是唯一有趣的方法。

the print is called once: "login called", and the username is empty (I checked this with name.IsEmpty()).



至于表单输入值为 null的具体问题当调用 Action 方法时, @SessionScoped CDI 托管 bean 似乎在每次访问时都会重新创建,这与 @Dependent 的行为相匹配。范围 bean。当找不到有效的 CDI 托管 bean 范围时,这是默认范围。另见 What is the default Managed Bean Scope in a JSF 2 application?

这反过来又建议您导入 @SessionScoped从错误的包装。确保它来自 javax.enterprise.context包装而不是来自例如 javax.faces.bean . JSF 托管 bean 范围无法识别为有效的 CDI 托管 bean 范围。
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;

@Named("login")
@SessionScoped
public class LoginBean implements Serializable {
// ...
}

关于jsf - 从 JSF @ManagedBean 迁移到 CDI @Named 后,多次调用构造函数并且提交的输入值始终为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36357894/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com