【问题标题】:@Inject annotation for object and two different behaviors of this object对象的@Inject 注释和该对象的两种不同行为
【发布时间】:2016-03-25 21:45:23
【问题描述】:

我使用 JSF 2.2 和 CDI。我创建了下面的示例来向您展示我的问题的核心。您可以在下面看到:

  • 两个 xhtml 页面,
  • 会话范围的 CDI bean (LoginController),它是 xhtml page1 的控制器,
  • 视图范围的 CDI bean (DataController),它是 xhtml page2 的控制器,
  • 请求范围的 CDI bean (DataServiceImpl),它是DataController bean 的服务。

这是一个用例和数据流:

xhtml page2 -> DataController 控制器 -> 在send() 方法中调用dataService.addData()(位于DataController 类中)-> 执行addData() 方法(位于DataServiceImpl类)

我的问题的核心:

  • 如果我将LoginController 注入DataServiceImpl 类,loginController 对象将不起作用(即它返回null)[下面代码中的选项1]。
  • 如果我将LoginController 注入DataController 类,loginController 对象工作正常(即它返回我想要的)[下面代码中的选项 2]。

我的问题是:为什么这个注入的对象会根据注入的位置以两种不同的方式表现?

这是我的 xhtml page1 的一部分:

<h:form>               

    <p:growl id="growl" showDetail="false" />

    <h:inputText id="username" value="#{userLogin.username}" label="Username" required="true" requiredMessage="Username: This field is required." title="Enter your username." pt:placeholder="Username" />
    <h:inputSecret  id="password" value="#{userLogin.password}" label="Password" required="true" requiredMessage="Password: This field is required." title="Enter your password." pt:placeholder="Password" />
    <p:commandButton value="Login" action="#{loginController.login}" update="growl" />                  

</h:form>

这是我的 xhtml page2 的一部分:

<h:form>    

    <p:growl id="growl" showDetail="false" />

    <p:panelGrid id="panel" columns="2" styleClass="ui-noborder" columnClasses="rightalign,leftalign">
        <p:outputLabel for="data" value="Data:" />
        <p:inputText  id="data" value="#{data.text}" required="true" requiredMessage="Data: This field is required." />
        <p:commandButton id="buttonSend" value="Send" action="#{dataController.send()}" update="messages" />                        
    </p:panelGrid>                                              

</h:form>

这是会话范围的 CDI bean:

@Named
@SessionScoped
public class LoginController implements Serializable {

    private static final long serialVersionUID = -6322113716363932422L;

    public String login(){      

        if(userService.login(userLogin)){

            currentUser=userService.getCurrnetUser(userLogin.getUsername());
            return "home?faces-redirect=true";          
        }
        else{

            facesContext.addMessage(null, new FacesMessage("Data entered are incorrect"));
            return null;
        }
    }

    public String logout(){

        currentUser=null;
        return "login?faces-redirect=true";
    }

    public boolean isLoggedIn() {

          return currentUser!=null;
    }

    @Produces
    @LoggedIn
    public UserAccount getCurrentUser(){

        return currentUser; 
    }   

    @Inject
    private FacesContext facesContext;

    @Inject
    private UserServiceImpl userService;

    @Named
    @Produces
    @RequestScoped
    private UserAccount userLogin=new UserAccount();

    private UserAccount currentUser;
}

这是视图范围的 CDI bean:

@Named
@ViewScoped
public class DataController implements Serializable {

    private static final long serialVersionUID = 1383572529241805730L;

    public void send(){

        /* OPTION 2
         * If I inject the LoginController here 
         * instead of in DataServiceImpl bean, the loginController object 
         * works fine (i.e. it isn't null and returns the name of the user). 
         */
        String name=loginController.getCurrentUser().getName();

        dataService=new DataServiceImpl();
        dataService.addData(data.getText);
    }

    @Named
    @Produces
    @RequestScoped
    private Data data=new Data();  

    @Inject
    private DataService dataService;

    @Inject
    private LoginController loginController;    
}

这是请求范围的 CDI bean:

@Named
@RequestScoped
public class DataServiceImpl implements DataService {

    @Override
    public void addData(String data) {

        /* OPTION 1
         * If I inject the LoginController here 
         * instead of DataController bean, the loginController object 
         * doesn't work (i.e. returns null. I get the NullPointerException exception 
         * in line below due to the loginController object which is null)
         */
        String name=loginController.getCurrentUser().getName();

        //Proccess some data
    }

    @Inject
    private LoginController loginController;
}

【问题讨论】:

  • 我认为 bean 的作用域与注入的行为有很大关系。
  • 这可能是真的。我还测试了如果更改DataController bean 的范围会发生什么。如果我对DataController bean 使用@RequestScoped 注释而不是@ViewScoped 注释,它的工作原理与以前相同。也许 CDI 不支持我发明的这种用例。

标签: jsf cdi jsf-2.2


【解决方案1】:

我不太了解您的设计,这可能是问题的一部分。

您不应将控制器注入另一个控制器,或将控制器注入服务。

看到您的LoginController 产生@LoggedIn UserAccount,为什么不简单地注入它,而不是注入loginController 并调用loginController.getCurrentUser().getName()?

【讨论】:

  • 如果将控制器注入服务 - 我不应该或不能?看看我的实验结果 - 我想我不能,但我想知道为什么。如果 CDI 不支持/不提供此类用例,那对我来说就足够了。你是对的——我可以在DataController bean 或DataServiceImpl bean 中注入这个:@LoggedIn UserAccount currentUser,而不是LoginController。这是更好的灵魂,但它与注入的LoginController 相同(即,如果我在DataServiceImpl bean 中调用currentUser.getName(),currnetUser 对象是null)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-30
  • 1970-01-01
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 2019-06-19
相关资源
最近更新 更多