Servlet-Cookie和HttpSession

会话

会话:用户打开一个浏览器,然后访问一个web应用中的资源,最后关闭浏览器,这个过程可以称为一次会话。
这种会话就是客户端访问的记录,我们就希望能够将这种记录存储下来,所以就诞生了Cookie和HttpSession这两种技术,用于记录浏览器访问web应用的会话。

保存会话的两种技术

Cookie

它是客户端存储会话的技术。

我们直接先看Cookie类的常用成员方法:

方法功能
public Cookie(String name, String value)该类的构造方法,想要新建一个Cookie类对象就,就必须声明其属性名name和属性值value
public void setDomain(String domain)指定该Cookie对象指定可见的域
public String getDomain()获取该Cookie对象的可见域
public void setMaxAge(int expiry)以秒为单位,设置该Cookie对象的最长生命值,负数表示为临时的Cookie,关闭浏览器就销毁了,0表示删除该cookie,正数表示它的最大生命周期
public int getMaxAge()获取该Cookie对象的最大生命值,未设置生命周期的Cookie数据默认为临时Cookie(MaxAge默认为-1)
public String getName()获取该Cookie的属性名
public void setValue(String newValue)更改该Cookie对象的属性值
public String getValue()获取该Cookie对象的属性值

我们先获取Cookie数据试试,在此之前,我们没有手动添加过任何Cookie:

package cn.ara.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CookieServlet01 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取客户端的cookie数据
        Cookie[] cookies = req.getCookies();
	//遍历打印输出
        if (cookies != null) {
	    for (Cookie cookie : cookies) {
	        System.out.println(cookie.getName() + ":" + cookie.getValue());
	    }
	}
	
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

使用360浏览器访问该CookieServlet01资源,控制台打印输出为空,说明浏览器在首次访问web应用的资源时是没有Cookie数据的。

接下来我们自行设置一些Cookie数据:

package cn.ara.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CookieServlet02 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //自定义Cookie数据
        Cookie cookie = new Cookie("username", "Ara_Hu");
        //写回客户端
        resp.addCookie(cookie);

        cookie = new Cookie("sex","男");
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

我们先打开浏览器的调试功能,找到网络选项,访问CookieServlet02,我们可以看到如下的Cookie数据:

在这里插入图片描述

我们发现客户端收到的响应Cookie中包含了我们设置的Cookie数据,然后我们再次请求CookieServlet01,再观察客户端Cookie数据的变化:

在这里插入图片描述

这个时候我们明显发现,客户端请求该web应用时的资源时就会将之前的收到的Cookie数据携带上,并且控制台也输出了我们设置的Cookie数据。

修改和删除Cookie数据:

package cn.ara.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CookieServlet03 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        Cookie[] cookies = req.getCookies();

        if (cookies != null) {
            for (Cookie cookie : cookies) {

                if ("username".equals(cookie.getName())) {
                    //删除username这条cookie数据
                    cookie.setMaxAge(0);
                    resp.addCookie(cookie);
                }

                if ("sex".equals(cookie.getName())) {
                    //修改sex这条cookie数据
                    cookie.setValue("女");
                    resp.addCookie(cookie);
                }
            }
        }


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

然后我们请求CookieServlet03,发现Cookie数据就会有所变化:
在这里插入图片描述
我们发现sex的值已经改变,username的值回来了,但是它的有效期为0,再刷新一次,我们就发现没有username这个Cookie数据了。
在这里插入图片描述
当我们把浏览器关闭之后,再次打开访问该web应用时,我们发现请求时Cookie数据就没有了,因为我们并未设置它的有效期。

package cn.ara.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CookieServlet04 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取系统当前时间
        long now = System.currentTimeMillis();

        //将当前时间存到Cookie中
        Cookie cookie = new Cookie("lastRequestTime", now + "");

        //设置其有效期为3分钟
        cookie.setMaxAge(60*3);

        //写回Cookie数据
        resp.addCookie(cookie);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

在这里插入图片描述

当我们设置了Cookie的有效时间之后,它在不被主动清除的前提下,它的的生命周期就是我们设置的3分钟,在这时间内,我们即使关闭浏览器,它也会存在,直至过期销毁,我们快速关闭浏览器,再访问CookieServlet01,发现Cookie数据还在。
在这里插入图片描述
当过去三分钟之后,我们再次访问,就没有Cookie数据了。

注:当Cookie传递中文时,可能会出现问题,我们可以使用以下方式对中文数据进行编码和解码:

//编码
String encode = URLEncoder.encode("编码内容", "编码方式");

//解码
String dncode = URLDecoder.decode("解码内容","解码方式");

这种存储方式虽然减少了服务器端的存储压力,但是直接存储到客户端,数据就会直接暴露给客户端,如果是比较重要的数据,就会出现对应的问题,所以就出来了一种存在服务器端的Session。

HttpSession

它是服务器存储会话的技术,它是依赖于cookie的,它也存储了cookie数据在客户端浏览器,但是它并没有直接将信息显式的放在客户端,而是只放了一个id记录的cookie数据在客户端浏览器,客户端可以根据这个id的cookie数据在web应用中的HttpSession中找到在服务器端存储的数据,这仅限于一次会话,关闭浏览器之后,session就会销毁。

还是先看看其中的方法:

方法作用
public long getCreationTime();返回该session创建的时间毫秒值
public String getId();返回一个字符串,其中包含分配给此会话的唯一标识符id
public long getLastAccessedTime();返回客户端上次发送与该会话相关的请求的时间
public ServletContext getServletContext();获取该web应用的ServletContext对象
public void setMaxInactiveInterval(int interval);设置该session的最大有效时间
public int getMaxInactiveInterval();获取该session的有效时间
public Object getAttribute(String name);获取该session域中的指定属性值
public Enumeration getAttributeNames();获取该session对象中存储的所有属性名
public void setAttribute(String name, Object value);在该session中设置指定属性,如果已存在,则替换之前的值
public void removeAttribute(String name);移除该session中指定的属性
public void invalidate();销毁该session,使之无效
public boolean isNew();判断该session是不是新的,就是判断客户端在请求服务器端的时候是否携带了标记sessionid的的cookie的值,存在返回true,不存在返回false
package cn.ara.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;

public class SessionServlet01 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取session对象,
        // 如果请求中带有JSESSIONID的Cookie,就获取该id指定的session,
        // 否则创建一个新的JSESSIONID,在响应客户端时以cookie的形式写回
        HttpSession session = req.getSession();

        //打印session的id和它是否是新创建的 F4E82D22E3B3787F58FD8AF2FFA9EA0D:true
        System.out.println(session.getId() + ":" + session.isNew());
        //打印创建时间 第一次访问该Servlet的时间
        System.out.println("CreationTime:" + new Date(session.getCreationTime()));
        //打印上次访问时间
        System.out.println("LastAccessedTime:" + new Date(session.getLastAccessedTime()));

        //循环遍历session中的内容
        Enumeration<String> attributeNames = session.getAttributeNames();
        while (attributeNames.hasMoreElements()) {
            String name = attributeNames.nextElement();
            Object attribute = session.getAttribute(name);

            System.out.println(name + "---" + attribute);
        }

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

用浏览器访问SessionServlet01,并抓包,观察它的Cookie变化如下:

在这里插入图片描述

我们发现,它响应了一个JSESSIONID的cookie数据回来,这个Cookie数据并不是我们手动设置的,对比上面的实验和控制台的打印输出,可以推断出这个cookie数据就是记录的Session的id值,这也说明了session的实现也有cookie的“功劳”。

我们存储一些数据在session中:

package cn.ara.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;

public class SessionServlet02 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取session对象
        HttpSession session = req.getSession();

        //打印session的id和它是否是新创建的
        System.out.println(session.getId() + ":" + session.isNew());

        session.setAttribute("name","Ara_hu");
        session.setAttribute("sex","男");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

然后我们重启服务器,重新访问SessionServlet01,让其重新生成新的Session(因为web应用关闭之后,存放在服务器中的session就会对应销毁,但是客户端的cookie数据还存在,所以会出现请求时包含cookie数据,但是服务器端已经找不到这个指定的session了,所以它会创建一个session,返回的cookie就是一个全新的sessionId):
在这里插入图片描述

然后再访问SessionServlet02,让它存一些数据在session中,

在这里插入图片描述
控制台输出:4EE5EFB3CEED28FF3218D17931F54CBA:false

我们再访问SessionServlet01,查看控制台是否打印出我们设置在session的属性
在这里插入图片描述
在这里插入图片描述
我们发现后两次请求时,服务器端就没有返回新的JSESSIONID数据了,然后我们将浏览器关闭,重新访问SessionServlet01,再观察控制台输出:
在这里插入图片描述
在这里插入图片描述
这时之前记录sessionId的Cookie数据就自行销毁了,这也说明session的有效期仅限于一次会话,会话结束后,session的值就会自行销毁。

我们也能手动的设置session的有效期,在web.xml中添加如下配置:

<session-config>
    <!--设置session10分钟失效-->
    <session-timeout>10</session-timeout>
</session-config>

这个配置和public void setMaxInactiveInterval(int interval);方法的效果一致,如果用户一直保持着会话但是长时间未响应,这个时间之后,session就会自动失效。

Cookie和Session的区别
CookieSession
存储在客户端存储在服务器(服务器会将sessionId以cookie的形式写回客户端)
Cookie不安全Session相对比较安全
Cookie数据有限制,只能存储字符串类型的数据,而且单个Cookie数据不能超过4K,浏览器一般对一个站点限制20个Cookie,一个浏览器最多能存储300个CookieSession没有对存储量进行限制,它还能保存复杂的数据类型
Cookie的有效期相对更长Session则很容易失效(浏览器关闭就失效了)
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值