会话追踪技术
1.session机制
什么是会话?
一次会话
:用户打开浏览器,进行一系列操作,然后最终将浏览器关闭,整个过程叫做一次会话。会话在服务器端也有一个对象,这个对象叫做session
对象。
一次请求
:用户打开浏览器,进行点击
等操作的时候,然后到页面上停下来,可以认为是一次请求。请求对应的服务器端的java对象是request
,一次会话对应n
次请求,n∈[1,...]
package javax.servlet.http;
public interface HttpSession {}
Session是B/S
结构的一部分,Session对象的最主要的功能就是保存会话状态信息。
原因:这是因为http协议是
无状态(连接)协议
。请求的时候B和S是连接的
,但是请求结束之后连接就断掉了
,这样的设计能够降低服务器的压力和占用带宽。但是这种设计的缺陷就是无法保存会话的状态。一个例子:当你访问百度首页的时候,这时候你会向百度的服务器发起一次连接请求,当你收到一个
response
的时候,这时候连接管道就会被断开,那你上次连接做的操作,存的数据就都没有了。具体体现在request
和reponse
对象被销毁掉了
一些网站设计的安全退出
按钮和直接点叉叉关闭有什么区别?首先由于服务器是不知道你退出了浏览器的,这时候服务器会保存你的session,你点了安全退出,就相当于告诉服务器你要退出了,这时候就会为你删除掉session
为什么不使用request
对象来保存状态?ServletContext
呢?
关于request
:request对象的生命周期太短,在一次请求和响应中就已经被销毁了,无法保存服务端和浏览器端的会话状态。
关于ServletContext
:这个对象在服务器启动的时候就被创建,在关闭的时候就被销毁,这个ServletContext
就只有一个,那么这个对象对于保存会话状态来说就太大了,而且涉及到多个用户共同访问的并发问题,不适合。
- HttpServlet:请求域
- HttpSession:会话域
- application:应用域
2. Session实现原理
Session是如何获取的?
HttpSession session = request.getSession();
HttpSession session = request.getSession(false);
//加false这个参数是:从服务器获取session,如果获取不到session,那么就不会新建,返回null
如果服务器端没有这个Session
,那么就会新建这个Session
并且保存到服务器端。
为什么能够拿到属于自己的Session?
在web
服务器中有一个如上的session
列表,key是session的key,value是session的对象
当用户发送第一次请求的时候,服务器会创建新的session
对象,然后将session
的id发送给浏览器,然后浏览器会将id
进行缓存。
当用户发送第二次请求的时候,会自动将缓存中的sessionId
发送给web
服务器,然后就能查找到对应的session
对象。
为什么关了浏览器就会导致session失效?
缓存问题
:当你关闭了浏览器的时候,缓存失效,也就是说sessionId不在缓存中了,这时候就相当于一次新的会话
那么一次会话可以解释成SessionId
生成到Session
对象找不到了
Session对象找不到了有两种情况
- 浏览器端找不到了,这种情况是缓存中的sessionId找不到了,清掉了
- 服务器端根据sessionId找不到对应的对象,清掉了
关于销毁的问题
超时销毁
<session-config>
<!--设置超时时间-->
<session-timeout>30</session-timeout>
</session-config>
手动销毁
session.invalidate();
浏览器端向服务端发送的
Session
的形式是以Cookie
的形式传回去的,是放在Http
协议的Header的,Session关联的Cookie不是放在磁盘中的,而是放在浏览器的内存中的。因此关闭浏览器的时候,缓存消失,Cookie消失,因此它就找不到Session了
如果禁用了Cookie,会发生什么?
Cookie禁用:表示服务器正常发送Cookie给浏览器,但是浏览器拒收了Cookie,从而导致浏览器中无法缓存SessionId。
在这种情况下每次都会生成一个新的
Session
对象,尽管浏览器端Cookie没有缓存你的SessionId,但是服务器端的底层依然会在不断生成Session
对象,而这些Session
在等待超时销毁。
解决办法
可以使用URL的重写机制
也就是在URL
后加一个;
JsessionId = ID
,这样的话也可以获得同一个Session
对象
这样的要求是在请求路径后总要加一个JsessionId
作为参数
3. Cookie理论基础
在Session
的实现原理中,每一个Session
对象都会关联一个SessionId
,比如说JSessionId = xxx
,这个ID是通过Cookie
技术缓存到浏览器的运行内存中的。服务器根据这个值来找到这个对象。
Cookie案例
- 存储本地状态:在未登录的情况下,向购物车中放几件商品,然后关闭商城,访问京东商城的时候,购物车内的东西还有,这是怎么做到的?实际上这是一种Cookie的应用手段,后台服务器将这些商品的ID存储到了
Cookie
中,然后保存到了我们的磁盘当中。这样即使关闭浏览器,下次到网站的时候,这时候会自动读取磁盘中的Cookie
,拿到商品编号,然后展示购物车中的商品,Cookie可能是这样的CookieId = xxx,yyy,zzz
等 - 十天内免登录:保存Cookie到本地的磁盘文件中。 登录成功后,浏览器客户端会保存一个
cookie
中保存了用户名和密码等信息,这个cookie
保存在硬盘文件当中的,十天内有效,在十天内用户再次访问126的时候,浏览器自动提交126关联的cookie给服务器,服务器接收到cookie之后,获取用户名和密码,验证,通过之后,自动登录成功。
Cookie保存在什么地方?
Cookie最终保存在浏览器客户端上,可以保存在运行内存中(浏览器关闭则消失),也可以保存在硬盘文件(永久保存)中
Cookie作用
将会话状态保存在浏览器客户端上,与之相对的有保存在浏览器服务端上的session
Cookie格式
任何一个cookie
都是由name
和value
组成的,都是字符串
public class Cookie implements Cloneable {}
public Cookie(String name, String value) {}
//构建Cookie(name,value)
public void setPath(String uri) {this.path = uri; }
//这个方法决定了Cookie将提交给哪个web服务站点,只有对应上了path才会发送对应的cookie
public void setMaxAge(int expiry) {this.maxAge = expiry;}
//设置Cookie的有效期为0,表示该Cookie被删除。删除浏览器上的同名Cookie
//只要这个数值大于0,就会保存在磁盘。
//如果设置为负数,那么就表示该cookie不会被存储到硬盘文件中,但是会被放到浏览器的运行内存中。
//和不调用maxAge()这个方法的效果是一样的。
服务端在生成session
的时候,会将对应的cookie
传递给客户端,那么是怎么实现这个操作的呢,是通过服务端中的一个方法:
void addCookie(Cookie var1);
这个接口方法实现,它会将JVM底层生成的Cookie
对象通过reponse
对象发送给浏览器客户端,然后给了客户端之后,浏览器根据存活时间选择保存策略,要么是通过运行时内存保存,要么是通过磁盘保存。甚至根据用户选择的Cookie
保存选项来确定是否接收Cookie
。
关于Cookie关联的路径
假设现在发送的请求路径是localhost:8080/servlet13/cookie/genarate
生成的cookie,如果cookie没有设置path
,那么关联的路径就是这个请求路径以及它的下级路径localhost:8080/servlet13/cookie/%xxx
public void setPath(String path){}
//这里提交的路径是localhost:8080以后加的东西
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
System.out.println(cookie);
}
//服务端使用cookie,要注意细节,这个方法有可能会返回null,如果没有提交cookie,那么将会返回null,而不是一个长度为0的数组
Cookie的基本设计是键值对,因此可以通过getName()
和 getValue()
的方式来得到相关的数据。