CDI v/s JSF注释的使用问题

CDI v/s JSF注释的使用问题,jsf,cdi,Jsf,Cdi,我对JSF和学习过程都是全新的,我在理解是使用CDI注释还是JSF注释时遇到了一些问题。在很多地方(比如),我发现我们应该始终使用CDI注释,但它确实不起作用,我的演示应用程序只有在使用JSF注释时才起作用 下面是我面临问题的例子,我的问题是-有人能解释一下我是否做错了什么,或者如果使用JSF我必须使用JSF注释,如果这是真的,那么我认为这些帖子(比如)是错误的。我看到在那篇文章中还提到,如果JSF版本2.0或更高版本没有CDI,那么应该使用JSF注释,我检查了我的JSF版本,它是JavaSer

我对JSF和学习过程都是全新的,我在理解是使用CDI注释还是JSF注释时遇到了一些问题。在很多地方(比如),我发现我们应该始终使用CDI注释,但它确实不起作用,我的演示应用程序只有在使用JSF注释时才起作用


下面是我面临问题的例子,我的问题是-有人能解释一下我是否做错了什么,或者如果使用JSF我必须使用JSF注释,如果这是真的,那么我认为这些帖子(比如)是错误的。我看到在那篇文章中还提到,如果JSF版本2.0或更高版本没有CDI,那么应该使用JSF注释,我检查了我的JSF版本,它是
JavaServer Faces参考实现2.1.20 Fri Mar 8 05:55:39 PST 2013
,但我不知道它是否有CDI

最后请参考我的代码片段

@javax.faces.bean.ManagedBean v/s@javax.inject.Named 我发现为了通过EL(表达式语言)语法使用托管bean-
{}
,托管bean类可以使用
@javax.faces.bean.ManagedBean
@javax.inject.Named
进行注释

理论上,这两种方法都应该有效,但当我使用CDI注释时,我会得到以下例外情况:

javax.el.PropertyNotFoundException: //C:/E_Drive/Projects/Workspace/HakerRank/testing/WebContent/greeting.xhtml @21,42 value="#{userNumberBean.userNumber}": Target Unreachable, identifier 'userNumberBean' resolved to null
    at com.sun.faces.facelets.el.TagValueExpression.getType(TagValueExpression.java:100)
    at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getConvertedValue(HtmlBasicInputRenderer.java:95)
    at javax.faces.component.UIInput.getConvertedValue(UIInput.java:1030)
    at javax.faces.component.UIInput.validate(UIInput.java:960)
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1233)
    at javax.faces.component.UIInput.processValidators(UIInput.java:698)
但是,当我使用
@javax.faces.bean.ManagedBean
注释时,事情就正常了



@javax.enterprise.context.SessionScoped v/s@javax.faces.bean.SessionScoped 同样,理论上这两种方法都应该有效,但是如果我使用CDIBean,那么它就不会成为会话bean,当我刷新页面时,我仍然会在日志中看到
####UserNumberBean实例化…
(尽管我可以看到我的浏览器有相同的JSESSION ID-
Cookie:JSESSIONID=A7IC7ZNGF3DWG069HZNY6T3UVGIVRFQ0GYJF8_pzT6Y0TzYAW3c!1544639247
),这表明正在创建一个新的bean实例。但是,如果我使用
javax.faces.bean.SessionScoped
,那么一切都会按预期进行


问候语。xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">

<h:head>
    <title>Guess Number Facelets Application</title>
</h:head>
<h:body>
    <h:form>
        <h:graphicImage value="#{resource['images:OracleLogo.png']}"
            alt="Duke waving his hand" />
        <h2>Hi, my name is Duke. I am thinking of a number from
            #{userNumberBean.minimum} to #{userNumberBean.maximum}. Can you guess
            it?</h2>
        <p>
            <h:inputText id="userNo" title="Enter a number from 0 to 10:"
                value="#{userNumberBean.userNumber}">
                <f:validateLongRange minimum="#{userNumberBean.minimum}" maximum="#{userNumberBean.maximum}" />
            </h:inputText>
            <h:commandButton id="submit" value="Submit" action="response" />
        </p>
        <h:message showSummary="true" showDetail="false"
            style="color: #d20005;
font-family: 'New Century Schoolbook', serif;
font-style: oblique;
text-decoration: overline"
            id="errors1" for="userNo" />
    </h:form>
</h:body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
    <title>Guess Number Facelets Application</title>
</h:head>
<h:body>
    <h:form>
        <h:graphicImage value="#{resource['images:OracleLogo.png']}"
            alt="Duke waving his hand" />
        <h2>
            <h:outputText id="result" value="#{userNumberBean.response}" />
        </h2>
        <h:commandButton id="back" value="Back" action="greeting" />
    </h:form>
</h:body>
</html>
import java.io.Serializable;
import java.util.Random;

import javax.inject.Named;

@Named
@javax.enterprise.context.SessionScoped
public class UserNumberBean implements Serializable {
    private static final long serialVersionUID = 5443351151396868724L;
    Integer randomInt = null;
    Integer userNumber = null;
    String response = null;
    private int maximum = 10;
    private int minimum = 0;

    {
        System.out.println("### UserNumberBean Instantiation ...");
    }

    static{
        System.out.println("### UserNumberBean Static initialization ...");
    }

    public UserNumberBean() {
        Random randomGR = new Random();
        randomInt = new Integer(randomGR.nextInt(maximum + 1));
        // Print number to server log
        System.out.println("Duke's number: " + randomInt);
    }

    public void setUserNumber(Integer user_number) {
        userNumber = user_number;
    }

    public Integer getUserNumber() {
        return userNumber;
    }

    public String getResponse() {
        System.out.println("### userNumber: " + userNumber + " | randomInt: " + randomInt);
        if ((userNumber == null) || (userNumber.compareTo(randomInt) != 0)) {
            return "Sorry, " + userNumber + " is incorrect.";
        } else {
            return "Yay! You got it!";
        }
    }

    public int getMaximum() {
        return (this.maximum);
    }

    public void setMaximum(int maximum) {
        this.maximum = maximum;
    }

    public int getMinimum() {
        return (this.minimum);
    }

    public void setMinimum(int minimum) {
        this.minimum = minimum;
    }

}


更新1:@XtremeBiker-我使用的是Weblogic 12.1.2。Servlet版本是3.0,JSP版本是2.1,所以我的JEE版本应该是>=6,这意味着我应该有CDI。现在,我不知道如何获得CDI版本。

托管bean是由JSF管理的bean。这是JSF在CDI不可用时引入的旧技术。D在此期间,JSF中定义了几个作用域

@javax.faces.bean.ManagedBean

@javax.faces.bean.SessionScoped

由于JVAE6,CDI是EE版本的一部分。CDIBean不是特定于JSF的,可以在整个JEE生态系统中使用。CDI定义了几个范围

@javax.inject.Named

@javax.enterprise.context.SessionScoped

上面我将JSF和CDI注释组合在一起。不可能将它们混合在一起。如果您混合使用这些注释,您的应用程序将无法正常运行


不要再使用老式的JSF标签了-标签被标记为已弃用。从JSF 2.3(JEE 8)开始,旧的注释将被删除。

如果有人想了解这个问题的完整概念和原因,请参考@Kukeltje推荐的答案,谢谢,伙计

以下是我的问题的简短总结以及我从中学到的东西:

  • 我的问题的根本原因是,尽管我使用了
    javax.inject.Named
    annotation,但它没有生效,因为我没有创建CDI容器
  • 代码修复是将beans.xml文件包含在WEB-INF目录中。请阅读如何配置CDI应用程序。因此,基本上我缺少的是我没有配置CDI,因此注释没有生效。
    • 另一方面,由于我的是JEE 6容器,所以我明确需要
      beans.xml
      文件,在JEE 7容器中,如果任何类具有CDI注释,那么服务器将自动将该应用程序识别为CDI应用程序,请阅读更多
  • 我学到的另一件重要的事情是CDI注释比JSF注释更受欢迎(很好,我发现并遇到了这个问题,否则我可能会使用JSF注释)

您无法说出您正在测试代码的服务器/版本以及正在尝试的CDI版本。无论如何,这个问题表明了研究的努力,并且得到了恰当的说明。“但我不知道它是否与CDI一起使用”…JSF本身没有cdi。如果您不使用java ee服务器,则需要安装cdi。请阅读并查看其中是否包含有用的内容info@XtremeBiker我已经用服务器信息更新了我的问题。@Kukeltje我已经用服务器信息更新了我的问题。但是你检查了我发布的链接中的所有信息了吗?谢谢你尝试帮助我们。但我认为OP都知道这一点。问题是为什么在使用cdi注释时它不起作用。您的答案已经很笼统了:(有效管理的bean是由容器(JSF、cdi、Spring、Guice等)管理的bean)因此,第一句话并非完全正确。这也是一个补充:感谢您抽出时间回答并研究这个问题。请阅读所有>35 upvote JSF Q/A的标题,快速扫描并记住它们的存在(不要记住它们;-)。一个好的设计有很大帮助。例如,我在IBM OpenLiberty中遇到了同样的问题,并通过向
server.xml