在Java中,什么是session?

16

到目前为止,我理解了Java中的Httpsession概念。

 HttpSession ses = req.getSession(true);

将根据请求创建一个会话对象。

setAttribute("String", object);

将会把 'String' 和 value 绑定到 Session 对象。

getAttribute("String");
将返回与指定字符串相关联的对象。
我无法理解的是:我正在创建一个会话对象,如HttpSession ses = req.getSession(true);,并通过调用setAttribute("String", object);为其设置名称。这段代码位于服务器内部。对于每个尝试登录的人,服务器中同样的代码将被执行。setAttribute("String", object);方法中的字符串值是一个常量。因此,创建的每个会话对象都将由我提供的相同字符串绑定。当我尝试检索该字符串以验证他的会话或在执行注销操作时,getAttribute("String");将返回相同的常量字符串值(我是否正确?实际上我不知道,我只在思考它的执行逻辑)。那么,我如何能使它失效呢?
我在所有WEB教程中都看到了这种类型的说明。这是设置属性的实际方式吗?或者,真正的应用程序开发人员是否会在“String”字段中提供变量以动态设置它?
最后一个问题是什么?
WebContext ctx = WebContextFactory.get();
request = ctx.getHttpServletRequest();

上面的两行代码是做什么用的?ctx和request会存储什么内容? HttpSession ses = req.getSession(true); 会创建一个新的session。ses中存储的数值是什么。


2
一个会话(session)与单个用户关联。两个不同的用户有不同的session。如果您想与同一用户共享内容,请在session对象上使用setAttribute。如果涉及多个用户,则使用context对象。您还可以通过将其附加到请求对象来共享对象。 - Abhishek Jain
4个回答

22

一些[随机]的澄清:

  1. 你不需要登录/注销机制来使用会话。
  2. 在Java servlet中,HTTP会话使用两种机制进行跟踪:HTTP cookie(最常用)或URL重写(以支持没有cookie或已禁用cookie的浏览器)。仅使用cookie很简单,您无需做任何特殊处理。对于URL重写,您需要修改指向servlet/filter的所有URL。
  3. 每次调用request.getSession(true)时,将检查HttpRequest对象,以查找编码在cookie或/和URL路径参数(分号后面的内容)中的会话ID。如果找不到会话ID,则Servlet容器(即服务器)将创建新会话。
  4. 会话ID将作为Cookie添加到响应中。如果您还想支持URL重写,则需要使用response.encodeURL()方法修改HTML文档中的链接。如果未找到会话ID或会话ID引用无效会话,则调用request.getSession(false)或简单地调用request.getSession()将返回null。
  5. 每次访问只有一个HTTP会话,因为Java会话cookie不会永久存储在浏览器中。因此,会话对象不在客户端之间共享。每个用户都有自己的私有会话。
  6. 如果一段时间没有使用,会话将自动销毁。超时值可以在web.xml文件中进行配置。
  7. 可以使用invalidate()方法显式地使给定会话无效。
  8. 当人们谈论JSESSIONID时,他们指的是用于在Java中进行会话跟踪的HTTP cookie的标准名称。

13

我建议您阅读一篇有关Java会话的教程。每个用户都会获得一个不同的HttpSession对象,该对象基于Java网络服务器发送到浏览器的JSESSIONID请求/响应参数。因此,每个用户都可以有一个具有相同名称的属性,并且为此属性存储的值对于所有用户来说都是不同的。

此外,WebContextFactory和WebContext是DWR类,它们提供了一种方便的方法来获取Servlet参数。


不太确定为什么这个被踩了。 - Pat
是的,我知道。但是我不明白变量“ctx”和“request”中将存储什么内容。这就是我在那里问的问题。什么是WebContextFactory和WebContext?它们会做什么? - user405398
2
你看过那些类的javadocs了吗?HttpServletRequest: http://download.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html,WebContextFactory: http://www.jarvana.com/jarvana/view/org/directwebremoting/dwr/2.0.3/dwr-2.0.3-javadoc.jar!/org/directwebremoting/WebContextFactory.html,以及WebContext: http://www.jarvana.com/jarvana/view/org/directwebremoting/dwr/2.0.3/dwr-2.0.3-javadoc.jar!/org/directwebremoting/WebContext.html - Kaleb Brasee
1
JSESSIONID不是一个请求参数。 - gawi
我无法理解那里的内容,这就是为什么我向专业人士(stackoverflow)寻求帮助的原因,因为专业人士可以给出实际的观点。无论如何,感谢让我再次阅读文档,给你一个赞。 - user405398

10

据我所理解,您关注的是在HttpSession中存储时不同用户之间的分离问题。

Servlet容器(例如Tomcat)利用其JSESSIONID来处理此问题。

故事是这样的:

  1. 用户首次登录网站。
  2. Servlet容器在用户浏览器上设置一个COOKIE,存储一个唯一的jsessionId。
  3. 每次用户访问网站时,JSESSIONID cookie都会被发送回来。
  4. Servlet容器使用此cookie来跟踪谁是谁。
  5. 同样,这也是它如何跟踪数据分离的方式。每个用户都有自己的对象桶,由JSESSIONID唯一标识。

希望这至少部分回答了您的问题。

干杯


是的,你回答了我问题的一半。我该怎么做才能使一个会话失效(即如何删除特定用户的会话对象,当他们点击注销时)? - user405398
我相信session.invalidate()会终止当前的会话,因此当用户下一次访问该网站时,他们的进程将重新开始。 - lucas1000001
请注意,会话对象不是所有用户共享的单例 - 每个用户都有自己独立的对象! - lucas1000001
是的...是的...现在我才明白。感谢你的回答。 - user405398
2
@所有人:每一个回答都逐渐地消除了我对问题的疑虑。这就是为什么我喜欢StackOverflow。感谢大家。 - user405398

3

您的基本Servlet将如下所示:

public class MyServlet{

public doGet(HttpServletRequest req, HttpServletResponse res){
//Parameter true: 
//    create session if one does not exist. session should never be null 
//Parameter false: 
//    return null if there is no session, used on pages where you want to 
//    force a user to already have a session or be logged in
//only need to use one of the two getSession() options here. 
//Just showing both for this test
HttpSession sess = req.getSession(true);
HttpSession sess2 = req.getSession(false); 

//set an Attribute in the request. This can be used to pass new values
//to a forward or to a JSP
req.setAttribute("myVar", "Hello World");
}

}

不需要为已经完成的会话设置任何属性名称。正如其他答案中所建议的那样,使用cookie或URL重写来存储sessionID。

当您处理DWR WebContext时,它只是做与上述相同的事情,只是通常不会将请求对象传递到方法中,因此您可以使用WebContext获取该请求。

public class DWRClass {
 public doSomething(){
WebContext ctx = WebContextFactory.get();
HttpServletRequest req = ctx.getHttpServletRequest();
HttpSession sess = req.getSession(); //no parameter is the same as passing true

//Lets set another attribute for a forward or JSP to use
ArrayList<Boolean> flags = new ArrayList<Boolean>();
req.setAttribute("listOfNames", flags);
}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接