代码之家  ›  专栏  ›  技术社区  ›  hagrawal7777

CDI V/S JSF注释的使用问题

  •  1
  • hagrawal7777  · 技术社区  · 7 年前

    我对JSF和学习过程都是个新手,我对是否使用CDI注释或JSF注释有疑问。在很多地方(比如 this )我发现我们应该始终使用CDI注释,但它确实不起作用,我的演示应用程序仅在我使用JSF注释时才起作用。

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

    最后请参考我的代码片段。

    @javax.faces.bean.managedbean v/s@javax.inject.name名称

    我发现为了通过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 Instantiation ... 在日志中(即使我可以看到我的浏览器有相同的jsession id- Cookie: JSESSIONID=a7iC7zNgF3ddWg069Hzny6T3UvgIVrfQ0GYJf8_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>
    

    响应.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>
                <h:outputText id="result" value="#{userNumberBean.response}" />
            </h2>
            <h:commandButton id="back" value="Back" action="greeting" />
        </h:form>
    </h:body>
    </html>
    

    用户编号bean:

    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-我正在使用WebLogic12.1.2。servlet版本是3.0,JSP版本是2.1,所以我的jee版本应该是>=6,这意味着我应该有CDI。现在,我不知道如何获得CDI版本。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Michael Müller    7 年前

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

    @javax.faces.bean.managedbean

    @javax.faces.bean.sessionscoped

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

    @javax.inject.命名

    @javax.enterprise.context.sessionscoped(javax.enterprise.context.sessionscoped)

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

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

        2
  •  1
  •   hagrawal7777    7 年前

    如果有人想了解这个问题的全面概念和原因,请参考 this 回答是@kukeltje推荐的,谢谢,伙计。

    以下是我的问题和我从中学到的内容的简短总结:

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