Servlet学习笔记(四)

时间:2023-12-10 15:57:56
目录

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文件中修改(没有则创建)

Servlet学习笔记(四)

如果要禁用全部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只在当前的域名内有效,不可夸域名