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 пользователя, который вызвал создание сервлета.