(七)Session 对象知识点总结(来自那些年的笔记)

如果你想要转载话,可不可以不要删掉下面的 作者信息 呀!;

作者:淮左白衣

写于 

来源笔者自己之前学javaWeb的时候,写的笔记 ;

目录


Session对象

web 开发中,服务器可以为用户浏览器创建一个会话对象(session对象

注意一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其他程序时,其他程序可以从用户的 session 中取出该用户的数据,为用户服务 ;


Session和cookie的主要区别在于:

  • Cookie是把用户数据写给用户的浏览器

  • session技术把用户的数据写到用户独占的session中。

    Session对象有服务器创建,开发人员 可以调用request对象的 getSession 方法得到session对象 。

一个session对象只为一个会话服务也就是说在 同一台电脑 上,打开 同一个浏览 器两次,会创建2个session对象。这里就引申出 session的生命周期 问题 ;


Session对象的生命周期

创建并不是浏览器访问服务器就会创建session对象而是当浏览器访问的资源中有 getSession() 这个方法时,才会创建session对象

当session对象创建以后再次访问 getSession() 这个方法时,不会创建新的session对象;只是去获取服务器已经创建好的 session 对象 ;

销毁: 当一个 session 对象 30分钟 内没有人使用,那么服务器就会销毁这个session对象无论浏览器是否关闭,即使浏览器没有被关闭,但是只要这个session对象30分钟内没有被使用,就会被销毁 ; 这个 30分钟,我们是可以通过修改服务器的配置来改变这个有效时长的 ;

通过服务器配置,修改 session 有效时长:单位是分钟

<session-config>
<session-timeout>10</session-timeout>
</session-config>

通过代码,销毁session

//      销毁session对象
session.invalidate();

getSession()方法重载

这样,就会只获取session,而不创建session ;如果,没有创建对象,则返回null ;

request.getSession(false) ;

session的实现原理

其实 session 是基于 cookie 的;

设想一下,为什么服务器那么聪明,可以知道什么时候创建session对象,什么时候不创建而是去获取session ?

原因 :就在于 session 是基于 cookie 技术的; 服务器第一次为浏览器创建一个 session 对象的时候,(这里要知道每一个session对象,都是带有id),会将session的idcookie的形式回写给浏览器。

因此,当服务器遇到 getSession() 方法的时候,它会看浏览器是否带有标识 session 对象idcookie来,如果这样的cookie,则为这次会话,创建一个session对象;如果有带着标识session对象的idcookie来,则服务器根据id,返回对应的session对象;

这个 cookie 是没有设置有效时长的,因此就是一个会话的 cookie 这也解释了为什么同一个浏览器打开两次,访问服务器会创建不同的session;


为服务器自动回写的cookie设置保存时长

服务器没有为代表Id的cookie没有设置有效时长,显然是不合理的,假如我们在逛淘宝,由于我们误操作,导致浏览器关闭了,那么我们之前的买的商品就丢失了,还需要再去买一次;

因此,我们需要去设置一个有效时长 ;

具体方法:就是获得session对象的id,然后创建一个cookie,将cookie的名字和patn设置,与服务器自动回写的cookie一致;然后设置有效时长 ;

其中服务器回自动写的cookie的名字为“JSESSIONID”,pathWEB项目的路径


getSession( )内部原理

getSession()方法,获取到特定的session对象 ;

内部实现 ;它先根据代表id的cookie来获取 ;如果没有这个cookie,就会去看是否重写了URL地址,如果重写了URL,则根据url后面的id来获取session对象;

如果,上述两种方法都没有,则获取不到session,它会创建一个session对象 ;


URL地址重写

当浏览器 禁止接受cookie 的时候,我们需要对URL地址,进行重写,以达到根据cookie分辨出,谁是谁的session的效果

我们需要对我们的网址的超链接,进行URL重写,就是在超链接的后面添加浏览器各自的session对象的 id ;这样,根据这个id,response.getSession() 就可以获得服务器中已创建的 session 对象了 ;

URL重写这一步 Sun 公司帮我们做好了:方法:response.encodeURL(url) ,自动在url后面加上session的id,返回一个带有id标识的超链接 ;这样,即使禁止了保存cookie,服务器还是可以知道谁是谁的session ;

但是,假如浏览器禁止保存cookie,即使我们进行了URL地址重写,当关闭浏览器,再打开,就会创建新的session对象了 ;,因为,毕竟浏览器端,是不保存任何cookie的数据的 ;进行URL重写,只能保证,一次会话期间,服务器可以分辨出,谁是谁的session ;

只要涉及到会话管理的url,都要重写URL地址,因为,我们不确定浏览器是否禁止保存cookie了;

当我们进行了URL重写的时候 ,重定向,sendRedirect后面的地址,需要使用encodeRedirectURL() ;

细节当我们没有禁止保存cookie的时候,同时又存在重写URL编码,这时候,会发生什么呢?

在第一次访问服务器的时候,服务器是不知道浏览器是否禁止了cookie,它会回写一个cookie,并且同时还对URL地址进行重写;这时候刷新一下页面的时候,浏览器就会带着cookie去访问服务器,服务器发现浏览器没有禁止cookie,就不再对URL地址进行重写 ;

备注:同一个浏览器,打开多个选项卡,或者打开新的窗口,都会共享session对象,因为浏览器的进程没有销毁,cookie还存活着;以上的话都是基于IE7,到IE8就变了,即使关闭浏览器再打开,还是共享session对象 ;


Session案例

模拟购物功能;但是一般都是用cookie来完成,考虑到服务器压力,为每个用户创建一个session保存购物信息,需要巨大的内存空间,而且session有效时间为半小时,时间越久服务器压力越大 ;

模拟登录功能;使用session的原因,是因为其他servlet需要知道用户的登录状态;我们把用户的登录状态保存到session对象中,便于其他servlet查看;(cookie也可以完成)

保存登录状态:就是保存用户的对象,一个唯一的标记即可 ;注销登录状态,就是将浏览器对应的session对象中的标记去除 ;

还是一样的,代码太多 ,贴上来,也不一定有人看,别说代码,就这篇博客,可能都没人看,,,

假如,你真的需要代码,可以加下我的QQ:1255621959 ;(好孩子看不到系列,(全选试试))


表单细节:

在写表单的时候,需要为提交的内容写一个name属性,没有这个name属性,对应的数据是不会得到提交的 ;

表单默认以get方式提交;表单上添加action属性,表示将数据提交到哪里;

防止表单重复提交;

有两种方法可以防止重复提交 ;
  • 在客户端使用JS

    但是,这样做不是万无一失的;对于懂行的人来说,可以查看网页源代码,会看到表单的源代码,它会得到我们将表单提交的servlet地址;也会发现,我们是使用JS来防止重复提交的,它只要将js的代码删除,保存页面再继续访问,数据就会被重复提交;(简而言之JS代码会被删掉

  • 在服务器端防止数据重复提交

    我们在服务器端使用程序生成一个随机数将这个随机数放到表单里面,进行返回,服务器在浏览器提交数据的时候,会检查浏览器提交的数据带有的随机数,在服务器中是否存在;如果存在了,则说明表单已经提交过了;

  • 随机数问题

    如果随机数,在服务器中存在;则允许提交数据;在提交完数据以后,将服务器保存的随机数删掉;下次浏览器再次提交数据,也不会处理了;

    在生成随机数的时候,使用单例模式,创建一个随机数发生器,目的是为了防止减少随机数重复的概率;我们一般使用当前时间的毫秒值+一个随机数来拼接成一个随机数 ;


数据指纹算法

拼接随机数的时候,后面的随机数的长度是不确定的,导致拼接的随机数长度也是不确定的;我们最好保证每次生成的随机数的长度是一致的;但是显然是不可能的保证到的;但是我们可以使用数据指纹,无论数据的长度是多少,它们的数据指纹长度是固定的 ;我们选用MD5算法,生成数据指纹,长度是128位(16K);

//          获取当前时间的毫秒值
long time = System.currentTimeMillis();
String random = time + new Random().nextInt() + "";
// 由于拼接出来的random长度是不一样的
try {
// 转化为长度固定为128位的MD5数据指纹
byte[] md5 = MessageDigest.getInstance("md5").digest(random.getBytes());
// MD5需要进行base64编码
return Base64.encode(md5);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}

MessageDigest.digest()方法,生成数据指纹;返回的是一个字节数组 ;MD5还是可以用于验证信息的完整性 ;


base64编码

不能使用得到的 数据指纹 字节数组直接new字符串,因为生成的字节数组里面的放到的东西是啥,我也不清楚,反正GB2312码表里面没有转码会出现乱码这是就需要特定的转码方法base64编码

Base64编码 是将每3个字节变为4个字节;三个字节24位,每次取6位,空余的2个高位用0补全 ;这样3个字节就变为4个字节;组成的四个字节,每个字节的最小值为0(00000000),最大值为63(00111111);然后base64编码有自己的码表,它把0~63都变为明文,即键盘上可见的字符;这样无论原始数据,是什么,都可以变为明文,而不出现乱码 ;

Base64编码的使用场景很多,比如上传下载文件,浏览器都会自动的把数据进行base64编码的;这样就可以选择不在base64码表中的字符来当做结束开始标记 ;


验证码的验证:

在服务器发送验证码给浏览器的时候,先将验证码存储到浏览器对应的session对象中;然后验证浏览器带过来的验证码和保存到session中的验证码是否一样; (注意编码问题)


再讲转发与重定向的区别

  • 转发

    浏览器的url的地址是不会发生改变的,这样每次刷新页面,都会执行转发之前的逻辑和转发

    这样,在有些场景就会出现问题,比如买东西,每次刷新,都会再次执行买的逻辑,买无数次。。。

  • 重定向

    浏览器的url的地址发生改变,,这样每次刷新页面,都会执行新的地址的

    还是买定西的场景:会将购买商品的页面的地址重定向到购物车的地址,这样刷新,就是刷新购物车,和购买商品没关系。就不会出现购买多次的情况了 ;


Servlet的提供的容器(域)

  • request

    数据仅仅使用一次,使用结束以后,就没有用了的情况,选用request域 ;

  • session

    数据使用完以后,过一会还需要继续使用,选用session域

  • servletContext

    数据使用完以后,过一会还需要继续使用,不仅还需要继续使用,等会还需要给别人使用,选用servletContext域 ;

上一篇:自己封装一个简单的ajax插件


下一篇:重温Servlet学习笔记--session对象