Session对象的创建一般是源于这样的一条语句:
Session session = request.getSession(false);或者Session session = request.getSession();如果不在乎服务器压力可能多那么一点点的话。
在Tomcat的实现中,这个request是org.apache.catalina.connector.Request类的包装类org.apache.catalina.connector.RequestFacade的对象,它的两个#getSession()方法如下:
其实差不太多,最后都会进入org.apache.catalina.connector.Request的#getSession()方法。这个方法的源代码如下:
然后调用就到了#doGetSession()这个方法了。源代码如下
这个方法说明了Session创建的大致过程,首先判断requestedSessionId是否存在,如果存在,那么根据这个ID去查找Session对象。如果requestedSessionId不存在或者没有取到Session,并且传递给#getSession(boolean)的参数为真,那么要创建一个新的Session,并且给客户端写回去一个Session Cookie。
首先,我感兴趣的是requestedSessionId的赋值,它到底是什么时候被赋值的呢?
还要向回看Tomcat的请求处理过程,请求曾到过这一步,org.apache.catalina.connector.CoyoteAdapter的#service()方法。里边有这样一句方法调用:postParseRequest(req, request, res, response)。就是这一步处理了SessionID的获取,这个方法调用了#parseSessionId()和parseSessionCookiesId()这两个方法,就是它对Session ID进行了提取,源代码分别如下:
Tomcat就是通过上边的两个方法读到URL或者Cookie中存放的Session ID的。
了解了Session ID的获取,下面要看一下Session的查找过程,就是org.apache.catalina.session.StandardManager的#findSession()方法。这个方法是在它的基类中定义的,源代码如下:
代码很短,其中sessions是一个ConcurrentHashMap<String, Session>对象。那么这个sessions的对象是什么时候载入的Session呢?
启动的时候!可以看一下StandardManager#start()方法。最后调用了#load()方法,这个就是载入Session的方法了:
最后调用了#doLoad()方法来具体的载入Session,源代码如下:
大致知道了Session的读取过程,后面就是Session没找到时创建Session的过程了。具体就是org.apache.catalina.session.StandardManager的#createSession()方法:
最后调用到了它的基类的#createSession()方法了。
通过上述过程,一个新的Session就创建出来了。
Session session = request.getSession(false);或者Session session = request.getSession();如果不在乎服务器压力可能多那么一点点的话。
在Tomcat的实现中,这个request是org.apache.catalina.connector.Request类的包装类org.apache.catalina.connector.RequestFacade的对象,它的两个#getSession()方法如下:
- public HttpSession getSession(boolean create) {
- if (request == null) {
- throw new IllegalStateException(
- sm.getString("requestFacade.nullRequest"));
- }
- if (SecurityUtil.isPackageProtectionEnabled()){
- return (HttpSession)AccessController.
- doPrivileged(new GetSessionPrivilegedAction(create));
- } else {
- return request.getSession(create);
- }
- }
- public HttpSession getSession() {
- if (request == null) {
- throw new IllegalStateException(
- sm.getString("requestFacade.nullRequest"));
- }
- return getSession(true);
- }
其实差不太多,最后都会进入org.apache.catalina.connector.Request的#getSession()方法。这个方法的源代码如下:
- public HttpSession getSession(boolean create) {
- Session session = doGetSession(create);
- if (session != null) {
- return session.getSession();
- } else {
- return null;
- }
- }
然后调用就到了#doGetSession()这个方法了。源代码如下
- protected Session doGetSession(boolean create) {
- // 没有Context的话直接返回null
- if (context == null)
- return (null);
- // 判断Session是否有效
- if ((session != null) && !session.isValid())
- session = null;
- if (session != null)
- return (session);
- // 返回Manager对象,这里是StandardManager类的对象
- Manager manager = null;
- if (context != null)
- manager = context.getManager();
- if (manager == null)
- return (null); // Sessions are not supported
- // 判断是否有SessionID
- if (requestedSessionId != null) {
- try {
- // 在Manager中根据SessionID查找Session
- session = manager.findSession(requestedSessionId);
- } catch (IOException e) {
- session = null;
- }
- if ((session != null) && !session.isValid())
- session = null;
- if (session != null) {
- // 更新访问时间
- session.access();
- return (session);
- }
- }
- // 创建新的Session
- if (!create)
- return (null);
- if ((context != null) && (response != null) && context.getCookies()
- && response.getResponse().isCommitted()) {
- throw new IllegalStateException(sm.getString("coyoteRequest.sessionCreateCommitted"));
- }
- // 判断是否使用 "/" 作为Session Cookie的存储路径 并且 是否SessionID来自Cookie
- if (connector.getEmptySessionPath() && isRequestedSessionIdFromCookie()) {
- // 创建Session
- session = manager.createSession(getRequestedSessionId());
- } else {
- session = manager.createSession(null);
- }
- // 创建一个新的Session Cookies
- if ((session != null) && (getContext() != null) && getContext().getCookies()) {
- Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME, session.getIdInternal());
- // 配置Session Cookie
- configureSessionCookie(cookie);
- // 在响应中加入Session Cookie
- response.addCookieInternal(cookie);
- }
- if (session != null) {
- // 更新访问时间
- session.access();
- return (session);
- } else {
- return (null);
- }
- }
这个方法说明了Session创建的大致过程,首先判断requestedSessionId是否存在,如果存在,那么根据这个ID去查找Session对象。如果requestedSessionId不存在或者没有取到Session,并且传递给#getSession(boolean)的参数为真,那么要创建一个新的Session,并且给客户端写回去一个Session Cookie。
首先,我感兴趣的是requestedSessionId的赋值,它到底是什么时候被赋值的呢?
还要向回看Tomcat的请求处理过程,请求曾到过这一步,org.apache.catalina.connector.CoyoteAdapter的#service()方法。里边有这样一句方法调用:postParseRequest(req, request, res, response)。就是这一步处理了SessionID的获取,这个方法调用了#parseSessionId()和parseSessionCookiesId()这两个方法,就是它对Session ID进行了提取,源代码分别如下:
- protected void parseSessionId(org.apache.coyote.Request req, Request request) {
- ByteChunk uriBC = req.requestURI().getByteChunk();
- // 判断URL中是不是有";jsessionid="这个字符串
- int semicolon = uriBC.indexOf(match, 0, match.length(), 0);
- if (semicolon > 0) {
- // Parse session ID, and extract it from the decoded request URI
- // 在URL中提取Session ID
- int start = uriBC.getStart();
- int end = uriBC.getEnd();
- int sessionIdStart = semicolon + match.length();
- int semicolon2 = uriBC.indexOf(';', sessionIdStart);
- if (semicolon2 >= 0) {
- request.setRequestedSessionId(new String(uriBC.getBuffer(), start + sessionIdStart,
- semicolon2 - sessionIdStart));
- byte[] buf = uriBC.getBuffer();
- for (int i = 0; i < end - start - semicolon2; i++) {
- buf[start + semicolon + i] = buf[start + i + semicolon2];
- }
- uriBC.setBytes(buf, start, end - start - semicolon2 + semicolon);
- } else {
- request.setRequestedSessionId(new String(uriBC.getBuffer(), start + sessionIdStart,
- (end - start) - sessionIdStart));
- uriBC.setEnd(start + semicolon);
- }
- // 设定Session ID来自于URL
- request.setRequestedSessionURL(true);
- } else {
- request.setRequestedSessionId(null);
- request.setRequestedSessionURL(false);
- }
- }
- protected void parseSessionCookiesId(org.apache.coyote.Request req, Request request) {
- Context context = (Context) request.getMappingData().context;
- if (context != null && !context.getCookies())
- return;
- // 返回Cookie
- Cookies serverCookies = req.getCookies();
- int count = serverCookies.getCookieCount();
- if (count <= 0)
- return;
- for (int i = 0; i < count; i++) {
- ServerCookie scookie = serverCookies.getCookie(i);
- // 判断是否有JSESSIONID这个名字的Cookie
- if (scookie.getName().equals(Globals.SESSION_COOKIE_NAME)) {
- // Override anything requested in the URL
- if (!request.isRequestedSessionIdFromCookie()) {
- // 设定Session ID
- convertMB(scookie.getValue());
- request.setRequestedSessionId(scookie.getValue().toString());
- // 如果之前在URL中读到了SessionID,那么会覆盖它
- request.setRequestedSessionCookie(true);
- request.setRequestedSessionURL(false);
- if (log.isDebugEnabled())
- log.debug(" Requested cookie session id is " + request.getRequestedSessionId());
- } else {
- if (!request.isRequestedSessionIdValid()) {
- convertMB(scookie.getValue());
- request.setRequestedSessionId(scookie.getValue().toString());
- }
- }
- }
- }
- }
Tomcat就是通过上边的两个方法读到URL或者Cookie中存放的Session ID的。
了解了Session ID的获取,下面要看一下Session的查找过程,就是org.apache.catalina.session.StandardManager的#findSession()方法。这个方法是在它的基类中定义的,源代码如下:
- public Session findSession(String id) throws IOException {
- if (id == null)
- return (null);
- return (Session) sessions.get(id);
- }
代码很短,其中sessions是一个ConcurrentHashMap<String, Session>对象。那么这个sessions的对象是什么时候载入的Session呢?
启动的时候!可以看一下StandardManager#start()方法。最后调用了#load()方法,这个就是载入Session的方法了:
- public void load() throws ClassNotFoundException, IOException {
- if (SecurityUtil.isPackageProtectionEnabled()) {
- try {
- AccessController.doPrivileged(new PrivilegedDoLoad());
- } catch (PrivilegedActionException ex) {
- Exception exception = ex.getException();
- if (exception instanceof ClassNotFoundException) {
- throw (ClassNotFoundException) exception;
- } else if (exception instanceof IOException) {
- throw (IOException) exception;
- }
- if (log.isDebugEnabled())
- log.debug("Unreported exception in load() " + exception);
- }
- } else {
- doLoad();
- }
- }
最后调用了#doLoad()方法来具体的载入Session,源代码如下:
- protected void doLoad() throws ClassNotFoundException, IOException {
- if (log.isDebugEnabled())
- log.debug("Start: Loading persisted sessions");
- // 清空Map
- sessions.clear();
- // 对应work/Catalina/localhost/%app name%/SESSIONS.ser文件
- File file = file();
- if (file == null)
- return;
- if (log.isDebugEnabled())
- log.debug(sm.getString("standardManager.loading", pathname));
- FileInputStream fis = null;
- ObjectInputStream ois = null;
- Loader loader = null;
- ClassLoader classLoader = null;
- try {
- // 载入Session缓存文件
- fis = new FileInputStream(file.getAbsolutePath());
- BufferedInputStream bis = new BufferedInputStream(fis);
- if (container != null)
- loader = container.getLoader();
- if (loader != null)
- classLoader = loader.getClassLoader();
- if (classLoader != null) {
- if (log.isDebugEnabled())
- log.debug("Creating custom object input stream for class loader ");
- ois = new CustomObjectInputStream(bis, classLoader);
- } else {
- if (log.isDebugEnabled())
- log.debug("Creating standard object input stream");
- ois = new ObjectInputStream(bis);
- }
- } catch (FileNotFoundException e) {
- if (log.isDebugEnabled())
- log.debug("No persisted data file found");
- return;
- } catch (IOException e) {
- log.error(sm.getString("standardManager.loading.ioe", e), e);
- if (ois != null) {
- try {
- ois.close();
- } catch (IOException f) {
- ;
- }
- ois = null;
- }
- throw e;
- }
- synchronized (sessions) {
- try {
- // 读出Session个数
- Integer count = (Integer) ois.readObject();
- int n = count.intValue();
- if (log.isDebugEnabled())
- log.debug("Loading " + n + " persisted sessions");
- // 读入Session
- for (int i = 0; i < n; i++) {
- StandardSession session = getNewSession();
- session.readObjectData(ois);
- session.setManager(this);
- sessions.put(session.getIdInternal(), session);
- session.activate();
- sessionCounter++;
- }
- } catch (ClassNotFoundException e) {
- log.error(sm.getString("standardManager.loading.cnfe", e), e);
- if (ois != null) {
- try {
- ois.close();
- } catch (IOException f) {
- ;
- }
- ois = null;
- }
- throw e;
- } catch (IOException e) {
- log.error(sm.getString("standardManager.loading.ioe", e), e);
- if (ois != null) {
- try {
- ois.close();
- } catch (IOException f) {
- ;
- }
- ois = null;
- }
- throw e;
- } finally {
- try {
- if (ois != null)
- ois.close();
- } catch (IOException f) {
- }
- // 删除Session缓存文件
- if (file != null && file.exists())
- file.delete();
- }
- }
- if (log.isDebugEnabled())
- log.debug("Finish: Loading persisted sessions");
- }
大致知道了Session的读取过程,后面就是Session没找到时创建Session的过程了。具体就是org.apache.catalina.session.StandardManager的#createSession()方法:
- public Session createSession(String sessionId) {
- if ((maxActiveSessions >= 0) && (sessions.size() >= maxActiveSessions)) {
- rejectedSessions++;
- throw new IllegalStateException(sm.getString("standardManager.createSession.ise"));
- }
- return (super.createSession(sessionId));
- }
最后调用到了它的基类的#createSession()方法了。
- public Session createSession(String sessionId) {
- // 创建一个新的Session
- Session session = createEmptySession();
- // 初始化Session的属性
- session.setNew(true);
- session.setValid(true);
- session.setCreationTime(System.currentTimeMillis());
- session.setMaxInactiveInterval(this.maxInactiveInterval);
- // 如果Session ID为null,那么就生成一个
- if (sessionId == null) {
- sessionId = generateSessionId();
- }
- session.setId(sessionId);
- sessionCounter++;
- return (session);
- }
通过上述过程,一个新的Session就创建出来了。
相关推荐
jsp课程中内置对象session,jsp教程中的上课源代码
这是一个用springMVC的项目 是一个监听器 用于监听session的创建、销毁、移除。会触发相应的事件处理
本次工程的目标是学习监听器,掌握监听三个对象的创建和销毁方法。 三个对象:rquest,session,ServletContext 实现的接口:ServletRequestListener,HttpSessionListener,ServletContextListener 工程的大致步骤...
JSP简易购物车! 实现了向购物车添加物品,删除物品,计算物品总价格,使用session存储物品对象。 使用:部署后启动服务器,通过访问项目名称-BS直接可以运行!简单,易懂! 供大家学习用!
在进行接口测试的时候,我们会调用多个接口发出多个请求...# 创建一个session对象 s = requests.Session() # 用session对象发出get请求,设置cookies s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
Cart对象会放在Session对象里。 具体的设计: 表:t_computer create table t_computer( id bigint primary key auto_increment, name varchar(50), description varchar(100), pic varchar(255), price ...
http协议本身是一种无状态的协议,也就是客户端连续发送的多...Session对象是一个jsp内置对象,它在第一个jsp页面被装载时自动创建,完成会话期管理。 从一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开
当客户重新打开浏览器再连接到该服务器时,服务器为该客户再创建一个新的Session对象。 (3)Session对象的常用方法 ● public String getId():获取Session对象编号。 ● public void setAttribute(String...
本文详细介绍了PHP中的Session对象,从概念到如何创建,再到一般结构。希望对你有帮助,一起来看。
6、Session对象为空。 7、对控件赋文本值时,值不存在。 8、使用Request.QueryString()时,所获取的对象不存在,或在值为空时未赋初始值。 9、使用FindControl时,控件不存在却没有做预处理。 10、重复定义造成未将对象...
简单的网上购物,将购买者的姓名、商品名保存在session对象中,实现一个web目录下的页面对session对象中信息的共享。要求创建三个页面,第一个页面输入用户的姓名,第二个页面输入购买商品名的名称,第三个页面实现...
思路是ASP.NET中序列化Session以二进制数据保存到数据库,然后由JSP读取数据库中的二进制数据反序列化成Session对象,再强制转化成的Session对象,在JAVA端转换时,出现了错误,找遍网上的资料也没能解决,故采用一...
Request,Response,Session,Application,Server和Cookie。当web应用程序运行时,这些对象可以用来维护有关...由于ASP.NET在初始化页面请求时已经自动创建了这些内部对象,因此可以直接使用它们而无需再对类进行实例化。
在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象,即session对象,这篇文章就为大家详细介绍Session对象的定义、实现原理等基础知识点,感兴趣的小伙伴们可以参考一下
session对象指的是客户端与服务器的一次会话,从客户端连到服务器的一个WebApplication开始,直到客户端与服务器断开连接为止。它是HttpSession类的实例. 序号 方 法 说 明 1 long getCreationTime() 返回...
Java EJB中有、无状态SessionBean的两个例子,的无状态SessionBean可,会话Bean必须实现SessionBean,获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,计算利息等; 在有状态SessionBean中,用累加...
当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。 通过向客户程序发送唯一的 Cookie 可以管理服务器上的 ...
其他对象只能查询这些数据行,不能进行update、delete或select...for update操作。 insert / update / delete ... ; 是3的锁。 没有commit之前插入同样的一条记录会没有反应, 因为后一个3的锁会一直...
是非线程安全的(尽管创建一个Session对象消耗的资源很小),所以在获取Session对象时候也最好用单例模式获取 3.提交并清空Session中缓存的数据后开始一个事务 Session对象.flush(); //将Session中的缓存内容提交到...