会话跟踪技术(状态管理)

Http协议是无状态的,没有记忆能力.在浏览器与服务器交互时,因为无状态的特性,会导致无法连贯的交互.

HTTP协议实现状态管理,有两种方式:

1.Cookie技术: 将交互时产生的状态 存储在客户端中.
2.Session技术: 将交互时产生的状态 存储在服务器中.

Cookie技术

1.当服务器向客户端响应时,可以向响应头中加入Cookie,每一个Cookie表示一个键值对

2.当浏览器接收到响应头中的Cookie后,会将其存储在本地的一个文本文件中,

3.当浏览器再次访问相同的服务器时,会去文本文件中寻找这个服务器之前存储的Cookie

4.将寻找到的Cookie携带到请求头中,发送给服务器.

  • 如何创建一个Cookie

    Cookie在Java程序中的体现是一个表示键值对的Java类.类名为Cookie

    格式:Cookie cookie = new Cookie(String name,String value);

  • 如何将创建的Cookie添加到响应的头部

    通过响应对象,将Cookie添加到响应的头部

    格式:response.addCookie(Cookie cookie);

    一次响应,可以添加0-n个Cookie,浏览器接收后,会存储到文本文件中,如果相同域的相同路径存储相同键的Cookie,会导致旧值被覆盖.

  • 如何调整Cookie的存活时长

    cookie.setMaxAge(int 秒);

    传入的值 说明
    负数 默认值为-1,负数表示浏览会话结束时删除.(指的是浏览器关闭)
    正数 存活的秒数
    0 存活的秒数,通常用户覆盖一个Cookie,来完成删除操作.
  • Cookie存储时的路径问题

    因为Cookie发送时,需要匹配域和路径.我们在编写项目时,经常因为路径不同,导致cookie无法读取.

    Java为我们提供了设置Cookie路径的方法,我们可以在任意的servlet中,将Cookie路径设置为一致,来存储和读取.

    格式:

    在cookie添加到响应头部之前设置:cookie.setPath(“/”);

    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
    package demo1;

    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;

    /**
    * Servlet implementation class LoginServlet
    */
    @WebServlet("/login.do")
    public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1. 设置请求体的编码
    request.setCharacterEncoding("utf-8");
    //2. 设置响应体的内容类型 以及 编码格式
    response.setContentType("text/html;charset=utf-8");
    //3. 获取参数
    String uname = request.getParameter("uname");
    String upass = request.getParameter("upass");

    if(uname!=null && "123".equals(upass)) {
    //登录成功
    //向浏览器中, 存储Cookie , 将用户的用户名, 存储在Cookie中
    //1. 创建Cookie
    Cookie cookie = new Cookie("uname", uname);
    // 设置存活时长为10年
    cookie.setMaxAge(10*365*24*60*60);
    // 设置cookie存储路径为/
    cookie.setPath("/");
    //2. 将Cookie 添加到响应头部
    response.addCookie(cookie);
    //响应内容
    response.getWriter().append("<script>alert('恭喜你, 登录成功');window.location.href='home.do'</script>");
    }else {
    //登录失败
    response.getWriter().append("<script>alert('很遗憾, 登录失败');window.history.back()</script>");
    }
    }
    }
  • 如何从请求头部得到我们之前存储的多个Cookie

    可以从请求对象中,得到之前存储的Cookie信息,得到的是一个Cookie数组,如果从未存储过Cookie,则得到的数据是null

    格式:
    Cookie[] cookies = request.getCookies();

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
48
49
50
51
52
53
54
55
56
57
58
59
package demo1;

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;

/**
* Servlet implementation class HomeServlet
*/
@WebServlet("/home.do")
public class HomeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#HttpServlet()
*/
public HomeServlet() {
super();
// TODO Auto-generated constructor stub
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 设置响应的编码格式, 以及内容类型
response.setContentType("text/html;charset=utf-8");
//2. 从请求对象中, 得到所有的Cookie
Cookie[] cookies = request.getCookies();
//3. 循环遍历Cookie 取出用户名
String uname = null;
if(cookies!=null) {
for (Cookie cookie : cookies) {
if(cookie.getName().equals("uname")) {
uname = cookie.getValue();
}
}
}

if(uname == null) {
//cookie中没有找到帐号 (未登录)
response.getWriter().append("<script>alert('网站暂只对内部人员开放,请先登录');window.location.href='index.html'</script>");
}else {
response.getWriter().append("欢迎你: svip用户 "+uname+"<br> 此处省略主页n多 欧美日韩高清无码资源....");
}
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
  • Cookie技术的优缺点

    缺点:

    1.Cookie存储的数据类型有限制,只能存储字符串(早期无法存储中文)

    2.数据存储的大小有限制,不能超过4kb(4096个字节)

    3.数据存储在用户的计算机的文本文件中,不安全,有可能被恶意程序读取.

    4.受限于用户的浏览器设置,当浏览器禁用Cookie时,cookie就无法使用了.

    优点:

    数据存储在客户端中,分散了服务器的压力.

Session技术

1.浏览器访问服务器时,服务器可以主动创建Session对象,一个session表示一个键值对的容器,类似Map集合

2.每一个Session创建时,会产生一个id,这个id会存储到一个Cookie中,并发送给浏览器

3.等浏览器下一次访问时,会携带Cookie,cookie中包含session的id

4.我们就可以根据得到的sessionid,从服务器中寻找到属于这个浏览器的session对象.

  • 如何获取session对象

    格式1.

    调用请求的获取session的方法(无参),方法的内部调用了一参方法,传入了true
    HttpSession session = request.getSession();

    格式2.

    调用请求的获取session的方法(一参)
    HttpSession session = request.getSession(boolean isNew);

    参数的含义

    true: 根据浏览器发来的sessionid寻找session对象并返回,如果不存在,则创建新的并返回
    false: 根据浏览器发来的sessionid寻找session对象并返回,如果不存在,则返回null

  • session的常用方法

1
2
3
4
5
6
7
8
9
10
11
1.存储数据
session.setAttribute(String name,Object value);

2.取出数据
Object value = session.getAttribute(String name);

3.删除数据
session.removeAttribute(String name);

4.销毁这个Session
session.invalidate();
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
package cn.xdl.demo1;

import java.io.IOException;
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 javax.servlet.http.HttpSession;

/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/login.do")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 设置请求体的编码
request.setCharacterEncoding("utf-8");
//2. 设置响应体的内容类型 以及 编码格式
response.setContentType("text/html;charset=utf-8");
//3. 获取参数
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");

if(uname!=null && "123".equals(upass)) {
//登录成功
//将用户名 存储到session中
//1. 得到session对象
HttpSession session = request.getSession();
session.setAttribute("uname", uname);

//响应内容
response.getWriter().append("<script>alert('恭喜你, 登录成功');window.location.href='home.do'</script>");
}else {
//登录失败
response.getWriter().append("<script>alert('很遗憾, 登录失败');window.history.back()</script>");
}
}
}
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
48
49
50
51
52
53
package cn.xdl.demo1;

import java.io.IOException;
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 javax.servlet.http.HttpSession;

/**
* Servlet implementation class HomeServlet
*/
@WebServlet("/home.do")
public class HomeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#HttpServlet()
*/
public HomeServlet() {
super();
// TODO Auto-generated constructor stub
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 设置响应的编码格式, 以及内容类型
response.setContentType("text/html;charset=utf-8");
//2. 从session中取出uname
String uname = null;
HttpSession session = request.getSession();
uname = (String) session.getAttribute("uname");

if(uname == null) {
//session中没有找到帐号 (未登录)
response.getWriter().append("<script>alert('网站暂只对内部人员开放,请先登录');window.location.href='login.html'</script>");
}else {
response.getWriter().append("欢迎你: svip用户 "+uname+"<br> 此处省略主页n多 欧美日韩高清无码资源....");
}
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
  • session的存活时长

    session的默认存活时长为30分钟,当用户的上一次访问距离现在已经超过30分钟时,session会自动销毁.

    设置session的存储时长:

    方式1. 修改单个session的时长:
    session.setMaxInactiveInterval(int 秒);

    方式2.修改tomcat下, 所有session的默认时长
    独立环境: 找到conf/web.xml文件
    开发环境: 找到servers/web.xml

    修改其中的session-config节点
    
    
    1
    2
    3
    <session-config>
    <session-timeout>数值分钟</session-timeout>
    </session-config>
  • session的优缺点

    优点:

    1.数据存储在服务器中,安全

    2.session中可以存储任意类型数据

    3.存储的数据大小,理论上是无限制的

    缺点:

    数据存储在服务器中,大量的用户存储session时,会对服务器造成极大的压力,极易导致服务器资源耗尽.

Cookie技术和Session技术不是互斥的.

Cookie和session我们是结合使用的.

对于安全无要求的字符串数据, 存储在cookie中
对于安全敏感的数据, 存储在session中
对于安全敏感 , 且较大数据, 存储在数据库中...