前言
感谢
Cookie和Session概念介绍
什么叫做会话
会话指在多次HTTP连接间维护用户与同一用户发出的不同请求之间的关联称之为维护一个会话。
用人话来讲,我们在浏览器中进行访问,点击了很多链接,访问了很多的资源,最后关闭了浏览器。这个过程可以叫做会话
保存会话的两种技术
保存会话
因为HTTP是一种无状态的协议,这个无状态的意思是指,脸盲。
这个意思就好比,今天强哥交了个女朋友,聊得很开心。第二天女朋友来找他,强哥不认识了,要重新介绍一遍。
所以要解决强哥不认识女朋友的问题就是要让强哥做个标记,告诉强哥这就是女朋友。
在HTTP中也一样,今天我请求了,你知道了,下一个请求你又不认识了。每一次请求之间都是独立的,所以叫做无状态。
那么我要让你记住我之前来过,这就叫做保存会话。
Cookie和Session
强哥要记住自己有个女朋友
1、一种就是在女方身上搞个身份牌,上面写着我是强哥的女朋友
2、一种是在强哥那里登记,说谁谁谁是我女朋友
在HTTP中也是如此,保存会话就要在双方做手脚,这个双方就是客户端和服务器
1、Cookie,我们又称为客户端会话技术
2、Session,我们又称为服务器会话技术
Cookie,甜点;Session,主菜。
其实我们从英文单词就可以分析一下,很明显Session比Cookie要高级一些,对比强哥的那个例子。
Cookie其实是给客户端的一个通行证,每个客户端都有一个,这样服务器就可以从通行证上知道客户端的身份
Session其实就是一张登记表,这张登记表记录着客户端的状态,当客户端来的时候服务器只要一翻登记表就知道客户端的身份
Cookie和Session的区别
我们在这前大体了解了Cookie和Session,这里先说一下他们的区别
1、Cookie存储在客户端浏览器上,Session存放在服务器上
2、Cookie保存的数据<=4K,许多浏览器都限制一个站点上限20个Cookie,浏览器上限300个。Session无上限
3、Cookie只能保存ASCII,并且需要通过编码方式存储为Unicode字符或者二进制。Session无限制
4、Cookie对客户端可见,Session对客户端不可见。所以Cookie不如Session安全
5、Cookie可以设置时间令其长期有效,Session依赖名为JSESSIONID的Cookie,而它默认关闭窗口就失效,所以不能长期有效
6、Cookie保存在客户端浏览器,不占用服务器资源。Session保存在服务端,并发时会占用大量内存
7、Cookie支持跨域,Session不支持跨域
Cookie详解
快速起步
1、Cookie[] request.getCookie()
:获取Cookie
2、Cookie cookie = new Cookie(String name,String value)
:创建cookie
3、response.addCookie(Cookie cookie)
:发送cookie对象
4、cookie.getName()
:获取cookie名字
5、cookie.getValue()
:获取cookie值
package com.howling;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
@WebServlet("/cookie")
public class CookieProject extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取cookie
Cookie[] cookies = req.getCookies();
Arrays.stream(cookies).forEach(cookie -> {
System.out.print(cookie.getName());
System.out.print("----");
System.out.println(cookie.getValue());
});
System.out.println("--------------------");
//创建cookie
Cookie cookie = new Cookie("username", "howling");
//添加cookie
resp.addCookie(cookie);
}
}
在浏览器上和最后的输出都显示出来了,请求Cookie有两个,一个是Idea-xxx,一个是JSESSIONID,这个Cookie是不是很熟悉,因为我们之前讲过 回复的Cookie就是username,值为howling 所以,在浏览器上查看Cookie实际上是更加方便的,所以我们以后就在浏览器上查看Cookie
实现原理
Cookie的实现原理并不复杂,其实是根据请求头cookie和响应头set-cookie实现的,下面请看浏览器
我们可以看到,请求头中有着Cookie的请求,而响应头中存在Set-Cookie的请求,这也证实了我们的说法
Cookie的更多说明
可不可以一次性发送多个Cookie
可以,只需要创建多个Cookie对象,然后多次调用response的addCookie即可
Cookie的过期时间
1、默认情况下,当浏览器关闭时Cookie销毁
2、可以人工进行持久化存储
cookie.setMessage() 1、正数:将Cookie保存在硬盘中,数字就是过期时间,以秒为单位。过期Cookie自动失效 2、负数:默认值,关闭浏览器就失效 3、零:Cookie无效,也就是直接删除Cookie
package com.howling;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
@WebServlet("/cookie")
public class CookieProject extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建cookie
Cookie cookie = new Cookie("username", URLEncoder.encode("嚎羸","utf-8"));
//设置保存时间为5分钟
cookie.setMaxAge(60*5);
//添加cookie
resp.addCookie(cookie);
}
}
Cookie可不可以存储中文
1、Tomcat8之前需要用到编码和解码
2、Tomcat8之后支持中文数据,但是特殊字符仍然不支持
3、建议不管怎样都要使用URL编码存储,URL编码解析
package com.howling;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
@WebServlet("/cookie")
public class CookieProject extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取cookie
Cookie[] cookies = req.getCookies();
Arrays.stream(cookies).forEach(cookie -> {
System.out.print(cookie.getName());
System.out.print("----");
System.out.println(cookie.getValue());
});
System.out.println("--------------------");
//创建cookie
Cookie cookie = new Cookie("username", URLEncoder.encode("嚎羸","utf-8"));
//添加cookie
resp.addCookie(cookie);
String decode = URLDecoder.decode(cookie.getValue(), "utf-8");
System.out.println(decode);
}
}
Cookie共享
假如在一个Tomcat中有多个Web项目,这些项目中Cookie可不可以共享?
1、默认情况下Cookie不可以共享
2、可以手动设置共享
cookie.setPath(String path)
:设置Cookie的获取范围,默认情况下是设置当前虚拟目录 默认情况下设置当前虚拟目录是为了保证只有在当前的项目中才可以访问 假如我们要设置共享,只需要将path设置为"/"
即可
package com.howling;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
@WebServlet("/cookie")
public class CookieProject extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建cookie
Cookie cookie = new Cookie("username", URLEncoder.encode("嚎羸","utf-8"));
//设置服务器上的所有web项目都可以共享
cookie.setPath("/");
//添加cookie
resp.addCookie(cookie);
}
}
Session详解
快速起步
一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就一直存在,登陆之后,整个网站都可以访问
Session由服务器创建
1、HttpSession session = request.getSession()
:获取HttpSession对象
2、String session.getId()
:获取Session的ID
3、Object session.getAttribute(key)
:获取Session值
4、session.setAttribute(String key,Object value)
:向Session中存储
5、session.isNew()
:判断Session是否是新创建
6、session.removeAttribute(key)
:删除session中的存储内容
7、session.invalidata()
:注销Session
package com.howling;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session1")
public class Session1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("------------------------------");
//获取Session
HttpSession session = req.getSession();
//获取Session的ID
System.out.println(session.getId());
//给Session设置一个键值对
session.setAttribute("name","howling");
//判断Session是否为新创建的Session
System.out.println(session.isNew());
}
}
package com.howling;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session2")
public class Session2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("------------------------------");
HttpSession session = req.getSession();
//判断Session是否为新创建的Session
System.out.println(session.isNew());
//获取Session
System.out.println(session.getAttribute("name").toString());
//删除Session
session.removeAttribute("name");
}
}
package com.howling;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session3")
public class Session3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("------------------------------");
HttpSession session = req.getSession();
System.out.println(session.isNew());
//获取session
System.out.println(session.getAttribute("name"));
//销毁session
session.invalidate();
}
}
依次执行session1,session2,session3的Servlet 虽然这里存储的key-value中的value是String,但是其实可以存储Object
实现原理
Session的实现是基于Cookie的
1、客户端—》服务器
2、服务器响应,生成一个cookie对象(JSESSIONID=value),在set-cookie里面返回,浏览器获取这Cookie
3、客户端再次向服务器访问会带着这个cookie,以此来确认获取的Session是一个
注意,虽然Session是基于Cookie,但是Session不是Cookie,Session是根据Cookie来获取的
Session的更多说明
客户端关闭后,服务器不关闭,两次获取的Session是否为一个
默认情况下不是的,因为Session基于Cookie来获取,当浏览器关闭之后,Cookie消失了,即使再次创建也不是那个Cookie,对应的Session也不是那个了
但是我们可以创建名为JSESSION的Cookie,然后指定过期时间令其持久化即可
客户端不关闭,服务器关闭,两次获取的Session是否是一个
不是
但是如果要确保数据不丢失,tomcat自动完成Session的钝化和活化
Session的钝化:在服务器正常关闭之前,Session对象序列化到硬盘上成为一个文件
Session的活化:在服务器启动之后,Session文件转换为内存中的Session对象
注意:IDEA在服务器启动之后会把原本的目录删掉重新建立一个,所以活化没了,也就是说用IDEA时,数据也没了
Session什么时候被销毁
1、服务器关闭
2、session.invalidate()自杀
3、Session默认过期时间为30分钟,可以到tomcat->conf->web.xml->session-config
中修改
<session-config>
<session-timeout>30</session-timeout>
</session-config>