Java:跟踪用户登录会话 - 会话 EJB 与 HTTPSession
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2808773/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: Tracking a user login session - Session EJBs vs HTTPSession
提问by bguiz
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:
使用会话 EJB:
In the implementation of ServletContextListener registered as a Web Application Listener in WEB-INF/web.xml:
在 ServletContextListener 的实现中注册为 Web 应用程序侦听器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);
...
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.HttpSessionin the former, and in a ServletContextin the case of the latter.
在我看来,它们几乎相同,主要区别在于 UserState 实例HttpRequest.HttpSession在前者中被传输,而在ServletContext后者的情况下是在 a中传输。
Which of the two methods is more robust, and why?
这两种方法中哪一种更健壮,为什么?
采纳答案by ewernli
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 HttpSessionand a stateful session bean (SFSB). Especially these two ones:
但是在使用HttpSession和有状态会话 bean (SFSB)之间还有其他更细微的区别。尤其是这两个:
- Exception handling. If a transaction fails in the EJB, the bean is invalidated and can not be used any longer. This can complicate the error handling strategy in the web application.
- Concurrency. The same SFSB can not be accessed concurrently, so you will need to synchronize that in the web layer. Again, this can complicate the design.
- 异常处理。如果 EJB 中的事务失败,则 bean 将失效并且不能再使用。这会使 Web 应用程序中的错误处理策略复杂化。
- 并发。同一个 SFSB 不能同时访问,所以需要在 web 层同步。同样,这会使设计复杂化。
See this answer for more details: Correct usage of SFSB with Servlets
有关更多详细信息,请参阅此答案:正确使用 SFSB 与 Servlets
In summary: I would advise going for the HttpSessionapproach and against the SFSB in your case; use SFSB only if it provides something you can't do with HttpSession, which isn't the case.
总而言之:HttpSession在您的情况下,我建议采用这种方法并反对 SFSB;仅当 SFSB 提供了您无法使用的功能时才使用 SFSB,但事实HttpSession并非如此。
回答by BalusC
The ServletContextrepresents the application scope. 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 allclients.
该ServletContext表示的应用范围。应用程序范围的属性在所有会话中的所有请求之间共享。它是“应用程序范围的全局变量”。您不想在其中存储客户端(因此,会话)特定信息。如果新客户端登录,应用程序范围内的现有 EJB 将被客户端特定的 EJB 覆盖,并反映到所有客户端。
The session scope is exactly for this purpose. Make use of it.
会话范围正是为此目的。好好利用它。
回答by bennidi
Just to clearify a bit: The ServletContext is initialized when a servlet is created (see Servlet Specs) and is unique to that very instance. A servlet uses multiple threads to handle concurrent client requests. The servlet container decides when to create or destroy servlets and delegates the client requests.
澄清一下:ServletContext 在创建 servlet 时被初始化(参见 Servlet 规范),并且对于该实例是唯一的。servlet 使用多个线程来处理并发客户端请求。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.
这就是为什么您最终可能有 1 个 servlet 处理 n 个用户 (n >= 1) 的请求,因此在上面使用 ServletContext 的示例代码中,每个用户最终都会共享导致创建 servlet 的用户的会话 bean。

