目录

Servlet学习笔记(四)

一、会话技术Cookie、session

1. 什么是会话技术?

指用户打开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程我们称为一次会话,在一次会话中可以有多次请求,可以共享数据

会话跟踪技术有Cookie和Session,Cookie技术是先出现的

2. 会话技术有什么用?

我们在登录网站时候,有的会提示是否自动登录,这样得到下次访问就可以直接不用登录了,这就是使用了会话技术的

3. Cookie

3.1 什么是Cookie?

Cookie是由W3C组织提出,最早由netscape社区发展的一种机制

  • 我也之间交互是通过HTTP协议传输数据的,但是HTTP协议是无状态的,一旦提交完数据,浏览器和服务器的连接就会被关闭,再次连接时候又是一个新的连接,服务器无法直到是否浏览器上次来过了。多以W3C提出了:给每一个用户发一个通行证,无论谁访问都携带通行证,这样服务器就可以直到用户的信息了
3.2 使用Cookie

Cookie是基于响应头set-cookie请求头cookie实现的

**浏览器对于单个cookie 的大小有限制(4kb) **

添加Cookie

//设置response的编码
response.setContentType("text/html;charset=utf-8");
//创建一个Cookie对象
Cookie cookie = new Cookie("username", "linzeliang");
//将cookie的maxAge过期时间设置为1小时
cookie.setMaxAge(60 * 60)
//将cookie对象添加到response对象,发送cookie
response.addCookie(cookie);

获取Cookie

//通过request获取浏览器发送来的Cookie
Cookie[] cookies = request.getCookies();
//遍历cookies,获取每一个cookie
for (Cookie cookie : cookies) {
System.out.println(cookie.getValue());
}

Cookie工作流程:

  • 浏览器访问服务器,如果服务器需要记录该用户的状态,就使用response向浏览器发送一个Cookie,浏览器会把Cookie保存起来。当浏览器再次访问服务器的时候,浏览器会把请求的网址连同Cookie一同交给服务器

Cookie API:

  • Cookie类用于创建一个Cookie对象
  • response接口中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段
  • request接口中定义了一个getCookies方法,它用于获取客户端提交的Cookie

常用的Cookie方法:

  • public Cookie(String name,String value)
  • setValue与getValue方法
  • setMaxAge与getMaxAge方法
  • setPath与getPath方法
  • setDomain与getDomain方法
  • getName方法
3.2 可以创建多个Cookie吗?

可以的。可以同通过调用多次addCookie方法来发送多个cookie,浏览器就也会收到多个Cookie

3.3 Cookie在浏览器保存多久时间?
  • 在默认情况下,只要关闭浏览器,Cookie就会被销毁
  • 如果要持久化储存,即存储到硬盘上,则需要在服务器设置response.setMaxAge(int seconds)
    • 如果seconds为整数,则数字就是代表存储多少秒
    • 如果为负数(也就是默认的-1),代表Cookie是临时性的,关闭浏览器立即销毁该Cookie
    • 如果为0,代表删除Cookie信息,即下一次浏览器向客户端请求时,不带该cookie,因为已经删除了
3.4 Cookie保存中文
  • 在Tomcat8之前,Cookie不能保存中文,需要将中文进行URL编码

    Cookie cookie = new Cookie("username", URLEncoder.encode("名字", "UTF-8"));
    //同样,既让是通过URL编码发送到了浏览器,浏览器也是按照URL编码存储到硬盘中的,我们在获取cookie时候还需要将其解码
    Cookie[] cookies = request.getCookies();
    for (Cookie cookie : cookies) {
    String name = cookie.getValue();
    //URLDecoder解码
    String value = URLDecoder.decode(name, "UTF-8");
    System.out.println(value);
    }
  • 在Tomcat8及其之后,cookie支持中文数据,但是还是不支持特殊字符。为了容易维护,建议都使用URL编码进行存储和解析

3.5 Cookie的不可跨域名性

在访问Servlet的时候浏览器是不是把所有的Cookie都带过去给服务器会不会修改了别的网站的Cookie?是不会的的,Cookie具有不可跨域名性。浏览器判断一个网站是否能操作另一个网站的Cookie的依据是域名。所以一般来说,当我访问baidu的时候,浏览器只会把baidu颁发的Cookie带过去,而不会带上google的Cookie

3.6 修改、删除Cookie的值

Cookie机制也没有提供修改Cookie的方法,那么我们怎么修改Cookie的值呢?

我们可以通过Cookie的名字相同。通过response来添加到浏览器中,这样就会覆盖之前的Cookie了

Cookie删除即将色图Max Age修改为0即可

注意:删除,修改Cookie时,新建的Cookie除了value、maxAge之外的所有属性都要与原Cookie相同。否则浏览器将视为不同的Cookie,不予覆盖,导致删除修改失败

3.7 Cookie的共享

正常的cookie只能在一个应用中共享,即一个cookie只能由创建它的应用获得。

  1. 默认情况下在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie不能共享,如果需要共享,只需要设置setPath("/")即可,因为默认的就是当前的虚拟目录("/"指的是相对路径,本例中即是应用部署路径,tomcat/webapp)

    设置cookie.setPath("/webapp_a/jsp")或者cookie.setPath("/webapp_a/jsp/")的时候,只有在webapp_a/jsp下面可以获得cookie,在webapp_a下面但是在jsp文件夹外的都不能获得cookie

  2. 不同的tomcat服务器间cookie共享问题

    Cookie的domain属性决定运行访问Cookie的域名。domain的值规定为“.域名”

    • Cookie的隐私安全机制决定Cookie是不可跨域名的。也就是说www.baidu.comwww.google.com之间的Cookie是互不交接的。即使是同一级域名,不同二级域名也不能交接,也就是说:www.goole.comwww.image.goole.com的Cookie也不能访问

    • 如果现在我希望一级域名相同的网页Cookie之间可以相互访问。也就是说www.img.linzeliang.com可以获取到www.linzeliang.com的Cookie就需要使用到domain方法

      Cookie cookie = new Cookie("username", "linzeliang");
      cookie.setMaxAge(60 * 60);
      cookie.setDomain(".linzeliang.com");
      response.addCookie(cookie);
  3. setPath()和setDomain()区别:

    • Cookie中的setDomain()主要用来在两个不同名称但是后缀相同的网站地址上(不同主机),这样两个网站就能使用同一个cookie了
    • setPath()主要用来确定什么后缀下能够使用这个cookie,即地址栏上面的地址的约束
3.8 Cookie的安全属性

HTTP协议不仅是无状态,而且也不安全的,因为是明文传输的,如果不希望Cookie在非安全协议中传输,那么可以设置Cookie的secure属性为true,这样浏览器只会在HTTPS和SSL等安全协议中传输该Cookie

3.9 Cookie的应用

显示用户的上次访问时间

  • 如果用户第一次登录,那么就记录下时间,发送Cookie,并且在页面打印时第一次登录;如果不是第一次,就显示上一次是什么时候登录的

  • 代码如下:

    response.setContentType("text/html;charset=utf-8");
    //获取浏览器发送的所以cookie
    Cookie[] cookies = request.getCookies();
    //用来判断是否访问过了
    boolean flag = false;
    if (cookies != null && cookies.length != 0) {
    for (Cookie cookie : cookies) {
    if ("lastTime".equals(cookie.getName())) {
    //标记访问过了
    flag = true;
    //获取上一次登录记录
    String dateValue = cookie.getValue();
    dateValue = URLDecoder.decode(dateValue, "utf-8");
    PrintWriter pw = response.getWriter();
    //显示到浏览器中
    pw.write("<center><h1>您好,您上一次登录是在" + dateValue + "</h1></center>"); //获取这次访问的时间记录
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    String str_date = sdf.format(date);
    str_date = URLEncoder.encode(str_date, "utf-8");
    cookie.setValue(str_date);
    cookie.setMaxAge(60*60*24*30);
    //发送新的Cookie,覆盖掉原来的
    response.addCookie(cookie); break;
    }
    }
    }
    //第一次访问
    if (cookies == null || cookies.length == 0 || flag == false) {
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    String str_date = sdf.format(date);
    //要用URL编码,否则空格浏览器不能解析
    str_date = URLEncoder.encode(str_date, "utf-8");
    Cookie cookie = new Cookie("lastTime", str_date);
    cookie.setMaxAge(60*60*24*30);
    response.addCookie(cookie);
    }

4.Session

4.1什么是Session?

Session 服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中,对应的是HttpSession对象

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

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

有了Cookie为什么还要session?

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

4.2 使用Session

获取Session对象

//获取session对象
HttpSession session = request.getSession();
//设置session属性
session.setAttribute("username", "linzeliang");

从其他的Servlet访问Session对象设置的属性

HttpSession session = request.getSession();
String value = (String) session.getAttribute("username");
System.out.println(value);
//打印的结果就是linzeliang

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

Session API

  • long getCreationTime();【获取Session被创建时间】
  • String getId();【获取Session的id】
  • long getLastAccessedTime();【返回Session最后活跃的时间】
  • ServletContext getServletContext();【获取ServletContext对象】
  • void setMaxInactiveInterval(int var1);【设置Session超时时间】
  • int getMaxInactiveInterval();【获取Session超时时间】
  • Object getAttribute(String var1);【获取Session属性
  • Enumeration getAttributeNames();【获取Session所有的属性名】
  • void setAttribute(String var1, Object var2);【设置Session属性】
  • void removeAttribute(String var1);【移除Session属性】
  • void invalidate();【销毁该Session】
  • boolean isNew();【该Session是否为新的】
4.3 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
  • 默认情况下不是(虽然也会自动发送JSESSIONID,但是setMaxAge是默认的,一关闭浏览器Cookie就没了,所以无法通过ID找到原来的session,所以不相同)

  • 如果需要相同,那么可以创建Cookie,键为JSESSIONID。设置setMaxAge

    Cookie c = new Cookie("JSESSIONID", session.getId());
    c.setMaxAge(60 * 60);
    response.addCookie(c);
4.4 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
  • 不是同一个,但是为了保证数据不丢失,tomcat会自动完成如下操作:

    • session的钝化:

      • 在服务器正常关闭以前,将session对象序列化到硬盘上
    • session的活化:
      • 服务器启动后,将session文件转化为session对象(虽然对象不是同一个,但是数据确是一样的)
4.3 session什么时候被销毁?
  1. 服务器被关闭

  2. session对象调用invalidate()方法,让session中的多有属性失效,常常用于安全退出

  3. 或者等待30分钟没有活跃就会被销毁(用于用户多,防止内存溢出),但是30分钟我们可以在web.xml配置文件中修改(默认是30分钟,如果tomcat的web.xml和自己的web应用的web.xml冲突,那么以自己的为准)

    <session-config>
    <session-timeout>60(自定义时间,默认30)</session-timeout>
    </session-config>
  4. 通过setMaxInactiveInterval()方法设置

    //设置Session最长超时时间为60秒,这里的单位是秒
    session.setMaxInactiveInterval(60);
    System.out.println(session.getMaxInactiveInterval());
4.4 Session和Cookie的有效期不同
  1. session:

    • session的周期是指多长时间内没有访问
    • 如果希望session的某个属性失效,可以使用removeAttribute()方法
  2. Cookie:
    • Cookie的周期就是 从这个Cookie到达用户内存中开始计时,不管期间有没有访问过
4.5 Cookie被禁用怎么办?

由于Session是基于Cookie运行的,如果禁用了Cookie,session要怎么办呢?

  • 我们可以对URL进行重写,HttpServletResponse又encodeURL(String url)和encodeRedirectURL(String url)tring url)和encodeRedirectURL(String url),重写完成后,使用sendRedirect来重定向,这样JSESSIONID在URL中被带过去了
  • URL地址重写的原理将Session的id信息重写到URL地址中服务器解析重写后URL,获取Session的id。这样一来,即使浏览器禁用掉了Cookie,但Session的id通过服务器端传递,还是可以使用Session来记录用户的状态

encodeURL(java.lang.String url)该方法的实现机制为:

  • 先判断当前的 Web 组件是否启用 Session,如果没有启用 Session,直接返回参数 url。
  • 再判断客户端浏览器是否支持 Cookie,如果支持 Cookie,直接返回参数 url;如果不支持 Cookie,就在参数 url 中加入 Session ID 信息,然后返回修改后的 url。
4.5 Session禁用Cookie(让Session不依赖Cookie)

Java Web规范支持通过配置禁用Cookie,禁用自己项目的Cookie,在META-INF文件夹下的context.xml文件中修改(没有则创建)

如果要禁用全部web应用的Cookie,在conf/context.xml

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

4.8 Session的特点
  • session用于存储一次会话的多次请求的数据,存储在服务器端
  • session可以存储任意数据类型,任意大小的数据
4.9 Session和Cookie的区别

从存储方式上比较

  • Cookie只能存储字符串,如果要存储非ASCII字符串还要对其编码

  • session大小没有限制,cookie最大为4kb(4095-4097B,不同浏览器不一样,所以一般认为最大不超过4095B)

  • session存储数据安全,cookie存储数据相对来说不安全

  • 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只在当前的域名内有效,不可夸域名

Servlet学习笔记(四)的更多相关文章

  1. servlet学习笔记四

    Servlet 主要内容: 1)servlet初始化参数与上下文参数 2)过滤器 3)监听器一.servlet初始化参数与上下文参数 1)servlet初始化参数 把某些变量放在web.xml配置,到 ...

  2. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  3. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  4. java之jvm学习笔记四(安全管理器)

    java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...

  5. Learning ROS for Robotics Programming Second Edition学习笔记(四) indigo devices

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  6. Typescript 学习笔记四:回忆ES5 中的类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  7. ES6学习笔记<四> default、rest、Multi-line Strings

    default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...

  8. muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制

    目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ...

  9. python3.4学习笔记(四) 3.x和2.x的区别,持续更新

    python3.4学习笔记(四) 3.x和2.x的区别 在2.x中:print html,3.x中必须改成:print(html) import urllib2ImportError: No modu ...

随机推荐

  1. Numpy中的shape和reshape()

    shape是查看数据有多少行多少列reshape()是数组array中的方法,作用是将数据重新组织 1.shape import numpy as np a = np.array([1,2,3,4,5 ...

  2. 总线SPI的Arduino库函数

    来源参考:https://www.cnblogs.com/MyAutomation/p/9348480.html 总线SPI的Arduino库函数 SPI基本知识 SPI:高速同步串行口.是一种标准的 ...

  3. C语言中time_t数据类型详细介绍

    包含文件:<time.h> #ifndef __TIME_T #define __TIME_T     /* 避免重复定义 time_t */ typedef long     time_ ...

  4. 用C写一个简单的推箱子游戏(一)

    我现在在读大二,我们有一门课程叫<操作系统>,课程考查要求我们可以写一段程序或者写Windows.iOS.Mac的发展历程.后面我结合网上的资料参考,就想用自己之前简单学过的C写一关的推箱 ...

  5. Linux设备驱动中的阻塞和非阻塞I/O <转载>

    Green 博客园 首页 新随笔 联系 订阅 管理 Linux设备驱动中的阻塞和非阻塞I/O   [基本概念] 1.阻塞 阻塞操作是指在执行设备操作时,托不能获得资源,则挂起进程直到满足操作所需的条件 ...

  6. Tomcat配置Gizp 客户端使用okHttp3

    找到tomcat 在 server.xml 新增如下配置 <Connector connectionTimeout="20000" port="8088" ...

  7. 自定义chrome新标签页

    [跳转GitHub] chromeNewTab 自定义chrome新标签页.由于不想发布到chrome应用商店,因此搜了一下不用开发者模式就能用的方法. 使用说明 下载chrome的一个[window ...

  8. centos8上安装mysql8

    一,下载并解压mysql8 1,mysql官网 https://www.mysql.com/ 2,下载到source目录 [root@yjweb source]# wget https://cdn.m ...

  9. 【Azure 环境】连接到微软云Azure中国区 By VS 2019, VS Code, Powershell

    问题情形 最近,在使用最新的VS Code插件连接到中国区的Azure时候,出现了依旧是global版的登录连接.这个问题是当前Azure Account插件最新版的问题,可以使用V0.8.11版本登 ...

  10. 使用浏览器抓取QQ音乐接口(歌曲篇)

    前言 前面我们获取了歌曲的排行榜的数据,我们现在需要实现歌曲播放 前面我们写了一段函数来得到了回调的数据,现在我们需要使用这一段数据,来实现播放歌曲 完整代码 <!DOCTYPE html> ...