简体   繁体   English

Java:跟踪用户登录会话 - 会话EJB与HTTPSession

[英]Java: Tracking a user login session - Session EJBs vs HTTPSession

If I want to keep track of a conversational state with each client using my web application, which is the better alternative - a Session Bean or a HTTP Session - to use? 如果我想使用我的Web应用程序跟踪每个客户端的会话状态,那么更好的选择 - 会话Bean还是HTTP会话 - 要使用?

Using HTTP Session: 使用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

Using Session EJB: 使用Session EJB:

In the implementation of ServletContextListener registered as a Web Application Listener in WEB-INF/web.xml : 在ServletContextListener的实现中,在WEB-INF/web.xml注册为Web应用程序侦听器:

//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);
    ...

In a JSP: 在JSP中:

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

Elsewhere in the body of the same JSP: 在同一个JSP的主体的其他地方:

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

It seems to me that the they are almost the same, with the main difference being that the UserState instance is being transported in the HttpRequest.HttpSession in the former, and in a ServletContext in the case of the latter. 在我看来,它们几乎相同,主要区别在于UserState实例在前者的HttpRequest.HttpSession中传输,而在后者的情况下在ServletContext中传输。

Which of the two methods is more robust, and why? 这两种方法中哪一种更强大,为什么?

As @BalusC pointed out, in your example the EJB would be the same for all clients -- not what you want. 正如@BalusC所指出的那样,在您的示例中,EJB对于所有客户端都是相同的 - 而不是您想要的。

You can still change that and have one EJB per client, if for instance you create the EJB when the user logs in and store it in the session, or something similar. 您仍然可以更改它并在每个客户端拥有一个EJB,例如,如果您在用户登录并将其存储在会话中时创建EJB,或类似的东西。

But there are other more subtle differences between using the HttpSession and a stateful session bean (SFSB). 但是在使用HttpSession和有状态会话bean(SFSB)之间还有其他更微妙的区别。 Especially these two ones: 特别是这两个:

  1. Exception handling . 异常处理 If a transaction fails in the EJB, the bean is invalidated and can not be used any longer. 如果EJB中的事务失败,则bean将失效并且不能再使用。 This can complicate the error handling strategy in the web application. 这可能会使Web应用程序中的错误处理策略复杂化。
  2. Concurrency . 并发 The same SFSB can not be accessed concurrently, so you will need to synchronize that in the web layer. 无法同时访问同一个SFSB,因此您需要在Web层中同步该SFSB。 Again, this can complicate the design. 同样,这可能使设计复杂化。

See this answer for more details: Correct usage of SFSB with Servlets 有关更多详细信息,请参阅此答案: 使用Servlet正确使用SFSB

In summary: I would advise going for the HttpSession approach and against the SFSB in your case; 总结:在你的情况下,我会建议采用HttpSession方法和SFSB; use SFSB only if it provides something you can't do with HttpSession , which isn't the case. 仅当它提供了HttpSession无法做到的事情时才使用SFSB,但实际情况并非如此。

The ServletContext represents the application scope. ServletContext表示应用程序范围。 Application scoped attributes are shared among all requests in all sessions. 应用程序范围属性在所有会话中的所有请求之间共享。 It are "application wide globals". 它是“应用程序范围的全局”。 You don't want to store client (thus, session) specific information in there. 您不希望在其中存储客户端(因此,会话)特定信息。 If a new client logs in, the existing EJB in the application scope will be overridden with the client-specific one and be reflected to all clients. 如果新客户端登录,则应用程序范围中的现有EJB将被客户端特定的EJB覆盖,并反映到所有客户端。

The session scope is exactly for this purpose. 会话范围正是为此目的。 Make use of it. 利用它。

Just to clearify a bit: The ServletContext is initialized when a servlet is created (see Servlet Specs) and is unique to that very instance. 只是为了清楚一点:ServletContext在创建servlet时初始化(参见Servlet规范),并且对于该实例是唯一的。 A servlet uses multiple threads to handle concurrent client requests. servlet使用多个线程来处理并发客户端请求。 The servlet container decides when to create or destroy servlets and delegates the client requests. servlet容器决定何时创建或销毁servlet并委托客户端请求。

This is why you might end up having 1 servlet handling the request for n users (n >= 1) and thus in the above sample code using ServletContext every user would end up sharing the session bean of the user who caused creation of the servlet. 这就是为什么你最终可能有一个servlet处理n个用户的请求(n> = 1),因此在上面的示例代码中使用ServletContext,每个用户最终都会共享导致创建servlet的用户的会话bean。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM