我使用JSF 2.2和CDI。我創建了下面的例子來向你展示我的問題的核心。你可以看到如下:@對象的注入和對象的兩種不同行爲
- 兩個XHTML頁面,
- 會話範圍的CDI豆(
LoginController
),這是XHTML的第1頁控制器, - 視圖範圍的CDI豆(
DataController
),這是控制器對於xhtml頁面2, - 請求範圍CDI bean(
DataServiceImpl
),它是DataController
bean的服務。
這是一個用例和數據的流程:
XHTML第2頁 - >的DataController
控制器 - >調用dataService.addData()
在send()
方法(其位於DataController
類) - >執行addData()
方法(它位於DataServiceImpl
類)
我的問題的心臟:
- 如果我注入
LoginController
到DataServiceImpl
類,loginController
對象不起作用(即,它返回null
)[下面代碼中的選項1]。 - 如果我將
LoginController
注入DataController
類,loginController
對象正常工作(即它返回我想要的)[下面代碼中的選項2]。
我的問題是:爲什麼這個注入的對象有兩種不同的方式取決於注入的位置?
這是我的XHTML 1頁的部分:
<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 2頁的部分:
<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豆:
@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豆:
@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的範圍會發生什麼。如果我使用'@ RequestScoped'註釋代替'DataController' bean的'@ ViewScoped'註釋,它和以前一樣。也許CDI不支持我發明的這種用例。 – Robert