javaweb之Servlet(四)会话技术【Session】

Session 是另一种记录浏览器状态的机制。不同的是Cookie保存在浏览器中,Session保存在服务器中。用户使用浏览器访问服务器的时候,服务器把用户的信息以某种的形式记录在服务器,这就是Session。

如果说Cookie是检查用户身上的”通行证“来确认用户的身份,那么Session就是通过检查服务器上的”客户明细表“来确认用户的身份的。Session相当于在服务器中建立了一份“客户明细表”。

Session比Cookie使用方便,Session可以解决Cookie解决不了的事情【Session可以存储对象,Cookie只能存储字符串。】。

Session API

  1. long getCreationTime();【获取Session被创建时间】
  2. String getId();【获取Session的id】
  3. long getLastAccessedTime();【返回Session最后活跃的时间】
  4. ServletContext getServletContext();【获取ServletContext对象】
  5. void setMaxInactiveInterval(int var1);【设置Session超时时间】
  6. int getMaxInactiveInterval();【获取Session超时时间】
  7. Object getAttribute(String var1);【获取Session属性】
  8. Enumeration getAttributeNames();【获取Session所有的属性名】
  9. void setAttribute(String var1, Object var2);【设置Session属性】
  10. void removeAttribute(String var1);【移除Session属性】
  11. void invalidate();【销毁该Session】
  12. boolean isNew();【该Session是否为新的】

Session作为域对象

从上面的API看出,Session有着request和ServletContext类似的方法。其实Session也是一个域对象。Session作为一种记录浏览器状态的机制,只要Session对象没有被销毁,Servlet之间就可以通过Session对象实现通讯

一般来讲,当我们要存进的是用户级别的数据就用Session,那**什么是用户级别呢?**只要浏览器不关闭,希望数据还在,就使用Session来保存。

代码案例:
servlet向session中存数据


//得到Session对象
HttpSession httpSession = request.getSession();

//设置Session属性
httpSession.setAttribute("name", "看完博客就要点赞!!");

servlet向session中取数据


//获取到从Servlet4的Session存进去的值
HttpSession httpSession = request.getSession();
String value = (String) httpSession.getAttribute("name");
System.out.println(value);

Session的生命周期和有效期

  • Session在用户第一次访问服务器Servlet,jsp等动态资源就会被自动创建,Session对象保存在内存里,这也就为什么上面的例子可以直接使用request对象获取得到Session对象。
  • 如果访问HTML,IMAGE等静态资源Session不会被创建。
  • Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,无论是否对Session进行读写,服务器都会认为Session活跃了一次。
  • 由于会有越来越多的用户访问服务器,因此Session也会越来越多。为了防止内存溢出,服务器会把长时间没有活跃的Session从内存中删除,这个时间也就是Session的超时时间。
  • Session的超时时间默认是30分钟,有三种方式可以对Session的超时时间进行修改

session设置有效时间
第一种方式在tomcat/conf/web.xml文件中设置,时间值为20分钟,所有的WEB应用都有效

            
<session-config>
	<session-timeout>20</session-timeout>
</session-config>    

第二种方式:在单个web应用的web.xml文件中设置,对单个web应用有效,如果有冲突,以自己的web应用为准。

            
<session-config>
    <session-timeout>20</session-timeout>
</session-config>    

第三种方式:通过setMaxInactiveInterval()方法设置


//设置Session最长超时时间为60秒,这里的单位是秒
httpSession.setMaxInactiveInterval(60);

System.out.println(httpSession.getMaxInactiveInterval());

Session的有效期与Cookie的是不同的
在这里插入图片描述

Session的实现原理

服务器是如何实现一个session为一个用户浏览器服务的?换个说法:为什么服务器能够为不同的用户浏览器提供不同session?

  • HTTP协议是无状态的,Session不能依据HTTP连接来判断是否为同一个用户。于是乎:服务器向用户浏览器发送了一个名为JESSIONID的Cookie,它的值是Session的id值。其实Session依据Cookie来识别是否是同一个用户。
  • 简单来说:Session 之所以可以识别不同的用户,依靠的就是Cookie
  • 该Cookie是服务器自动颁发给浏览器的,不用我们手工创建的。该Cookie的maxAge值默认是-1,也就是说仅当前浏览器使用,不将该Cookie存在硬盘中
  • 所以:同一个浏览器中(也就是同一个会话)的不同 servlet 请求同一个服务器的时候,浏览器会把Cookie的值通过http协议带过去给服务器,服务器就知道用哪一个Session。

浏览器禁用了Cookie,Session还能用吗?

正常使用浏览器来请求 servlet 是不可以使用的。因为禁用了Cookie,所以用户浏览器并没有把Cookie带过去给服务器。

但是Java Web提供了解决方法:URL地址重写

  • HttpServletResponse类提供了两个URL地址重写的方法:
    • encodeURL(String url)
    • encodeRedirectURL(String url)
  • 需要值得注意的是:这两个方法会自动判断该浏览器是否支持Cookie,如果支持Cookie,重写后的URL地址就不会带有jsessionid了【当然了,即使浏览器支持Cookie,第一次输出URL地址的时候还是会出现jsessionid(因为没有任何Cookie可带)】

URL地址重写的原理:**将Session的id信息重写到URL地址中。服务器解析重写后URL,获取Session的id。**这样一来,即使浏览器禁用掉了Cookie,但Session的id通过服务器端传递,还是可以使用Session来记录用户的状态。

Session禁用Cookie

Java Web规范支持通过配置禁用Cookie

  • 禁用自己项目的Cookie
    • 在META-INF文件夹下的context.xml文件中修改(没有则创建)
<?xml version='1.0' encoding='utf-8'?>
        
<Context path="/ouzicheng" cookies="false">
</Context>
  • 禁用全部web应用的Cookie
    • 在conf/context.xml中修改
<!-- The contents of this file will be loadedfor each web application --> 
<Context cookies="false">    
  <!-- ... 中间代码略 --> 
</Context> 

注意:该配置只是让服务器不能自动维护名为jsessionid的Cookie,并不能阻止Cookie的读写。

Session案例

使用Session完成用户简单登陆
String username = request.getParameter("username");
String password = request.getParameter("password");

User user = UserDB.find(username, password);

//如果找不到,就是用户名或密码出错了。
if (user == null) {
	response.getWriter().write("you can't login");
	return;
}

//标记着该用户已经登陆了!
HttpSession httpSession = request.getSession();
httpSession.setAttribute("user", user);

//跳转到其他页面,告诉用户成功登陆了。
response.sendRedirect(response.encodeURL("index.jsp"));
利用Session防止表单重复提交
  • 重复提交的危害:
    • 在投票的网页上不停地提交,实现了刷票的效果。
    • 注册多个用户,不断发帖子,扰乱正常发帖秩序。
  • 首先来看一下常见的重复提交。
    • 在处理表单的Servlet中刷新。
    • 后退再提交
    • 网络延迟,多次点击提交按钮

1、对于网络延迟造成的多次提交数据给服务器,其实是客户端的问题。于是,我们可以使用javaScript来防止这种情况

  • 要做的事情也非常简单:当用户第一次点击提交按钮时,把数据提交给服务器。当用户再次点击提交按钮时,就不把数据提交给服务器了。监听用户提交事件。只能让用户提交一次表单!
  • 由于网络延迟造成的多次提交数据给服务器,我们还可以使用javaScript代码这样解决:当我点击过一次提交按钮时,我就把提交的按钮隐藏起来。不能让用户点击了!

2、在处理表单的Servlet中刷新和后退再提交这两种方式不能只靠客户端来限制了。也就是说javaScript代码无法阻止这两种情况的发生。

思路分析

  • Session可以用来标识一个用户是否登陆了。Session的原理也说了:不同的用户浏览器会拥有不同的Session。而request和ServletContext为什么就不行呢?request的域对象只能是一次http请求,提交表单数据的时候request域对象的数据取不出来ServletContext代表整个web应用,如果有几个用户浏览器同时访问,ServletContext域对象的数据会被多次覆盖掉,也就是说域对象的数据就毫无意义了。

  • 在表单中还有一个隐藏域,可以通过隐藏域把数据交给服务器。

    • 判断Session域对象的数据和jsp隐藏域提交的数据是否对应。
    • 判断隐藏域的数据是否为空【如果为空,就是直接访问表单处理页面的Servlet】
    • 判断Session的数据是否为空【servlet判断完是否重复提交,最好能立马移除Session的数据,不然还没有移除的时候,客户端那边儿的请求又来了,就又能匹配了,产生了重复提交。如果Session域对象数据为空,证明已经提交过数据了!】
  • 向Session域对象的存入数据究竟是什么呢?简单的一个数字?好像也行啊。因为只要Session域对象的数据和jsp隐藏域带过去的数据对得上号就行了呀,**反正在Servlet上判断完是否重复提交,会立马把Session的数据移除掉的。**更专业的做法是:向Session域对象存入的数据是一个随机数【Token–令牌】。

实现原理是非常简单的:

  • 在session域中存储一个token
  • 然后前台页面的隐藏域获取得到这个token
  • 在第一次访问的时候,我们就判断seesion有没有值,如果有就比对。对比正确后我们就处理请求,接着就把session存储的数据给删除了
  • 等到再次访问的时候,我们session就没有值了,就不受理前台的请求了!

但这种方式适用于 jsp 页面,因为需要在jsp中获取session的值。以后开发前后端分离开发主要在前端解决。

Session和Cookie的区别

  • 从存储方式上比较

    • Cookie只能存储字符串,如果要存储非ASCII字符串还要对其编码。
    • Session可以存储任何类型的数据,可以把Session看成是一个容器
  • 从隐私安全上比较

    • Cookie存储在浏览器中,对客户端是可见的。信息容易泄露出去。如果使用Cookie,最好将Cookie加密
    • Session存储在服务器上,对客户端是透明的。不存在敏感信息泄露问题。
  • 从有效期上比较

    • Cookie保存在硬盘中,只需要设置maxAge属性为比较大的正整数,即使关闭浏览器,Cookie还是存在的
    • Session的保存在服务器中,设置maxInactiveInterval属性值来确定Session的有效期。并且Session依赖于名为JSESSIONID的Cookie,该Cookie默认的maxAge属性为-1。如果关闭了浏览器,该Session虽然没有从服务器中消亡,但也就失效了。
  • 从对服务器的负担比较

    • Session是保存在服务器的,每个用户都会产生一个Session,如果是并发访问的用户非常多,是不能使用Session的,Session会消耗大量的内存。
    • Cookie是保存在客户端的。不占用服务器的资源。像baidu、Sina这样的大型网站,一般都是使用Cookie来进行会话跟踪。
  • 从浏览器的支持上比较

    • 如果浏览器禁用了Cookie,那么Cookie是无用的了!
    • 如果浏览器禁用了Cookie,Session可以通过URL地址重写来进行会话跟踪。
  • 从跨域名上比较

    • Cookie可以设置domain属性来实现跨域名
    • Session只在当前的域名内有效,不可跨域名(其实是不能跨服务器),也可以将session存储到redis等第三方存储中。

Cookie和Session共同使用

如果仅仅使用Cookie或仅仅使用Session可能达不到理想的效果。

服务器为Session自动维护的Cookie的maxAge属性默认是-1的,当浏览器关闭掉了,该Cookie就自动消亡了。当用户再次访问的时候,已经不是原来的Cookie了。

问题:即使我不小心关闭了浏览器了,我重新进去网站,我还能找到我的购买记录。
答:服务器为Session自动维护的Cookie的maxAge属性是-1,Cookie没有保存在硬盘中。我现在要做的就是:把Cookie保存在硬盘中,即使我关闭了浏览器,浏览器再次访问页面的时候,可以带上Cookie,从而服务器识别出Session。

实现方式:
**第一种方式:**只需要在处理购买页面上创建Cookie,Cookie的值是Session的id返回给浏览器即可


Cookie cookie = new Cookie("JSESSIONID",session.getId());
cookie.setMaxAge(30*60);
cookie.setPath("/ouzicheng/");
response.addCookie(cookie);

第二种方式: **在server.xml文件中配置,将每个用户的Session在服务器关闭的时候序列化到硬盘或数据库上保存。**但此方法不常用,知道即可!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JavaWeb的Cookie和Session是用于在服务器和客户端之存储和传递数据的机制。 Cookie是在客户端(浏览器)保存少量数据的文本文件,它由服务器发送给浏览器,并在浏览器下一次向同一服务器发送请求时被浏览器携带过去。Cookie可以用于实现用户认证、记住登录状态、记录用户行为等功能。在JavaWeb,可以使用`javax.servlet.http.Cookie`类来创建和设置Cookie。 Session是在服务器端存储用户信息的一种机制。当用户第一次访问服务器时,服务器会为该用户创建一个唯一的会话标识(Session ID),并将该标识保存在Cookie发送给客户端。客户端在后续的请求会带上这个Session ID,服务器通过这个Session ID可以获取到对应的会话信息。在JavaWeb,可以使用`javax.servlet.http.HttpSession`类来创建、获取和操作Session。 Cookie和Session的区别主要有: 1. 存储位置:Cookie存储在客户端,Session存储在服务器端。 2. 容量限制:Cookie有大小限制,一般为4KB左右;Session可以存储较大量的数据。 3. 安全性:Cookie数据存储在客户端,容易被恶意篡改;Session数据存储在服务器端,相对较安全。 4. 生命周期:Cookie可以设置过期时间,可以长期保存在客户端;Session默认情况下会在一段时间内保持活跃,超过时间会被销毁。 在实际应用,Cookie和Session常常结合使用,通过Cookie存储Session ID来实现用户的身份验证和状态管理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值