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

Если я хочу отслеживать состояние разговора с каждым клиентом, использующим мое веб-приложение, какой вариант лучше использовать - сессионный компонент или сеанс 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

Использование Session 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 в случае последнего.

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

3 ответа

Решение

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

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

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

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

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

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

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

Область сеанса именно для этой цели. Используйте это.

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

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

Другие вопросы по тегам