1、Session简介
Session概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中,这个对象就是 HttpSession。
Session是如何共享数据?(视频17-1.10)
快速入门:
1. 获取HttpSession对象:
HttpSession session = request.getSession();
2. 使用HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
我们之前学过的request、ServletContext、Cookie都可以共享数据,他们都是域对象,而Session也是域对象,它也可以用于共享数据。我们创建sessionTest1类与sessionTest2类,启动服务器,先访问sessionTest1,再访问sessionTest2,发现打印hello Session,这是2次请求,说明可以通过Session域进行同一个会话中的多次请求之间的数据共享。
我们将浏览器关闭,再次访问sessionTest2类,发现打印:null,发现Seeion域数据共享的范围确实是一次会话之间。
相应的测试代码如下:
//sessionTest1类
package lkj.test.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/sessionTest1")
public class SessionTest1 extends HttpServlet
{
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
//首先,在这个Servlet类提供Request对象获取HttpSession对象
HttpSession ss = request.getSession();
//使用HttpSession对象设置共享数据
ss.setAttribute("msg","hello Session");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
this.doPost(request, response);
}
}
//sessionTest2类
package lkj.test.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/sessionTest2")
public class SessionTest2 extends HttpServlet
{
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
//在另一个类,想获取获取SessionTest1类的Session所共享的数据,需要先通过Request对象获取session
HttpSession ss = request.getSession();
//通过HTTPSession对象获取共享数据
Object msg = ss.getAttribute("msg");
System.out.println(msg);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
this.doPost(request, response);
}
}
原理: Session的实现是依赖于Cookie的。
原理见视频18解析。比如上面的例子,我们在2个Servlet资源中获取了2个Session,他们是同一个Session。因为是同一个Session,我们才可以通过它共享数据。
首先我们在资源1中通过Request对象获取一个Session,此时没有Cookie,此时会在内存中创建一个新的Session对象,并使用一个id标识这个Session对象。当响应回去的时候,会通过set-cookie响应头:JSESSION=id值。浏览器收到这个头,会将JSESSION=id值存储到浏览器本地,下次发送的时候,通过Cookie请求头Cookie:JSESSION=id值发送回给访问的服务器资源,服务器会获取这个信息,然后getSession()方法根据id值查找内存中有没有对应的Session对象,如果查找到,返回给HTTPSession对象,如果没有查找到,则会在内存中创建一个新的Session对象。服务器是通过Cookie确保在异常会话范围内Session对象是同一个的。
我们可以通过浏览器抓包来验证,看视频18-6.50
细节1
当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
* 默认情况下。不是。客户端关闭意味着会话结束,会话结束就没有相应的set-cookie以及Cookie头来携带JSESSIONID,那么就肯定不是同一个Session。
* 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存到硬盘,这样子在指定的时间内,不管浏览器是否关闭,都可以获得同一个Session。注意必须是同一个浏览器,不同浏览器则会获得不同的Session。时间结束后,再通过Request获取Session,就会在内存中创建新的Session。
Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);
response.addCookie(c);
相应的代码如下:
package lkj.test.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;