【问题标题】:How to inject CDI SessionScoped bean into RequestScoped bean如何将 CDI SessionScoped bean 注入 RequestScoped bean
【发布时间】:2019-08-04 21:18:46
【问题描述】:

我正在尝试使用 jsf 和 CDI 编写一个简单的登录表单。 问题是当我注入我的 SessionScoped bean 时,它并没有像我预期的那样工作。 这是我的豆子

@Named
@SessionScoped
public class LoginInfo implements Serializable {
    private String uname;
    private String pass;
    private String pagename;
    private int count;

    public LoginInfo() {
    }

    public void increment() {
        count++;
    }
}

这是我的控制器:

@Named
@RequestScoped
public class LoginPageMg {
    @Inject
    LoginInfo lo;

    public LoginPageMg() {
    }


    public void login() {
        lo.increment();
        lo.setPagename("aaa");
        int x = 8;
    }
}

还有一个简单的Jsf表单,调用login函数,显示LoginInfo类的counter字段。

<h:form prependId="false" id="mainform" styleClass="login-box">
                        <p:inputText value="#{loginPageMg.uname}"/>
                        <p:password value="#{loginPageMg.pass}"/>

                        <h:outputLabel id="counter" value="#{loginInfo.count}"></h:outputLabel>

                        <p:commandButton update="counter"
                                         action="#{loginPageMg.login}"
                                         value="login"></p:commandButton>
</h:form>

通过点击登录按钮和调试变量,我可以看到“lo”是这样的:

lo = {LoginInfo$Proxy$_$$_WeldClientProxy@16688}"com.mg.LoginInfo@703ec5d5"

在线 int x=8 我可以看到“lo”变量根本没有改变,但是在我的 jsf 页面中,我可以看到每次按下登录按钮时计数器都会增加,刷新页面后 bean 会保留该值。

  1. 什么是 WeldClientProxy?
  2. 为什么有两个不同的 SessionScoped bean 实例?是 那是正常的还是我做错了什么?
  3. 如何注入与 jsf 相同的实例?

我正在使用 野蝇 15 JSF 2.3.4 CDI 1.1

【问题讨论】:

标签: jsf cdi


【解决方案1】:

我正在使用 Wildfly 15 Jsf 2.3.4 CDI 1.1

WildFly 15 表示兼容 EE 8,因此它带有 CDI 2.0。

现在尽可能多地回答您的问题:

什么是 WeldClientProxy?

Weld 是大多数 EE 服务器使用的 CDI 参考实现,包括 WildFly。 WeldClientProxy 是一个内部构造,它用于注入普通范围的 bean(几乎除了 @Dependent 之外的所有)。它不是 bean 的实际实例,您可以将其视为一个“包装器”,它知道如何检索实际的上下文实例并将调用委托给它。这样,您可以重用代理实例,同时仍然指向正确的实例(因此不需要更改引用)。

为什么一个 SessionScoped bean 有两个不同的实例?这是正常的还是我做错了什么?

只有一个,客户端代理不是实际实例。您基本上通过看到count 每次增加并在请求之间保持状态来验证这一点。

如何注入与 jsf 相同的实例?

JSF 实际上并没有注入任何东西,而是使用表达式语言根据其名称查找 bean。 CDI 允许您通过@Named 定义此名称。然后,JSF 再次通过代理使用您正在注入的同一个 bean。

【讨论】:

  • 我将 CDI 版本从 1.1 更改为 2.0,但没有任何改变。如果我只能设置它而不读取它的状态,那么 Weld 的意义何在?我设法通过这篇文章阅读了状态。 docs.jboss.org/weld/reference/latest/en-US/html/example.html.
  • 对于 CDI 2.0,我只是指出,无论您喜欢与否,使用该版本的 WFLY,您都在运行 2.0(WFLY 本身提供依赖项,而不是您的项目设置)。较新的版本是向后兼容的,因此无论如何您都不应该看到太大的区别。至于你的另一个问题,恐怕我不明白?
  • 到目前为止我得到了逻辑谢谢。剩下的唯一问题是为什么对 bean 的更改没有出现在焊接代理上?我提供的链接建议的方式是有效的。这是最好的方法还是这个问题有更好的主意
  • 重要的是设置工作正常——新请求改变了 bean 的状态并且你的应用程序工作正常。中间有一些代理并且它以这种或那种方式表现的事实应该被视为 Weld 的内部问题,不应影响您。那里发生的事情是代理是一个新对象,它与您的 bean 具有相同的类型,并引用实际的 bean 并将所有方法调用转发给它。代理对象保持不变,只是引用发生了变化。那就是,我想,你看不到代理上 bean 的变化是什么意思?
  • 正如我在登录功能中的问题中提到的,lo.count 不会改变并且保持为零(我可以在调试时看到)。但我知道计数正在改变根据你的回答,只有一个实例
猜你喜欢
  • 2014-06-02
  • 2016-06-08
  • 2016-08-02
  • 1970-01-01
  • 1970-01-01
  • 2012-03-30
  • 2015-07-14
  • 1970-01-01
相关资源
最近更新 更多