0%

Session&Cookie

Session,服务端会话控制。Cookie,客户端暂时或永久保存信息。

Session&Cookie

Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。摘自百度百科

Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。摘自百度百科

后边所有的代码演示部分只给出核心代码,具体项目配置流程访问这里:传送门。若遇到乱码问题,可以试试这样设置:传送门

会话

会话:用户打开了一个浏览器,点击了很多超链接,访问了多个web资源,关闭浏览器,这个过程可以称之为会话。

有状态会话:一个同学来过教室,下次再来教室,我们知道这个同学曾经来过,这个就与有状态会话相似;

保存会话的两种技术

cookie

  • 客户端技术(响应,请求)

session

  • 服务器端技术,利用这个技术,可以保存用户的会话信息,我们可以把信息或数据放在session中!

常见:网站登陆之后,你下次不用再登陆了,第二次访问直接就是登陆状态了。

Cookie

一些细节问题

  • 一个cookie只能保存一个信息
  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
  • cookie大小有限制4kb
  • 300个cookie浏览器上限

删除cookie

  • 不设置有效期,关闭浏览器,自动失效
  • 设置有效期时间为0

获取&发送cookie

  1. 从请求中拿到cookie信息(浏览器会将cookie发送过来)。req.getCookies()
  2. 服务器响应给客户端cookie。resp.addCookie(cookie对象)
1
2
3
4
5
6
Cookie[] cookies = req.getCookies();//获得Cookie(可能存在多个,返回数组)
cookie.getName()//获得cookie中的key
cookie.getValue()//获得cookie中的Value
Cookie mycookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");//新建一个cookie
mycookie.setMaxAge(24*60*60);//设置cookie的有效期(一天
resp.addCookie(mycookie);//响应给客户端一个cookie

代码演示

创建类CookieDemo01。该类,在web.xml文件中注册时设置的请求路径为/c1。当浏览器访问该路径时,该类给浏览器发送一个名为lastLoginTime的cookie,用于记录本次访问的时间。下次访问时,相对于服务器来说该cookie值就变成了上一次访问时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//保存用户上一次访问的时间
public class CookieDemo01 extends HttpServlet {

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

//服务器,告诉你,你来的时间,把这个时间封装成为一个信件,你下次带来,我就知道你来了

//解决中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");

PrintWriter writerout = resp.getWriter();

//Cookie,服务器端从客户端获取
Cookie[] cookies = req.getCookies();//这里返回数组,说明Cookie可能存在多个

//判断Cookie是否存在
if (cookies != null){
//如果存在怎么办
writerout.write("你上次访问的时间是:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//获取cookie的名字
if (Objects.equals(cookie.getName(),"lastLoginTime")){//自定义的一个cookie
//获取cookie中的值
long time = Long.valueOf(cookie.getValue());
Date date = new Date(time);
writerout.write(date.toLocaleString());
}
}
writerout.print("<br>当前cookie数:"+cookies.length);
}else {
//没有Cookie信息(这种情况是不会发生的,因为程序会自动发一些cookie信息该浏览器
writerout.write("这是您第一次访问本站");
}
//服务器给客户端响应一个cookie
Cookie mycookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");
//cookie有效期1天
mycookie.setMaxAge(24*60*60);
resp.addCookie(mycookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);//post请求,也放到doGet方法中处理
}
}

解决中文乱码:

1
2
3
//解决中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");

运行效果:

截屏2020-10-24 下午4.56.31

删除cookie

删除cookie。有两种方法,一是不设置cookie的有效期,二是再次向浏览器发送cookie信息此时将有效期设置为0(注意cookie名一定不要写错了)。

演示删除cookie。类CookieDemo02,新建一个cookie名字与CookieDemo01中的一样(相对于浏览器来说就是同一个cookie),将cookie的有效期设置为0。该类,在web.xml文件中注册时设置的请求路径为/c2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class CookieDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服务器给客户端响应一个cookie(名字与要删除的名字一致)
Cookie mycookie = new Cookie("lastLoginTime","");
//cookie有效期设置为0,立马过期
mycookie.setMaxAge(0);
resp.addCookie(mycookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);//post请求,也放到doGet方法中处理
}
}

运行结果:

乱码问题

cookie中使用中文可能会有乱码问题,我们可以使用URLEncoder类对字符串进行编码,使用时再使用URLDecoder类对字符串进行解码。

1
2
URLEncoder.encode("北京时间:"+System.currentTimeMillis(),"utf-8")//编码
URLDecoder.decode(cookie.getValue(),"utf-8")//解码

若乱码问题还是没有解决,可以进行以下配置(HttpServletRequest对象和HttpServletResponse对象)

1
2
3
//解决中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");

Session(重点)

什么是session:

  • 服务器会给每一个用户(浏览器)创建一个session对象
  • 一个session独占一个浏览器,只要浏览器没有关闭,这个session就存在
  • 用户登陆之后,整个网站它都可以访问 –> 保存用户的信息,保存购物车的信息。

session和cookie的区别

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  • Session是把用户的数据写到用户独占的Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
  • Session对象由服务自动创建

使用场景

  • 保存一个登陆用户的信息
  • 购物车信息
  • 在整个网站中经常会使用的数据,我们将它保存在Session中

代码演示

若遇到乱码问题,可以试试这样设置:传送门

注意,session保存在服务器端,由服务器自动创建。服务器通过cookie将sessionID发送给浏览器,通过判断sessionID判断是不是同一浏览器(客户端)。

共享数据

通过session即可实现数据共享(不同servlet类之间),以前学过使用ServletContext对象实现数据共享,推荐使用Session。(JSP页面中也有session对象可以实现数据共享,跟这里的session可以看作是同一个)下边代码演示如何添加数据和获取数据。

session:

servletContext:

添加数据

类SessionDemo01,往session中添加数据(下边例子中,添加了一个普通字符串和一个Person对象),并且判断session是不是新创建的。(新创建了session,说明之前保存在其中的数据已经被清除了)。使用方法setAttribute(key,value)。该类,在web.xml文件中注册时设置的请求路径为/s1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//解决中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");

//得到session
HttpSession session = req.getSession();
//往session中存东西
session.setAttribute("name","码代码的冰果果");
session.setAttribute("user",new Person("小黑",18,"男"));
//获取session的ID
String id = session.getId();
resp.getWriter().print("测试获取sessionID:"+id);
//判断session是不是新创建的
if (session.isNew()){
resp.getWriter().print("<br><br>新创建了session,ID:"+id);
}else {
resp.getWriter().print("<br><br>session已经在服务器中存在了,ID:"+id);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);//post请求,也放到doGet方法中处理
}
}

获取数据

类SessionDemo02,获取session中的保存的数据(下边例子中数据有:普通字符串、一个Person对象)。getAttribute(key名)方法,若没有该key名则会返回null。该类,在web.xml文件中注册时设置的请求路径为/s2。(下边通过cookie获取sessionID所使用cookie的name-JSESSIONID是在浏览器中查看到的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class SessionDemo02 extends HttpServlet {

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

//解决中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");

//得到session
HttpSession session = req.getSession();

Cookie[] cookies = req.getCookies();//服务器通过cookie将sessionID发送给浏览器
for (int i = 0; i < cookies.length; i++) {
if (Objects.equals(cookies[i].getName(),"JSESSIONID")){
resp.getWriter().print("从cookie中获取的SessionID为:"+cookies[i].getValue());
}
}

resp.getWriter().print("<br>从session中获取ID:"+session.getId());
resp.getWriter().print("<br><br>获取到的Session数据如下:");
resp.getWriter().print("<br> name = "+session.getAttribute("name"));
resp.getWriter().print("<br>用户信息 = "+session.getAttribute("user"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);//post请求,也放到doGet方法中处理
}
}

注销session

手动注销

类SessionDemo03,手动注销session,使用方法invalidate()。想清除某个数据不想注销session,可以使用方法removeAttribute(key名)。该类,在web.xml文件中注册时设置的请求路径为/s3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class SessionDemo03 extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");

//注销session
final HttpSession session = req.getSession();
session.removeAttribute("name");//删除某个数据
session.invalidate();//注销后,会立马生成一个新的(并发送给浏览器)
if (req.getSession().isNew()){
resp.getWriter().print("session已经注销,数据已经全部销毁。新session创建成功。。。");
}

}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);//post请求,也放到doGet方法中处理
}
}

自动注销

会话自动过期:web.xml配置

1
2
3
4
5
<!--  设置session默认的失效时间-->
<session-config>
<!--1分钟后session自动失效,以分钟为单位-->
<session-timeout>1</session-timeout>
</session-config>

运行结果

服务器会给每一个用户(浏览器)创建一个session对象。

添加数据与获取数据:

注销session:

若图片不能正常显示,请在浏览器中打开

欢迎关注我的其它发布渠道