как экземпляр @ RequestScoped bean предоставляется @ sessionscoped bean во время выполнения здесь?
я читаю этот пример в от JBoss где @RequestScoped
Боб резервное копирование JSF page
используется для передачи учетных данных пользователя, которые затем сохраняются в @sessionScoped bean
.
Вот пример взять из JBoss docs.
@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) бин вводится в @SessionScoped
бобовые. Какова гарантия того, что учетные данные установлены на одном экземпляре RequestScoped
это то же самое, что вводится в @SessionScoped
бобовые. почему не другой @RequestScoped
из пула вводится или даже новый экземпляр?
2) почему Боб дан @SessionScoped
а не @Stateful
. Я думаю @Stateful
будет работать здесь.
3) как жизненный цикл @sessionScoped
Боб успел? То есть когда он разрушается ?. Если я перейду к другому JSF
страница, в которой, если я вытяните информацию, такую как currentUser.userName
, я получу ту же информацию, которую я установил на своем первом JSF
страница используется для входа в систему. (Шаг 1 выше)
4) Если я не указать @RequestScoped
, затем Бин учетных данных получает @Dependent
объем что объем умолчанию. Это упоминается в docs это установка любых переменных экземпляра @Dependent
немедленно теряется. Но я не понимаю, почему? На самом деле, это наводит меня на вопрос о том, какое использование @Dependent
объем будет ?
спасибо
редактировать Спасибо kolossus за подробный и отличный ответ. Мне нужно немного больше разъяснений по некоторым из ваших моментов для лучшего понимания
- для компонента @requestScoped существует пул доступных экземпляров, который передается клиентам. Теперь, если у меня есть два клиента, обращающиеся к JSF, который поддерживается
@RequestScoped
bean, каждый клиент получает работать на одном экземпляре@RequestScoped
Боб из бассейна. Фактически, оба клиента фактически не работают на прямом экземпляре, но косвенная ссылка на тот единственный экземпляр, который является прокси здесь. клиенты выполняют все вызовы методов или транзакции с помощью этого прокси-сервера. Итак, как долго прокси-сервер держит эту косвенную ссылку? То есть, в моем примере выше, переменные экземпляра@RequestScoped
бобовые (Credentials
) установлены в JSF. но истинный факт заключается в том, что этот параметр переменных экземпляра происходит с одним экземпляром компонента @RequestScoped косвенно через прокси. Но когда этот экземпляр вводится вSessionScoped
бин, это прокси, который вводится? Начиная с жизненного циклаSessionScoped
для сеанса, установленного между клиентом и приложением, прокси-сервер также живет в течение этой жизни. Означает ли это этоsingle instance of @RequestScoped bean
обязанSessionScoped
и жизненный цикл@RequestScoped
экземпляр компонента или его прокси определяется жизненным цикломSessionScoped
бин?
1 ответов
-
на
@RequestScoped
Боб вводится в@SessionScoped
бобовые. Какова гарантия того, что набор учетных данных для одного экземпляра RequestScoped является тем же, что и в@SessionScopedbean
. почему не другой@RequestScoped
из пула вводится или даже новый экземпляр?это законно, благодаря средствам, с помощью которых CDI фактически получает ссылки на запрошенный компонент:клиент прокси. От CDI spec
введенная ссылка или ссылка, полученная программным поиском, обычно является контекстной ссылкой.Контекстная ссылка на компонент с нормальной областью действия[...], не является прямой ссылкой на контекстный экземпляр компонента[...].Вместо контекстная ссылка-это клиентский прокси-объект прокси-сервер клиента реализует / расширяет некоторые или все типы компонентов компонента и делегирует все методы вызовы текущего экземпляра bean...
есть ряд причин для этого косвенного:
- контейнер должен гарантировать, что при вызове любой допустимой введенной ссылки на компонент нормальной области вызов всегда обрабатывается текущим экземпляром введенного компонента. В некоторых случаях например, если Боб области запроса вводится в Боб области сеанса или в сервлет, это правило требует косвенной ссылки
и с эта статья DZone CDI:
CDI обрабатывает инъекции бобов с несовпадающими областями с помощью прокси-серверов. Из-за этого вы можете ввести компонент области запроса в компонент области сеанса, и ссылка будет по-прежнему действительна для каждого запроса, потому что для каждого запроса прокси-сервер повторно подключается к живому экземпляру области запроса в зернах
это означает, что прокси заменяется реальной вещью в каждой точке инъекции. Прокси-сервер имитирует тип, объявленный в точке инъекции, путем расширения / реализации дерева предков типа, который он должен имитировать. В то время, когда вам действительно требуется использовать объект, прокси-сервер выполняет контекстный поиск существующего экземпляра запрошенного компонента в текущем диалоге. Это объект с областью запросов, вы гарантированно иметь ровно один экземпляр в текущем разговоре / контексте.
-
почему Боб задан @SessionScoped, но не @Stateful. Думаю, @Stateful будет работать здесь.
@Stateful
не будет работать здесь, как я уже говорил здесь, они не дешевы; если вам действительно не нужно, придерживайтесь ванилиHttpSession
. Не говоря уже о том, что как только клиент SFSB выпускает Боб, он уничтожается, т. е. SFSB не привязан к текущей сессии@SessionScoped
есть. -
как управляется жизненный цикл компонента @sessionScoped? То есть когда он разрушается ?. Если я перейду на другую страницу JSF, в которой, если я вытащу информацию, такую как currentUser.имя пользователя, я получу ту же информацию, которую я установил на своей первой странице JSF, используемой для входа в систему. (Шаг 1 выше)
зависит от того, какой
@SessionScoped
вы говорите:javax.faces.bean.SessionScoped
привязан непосредственно к токHttpSession
/сеанс браузера, поэтому он прекращается всякий раз, когда это умирает; JBoss, однако означает, чтоjavax.enterprise.context.*
ограниченные бобы на самом деле никуда не идут, пока "контекст" не умретна самом деле нет способа удалить Боб из контекста, пока весь контекст не будет уничтожен
-
думать
@Dependent
как и любой метод-локальная переменная: это полезно только до тех пор, пока это родительская конструкция. Что как говорится, лучше всего использовать не для поддержки представления JSF. Это самое полезное приложение переопределяет область, указанную в bean, ad-hoc. Используя ваш текущий пример, я могу иметь следующее Где-то еще в моем приложении:@Inject @New Login aDependentLoginBean; //implicit @Dependent scope applied @Inject Login aSessionScopedLoginBean; //standard Login bean's scope applied
вместе с @New, вы можете перепрофилировать любой другой Боб, чтобы быть
@Dependent
по теме: