Java: отслеживание сеанса входа пользователя - сеанс EJBs против HTTPSession

Если я хочу отслеживать состояние разговоров с каждым клиентом с помощью моего веб-приложения, что является лучшей альтернативой - сеансом Bean или сеансом HTTP - для использования?

Использование сеанса HTTP:

//request is a variable of the class javax.servlet.http.HttpServletRequest
//UserState is a POJO
HttpSession session = request.getSession(true);
UserState state = (UserState)(session.getAttribute("UserState"));
if (state == null) { //create default value .. }
String uid = state.getUID();
//now do things with the user id

Использование сеанса EJB:

В реализации ServletContextListener, зарегистрированного как прослушиватель веб-приложений, в WEB-INF/web.xml:

//UserState NOT a POJO this this time, it is
//the interface of the UserStateBean Stateful Session EJB
@EJB
private UserState userStateBean;

public void contextInitialized(ServletContextEvent sce) {
    ServletContext servletContext = sce.getServletContext();
    servletContext.setAttribute("UserState", userStateBean);
    ...

В JSP:

public void jspInit() {
    UserState state = (UserState)(getServletContext().getAttribute("UserState"));
    ...
}

В другом месте в теле того же JSP:

String uid = state.getUID();
//now do things with the user id

Мне кажется, что они почти одинаковы, причем основное отличие состоит в том, что экземпляр UserState переносится в HttpRequest.HttpSession в первом, а в ServletContext в случае последнего.

Какой из двух методов более надежный и почему?

Ответы

Ответ 1

Как отметил @BalusC, в вашем примере EJB будет одинаковым для всех клиентов - не то, что вы хотите.

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

Но есть и другие более тонкие различия между использованием HttpSession и сеанса с состоянием bean (SFSB). Особенно эти два:

  • Обработка исключений. Если транзакция завершилась с ошибкой в ​​EJB, bean признан недействительным и больше не может быть использован. Это может усложнить стратегию обработки ошибок в веб-приложении.
  • Concurrency. Одновременно с одним и тем же SFSB нельзя получить доступ, поэтому вам нужно будет синхронизировать его с веб-уровнем. Опять же, это может усложнить дизайн.

См. этот ответ для более подробной информации: Правильное использование SFSB с сервлетами

Вкратце: я бы посоветовал использовать подход HttpSession и против SFSB в вашем случае; используйте SFSB только в том случае, если он предоставляет что-то, что вы не можете сделать с HttpSession, что не так.

Ответ 2

ServletContext представляет область приложения. Атрибуты области приложения распределяются между всеми запросами во всех сеансах. Это "глобальные глобальные приложения". Вы не хотите хранить в нем конкретную информацию клиента (таким образом, сеанс). Если новый клиент входит в систему, существующий EJB в области приложения будет переопределен конкретным клиентом и будет отображаться в всех клиентах.

Сфера действия сеанса точно для этой цели. Используйте его.

Ответ 3

Просто, чтобы немного очистить: ServletContext инициализируется при создании сервлета (см. спецификации сервлета) и уникален для этого самого экземпляра. Сервлет использует несколько потоков для обработки одновременных запросов клиентов. Контейнер сервлета решает, когда создавать или уничтожать сервлеты и делегировать запросы клиентов.

Вот почему у вас может быть 1 сервлет, обрабатывающий запрос для n пользователей (n >= 1), и, таким образом, в приведенном выше примере кода, используя ServletContext, каждый пользователь будет разделять сеанс bean пользователя, который вызвал создание сервлета.