как экземпляр @ 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 за подробный и отличный ответ. Мне нужно немного больше разъяснений по некоторым из ваших моментов для лучшего понимания

  1. для компонента @requestScoped существует пул доступных экземпляров, который передается клиентам. Теперь, если у меня есть два клиента, обращающиеся к JSF, который поддерживается @RequestScoped bean, каждый клиент получает работать на одном экземпляре @RequestScoped Боб из бассейна. Фактически, оба клиента фактически не работают на прямом экземпляре, но косвенная ссылка на тот единственный экземпляр, который является прокси здесь. клиенты выполняют все вызовы методов или транзакции с помощью этого прокси-сервера. Итак, как долго прокси-сервер держит эту косвенную ссылку? То есть, в моем примере выше, переменные экземпляра @RequestScoped бобовые (Credentials) установлены в JSF. но истинный факт заключается в том, что этот параметр переменных экземпляра происходит с одним экземпляром компонента @RequestScoped косвенно через прокси. Но когда этот экземпляр вводится в SessionScoped бин, это прокси, который вводится? Начиная с жизненного цикла SessionScoped для сеанса, установленного между клиентом и приложением, прокси-сервер также живет в течение этой жизни. Означает ли это это single instance of @RequestScoped bean обязан SessionScoped и жизненный цикл @RequestScoped экземпляр компонента или его прокси определяется жизненным циклом SessionScoped бин?

1 ответов


  1. на @RequestScoped Боб вводится в @SessionScoped бобовые. Какова гарантия того, что набор учетных данных для одного экземпляра RequestScoped является тем же, что и в @SessionScopedbean. почему не другой @RequestScoped из пула вводится или даже новый экземпляр?

    это законно, благодаря средствам, с помощью которых CDI фактически получает ссылки на запрошенный компонент:клиент прокси. От CDI spec

    введенная ссылка или ссылка, полученная программным поиском, обычно является контекстной ссылкой.Контекстная ссылка на компонент с нормальной областью действия[...], не является прямой ссылкой на контекстный экземпляр компонента[...].Вместо контекстная ссылка-это клиентский прокси-объект прокси-сервер клиента реализует / расширяет некоторые или все типы компонентов компонента и делегирует все методы вызовы текущего экземпляра bean...

    есть ряд причин для этого косвенного:

    • контейнер должен гарантировать, что при вызове любой допустимой введенной ссылки на компонент нормальной области вызов всегда обрабатывается текущим экземпляром введенного компонента. В некоторых случаях например, если Боб области запроса вводится в Боб области сеанса или в сервлет, это правило требует косвенной ссылки

    и с эта статья DZone CDI:

    CDI обрабатывает инъекции бобов с несовпадающими областями с помощью прокси-серверов. Из-за этого вы можете ввести компонент области запроса в компонент области сеанса, и ссылка будет по-прежнему действительна для каждого запроса, потому что для каждого запроса прокси-сервер повторно подключается к живому экземпляру области запроса в зернах

    это означает, что прокси заменяется реальной вещью в каждой точке инъекции. Прокси-сервер имитирует тип, объявленный в точке инъекции, путем расширения / реализации дерева предков типа, который он должен имитировать. В то время, когда вам действительно требуется использовать объект, прокси-сервер выполняет контекстный поиск существующего экземпляра запрошенного компонента в текущем диалоге. Это объект с областью запросов, вы гарантированно иметь ровно один экземпляр в текущем разговоре / контексте.

  2. почему Боб задан @SessionScoped, но не @Stateful. Думаю, @Stateful будет работать здесь.

    @Stateful не будет работать здесь, как я уже говорил здесь, они не дешевы; если вам действительно не нужно, придерживайтесь ванили HttpSession. Не говоря уже о том, что как только клиент SFSB выпускает Боб, он уничтожается, т. е. SFSB не привязан к текущей сессии@SessionScoped есть.

  3. как управляется жизненный цикл компонента @sessionScoped? То есть когда он разрушается ?. Если я перейду на другую страницу JSF, в которой, если я вытащу информацию, такую как currentUser.имя пользователя, я получу ту же информацию, которую я установил на своей первой странице JSF, используемой для входа в систему. (Шаг 1 выше)

    зависит от того, какой @SessionScoped вы говорите: javax.faces.bean.SessionScoped привязан непосредственно к ток HttpSession/сеанс браузера, поэтому он прекращается всякий раз, когда это умирает; JBoss, однако означает, что javax.enterprise.context.* ограниченные бобы на самом деле никуда не идут, пока "контекст" не умрет

    на самом деле нет способа удалить Боб из контекста, пока весь контекст не будет уничтожен

  4. думать @Dependent как и любой метод-локальная переменная: это полезно только до тех пор, пока это родительская конструкция. Что как говорится, лучше всего использовать не для поддержки представления JSF. Это самое полезное приложение переопределяет область, указанную в bean, ad-hoc. Используя ваш текущий пример, я могу иметь следующее Где-то еще в моем приложении:

    @Inject @New Login aDependentLoginBean; //implicit @Dependent scope applied
    @Inject Login aSessionScopedLoginBean;  //standard Login bean's scope applied
    

    вместе с @New, вы можете перепрофилировать любой другой Боб, чтобы быть @Dependent


по теме: