Я читаю этот пример в JBoss, где bean-компонент @RequestScoped
, резервный JSF page
, используется для передачи учетных данных пользователя, которые затем сохраняются в файле @sessionScoped bean
. Вот пример из документов JBoss.
@Named @RequestScoped
public class Credentials {
private String username;
private String password;
@NotNull @Length(min=3, max=25)
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
@NotNull @Length(min=6, max=20)
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
JSF-форма:
<h:form>
<h:panelGrid columns="2" rendered="#{!login.loggedIn}">
<f:validateBean>
<h:outputLabel for="username">Username:</h:outputLabel>
<h:inputText id="username" value="#{credentials.username}"/>
<h:outputLabel for="password">Password:</h:outputLabel>
<h:inputSecret id="password" value="#{credentials.password}"/>
</f:validateBean>
</h:panelGrid>
<h:commandButton value="Login" action="#{login.login}" rendered="#{!login.loggedIn}"/>
<h:commandButton value="Logout" action="#{login.logout}" rendered="#{login.loggedIn}"/>
</h:form>
Объект пользователя:
@Entity
public class User {
private @NotNull @Length(min=3, max=25) @Id String username;
private @NotNull @Length(min=6, max=20) String password;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String setPassword(String password) { this.password = password; }
}
Компонент SessionScoped
@SessionScoped @Named
public class Login implements Serializable {
@Inject Credentials credentials;
@Inject @UserDatabase EntityManager userDatabase;
private User user;
public void login() {
List<User> results = userDatabase.createQuery(
"select u from User u where u.username = :username and u.password = :password")
.setParameter("username", credentials.getUsername())
.setParameter("password", credentials.getPassword())
.getResultList();
if (!results.isEmpty()) {
user = results.get(0);
}
else {
// perhaps add code here to report a failed login
}
}
public void logout() {
user = null;
}
public boolean isLoggedIn() {
return user != null;
}
@Produces @LoggedIn User getCurrentUser() {
return user;
}
}
Мои вопросы
1) Компонент @RequestScoped
внедряется в компонент @SessionScoped
. Какова гарантия того, что учетная информация, установленная в одном экземпляре RequestScoped
, совпадает с введенной в @SessionScoped
bean. почему не внедряется другой @RequestScoped
из пула или даже новый экземпляр?
2)почему бину присваивается @SessionScoped
, а не @Stateful
. Думаю, @Stateful
здесь подойдет.
3) как управляется жизненный цикл бина @sessionScoped
? То есть когда он уничтожается? Если я перейду на другую JSF
страницу, на которой, если я извлеку информацию, такую как currentUser.userName
, я получу ту же информацию, которую я установил на моей первой JSF
странице, используемой для входа в систему. (шаг 1 выше)
4) Если я не укажу @RequestScoped
, то bean-компонент Credentials получит область @Dependent
, которая является областью действия по умолчанию. В документах упоминается, что установка любых переменных экземпляра @Dependent
немедленно теряется. Но я не понимаю, почему? На самом деле, это подсказывает мне вопрос о том, как будет использоваться @Dependent
прицел?
Спасибо
EDIT Спасибо, kolossus, за подробный и отличный ответ. Мне нужно немного больше разъяснений по некоторым вашим пунктам для лучшего понимания
- Для bean-компонента @requestScoped существует пул доступных экземпляров, которые передаются клиентам. Теперь, если у меня есть два клиента, обращающихся к JSF, который поддерживается bean-компонентом
@RequestScoped
, каждый клиент получает возможность работать с одним экземпляром bean-компонента@RequestScoped
из пула. На самом деле оба клиента на самом деле работают не с прямым экземпляром, а с косвенной ссылкой на тот единственный экземпляр, который здесь является прокси. клиенты выполняют все вызовы методов или транзакции, используя этот прокси. так как долго прокси удерживает эту косвенную ссылку? То есть в моем примере выше переменные экземпляра@RequestScoped
bean-компонента (Credentials
) задаются в JSF. но истинный факт заключается в том, что эта настройка переменных экземпляра происходит с одним экземпляром bean-компонента @RequestScoped косвенно через прокси. Но когда этот экземпляр внедряется в bean-компонентSessionScoped
, внедряется ли прокси-сервер? Поскольку жизненный циклSessionScoped
предназначен для сеанса, установленного между клиентом и приложением, прокси-сервер также живет в течение этого времени существования. Означает ли это, что этотsingle instance of @RequestScoped bean
привязан кSessionScoped
, а жизненный цикл экземпляра компонента@RequestScoped
или его прокси определяется жизненным циклом компонентаSessionScoped
?
@RequestScoped
bean-компоненты не объединены в пул. Почему бы им быть? Они живы только на время одного запроса. Пользователю потребуется только один. - person kolossus   schedule 12.10.2014@RequestScoped
в@SessionScoped
? жизненный цикл этого экземпляра@RequestScoped
связан с@SessionScoped
? - person brain storm   schedule 12.10.2014@SessionScoped
может требовать компонент@RequestScoped
и наоборот. - person kolossus   schedule 12.10.2014