[Java | Web] JavaWeb——Cookie 和 Session 简介

目录

一、Cookie 简介

1、什么是 cookie

2、Cookie 的创建

3、服务器如何获取 Cookie

4、Cookie 的修改

5、Cookie 的生命控制

6、Cookie 的 path 属性

7、练习之免用户名登录

二、Session 简介

1、什么是 Session 对话

2、Session 的创建和获取

3、Session 域中数据的存取

4、Session 生命周期控制

5、浏览器 Cookie 和服务器 Session 之间的关联


一、Cookie 简介

1、什么是 cookie

  • Cookie 是服务器端通知客户端保存键值对的一种技术。
  • Cookie 是 servlet (服务器)发送到 Web 浏览器(客户端)的少量信息,这些信息由浏览器保存,然后发送回服务器。
  • 客户端有了 Cookie 后,每次请求都会发送 Cookie 给服务器。
  • 每个 Cookie 的大小不能超过 4KB。

2、Cookie 的创建

(1)示例

(1-1)cookie.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="pragma" content="no-cache" />
	<meta http-equiv="cache-control" content="no-cache" />
	<meta http-equiv="Expires" content="0" />
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Cookie</title>
	<style type="text/css">

		ul li {
			list-style: none;
		}

	</style>
	<base href = "http://localhost:8080/cookie_war_exploded/"/>
</head>
<body>
	<iframe name="target" width="500" height="500" style="float: left;"></iframe>
	<div style="float: left;">
		<ul>
			<li><a href="./start_CookieServlet?action=createCookie" target="target">Cookie的创建</a></li>
			<li><a href="" target="target">Cookie的获取</a></li>
			<li><a href="" target="target">Cookie值的修改</a></li>
			<li>Cookie的存活周期</li>
			<li>
				<ul>
					<li><a href="" target="target">Cookie的默认存活时间(会话)</a></li>
					<li><a href="" target="target">Cookie立即删除</a></li>
					<li><a href="" target="target">Cookie存活3600秒(1小时)</a></li>
				</ul>
			</li>
			<li><a href="" target="target">Cookie的路径设置</a></li>
			<li><a href="" target="target">Cookie的用户免登录练习</a></li>
		</ul>
	</div>
</body>
</html>

(1-2)CookieServlet 类:

package com.web;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class CookieServlet extends BaseServlet {

    protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.创建 cookie 对象
        Cookie cookie1 = new Cookie("key_1", "value_1");
        Cookie cookie2 = new Cookie("key_2", "value_2");
        // 2.通知客户端保存 cookie(只要是服务器要发给客户端的,都是通过响应来进行操作的)
        resp.addCookie(cookie1);
        resp.addCookie(cookie2);
        // 3.在客户端上显示一句话
        resp.getWriter().write("cookie 创建成功");
    }

}

(1-3)BaseServlet 类(自定义的用来处理页面 action 属性的类)

package com.web;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import java.lang.reflect.Method;

public abstract class BaseServlet extends HttpServlet {
    /**
     * TODO 因为有些访问方式是 GET 请求,因此还需要 doGet 方法,然后再传到 doPost 方法即可
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        String action = req.getParameter("action");
        try { // 通过反射,用 action 的值对应相同的函数名
            /*
                this.getClass() == UserServlet.class
                this == new UserServlet()
             */
            Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
            // 调用目标方法(业务)
            method.invoke(this, req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

(2)查看 Cookie

3、服务器如何获取 Cookie

服务器获取客户端的 Cookie 只需要一行代码:

Cookie[] cookies = req.getCookies();

(1)示例:

(1-1)CookieServlet 类:

package com.web;

import com.utils.CookieUtils;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class CookieServlet extends BaseServlet {

    protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie[] cookies = req.getCookies();
        for (Cookie cookie : cookies) {
            resp.getWriter().write("Cookie[" + cookie.getName() + "]" + "=" + cookie.getValue() + "\n");
        }
        resp.getWriter().write(CookieUtils.findCookie("key_1", cookies).getValue());
    }
}

(1-2)CookieUtils 类(自定义的 Cookie 工具类):

package com.utils;

import javax.servlet.http.Cookie;

public class CookieUtils {
    /**
     * TODO 查找指定名称(键)的 Cookie 对象
     * @param name
     * @param cookies
     * @return
     */
    public static Cookie findCookie(String name, Cookie[] cookies) {
        if (name == null || cookies == null || cookies.length == 0) {
            return null;
        }

        for (Cookie cookie : cookies) {
            if (name.equals(cookie.getName())) {
                return cookie;
            }
        }

        return null;
    }
}

4、Cookie 的修改

(1)方案一

  • 使用 cookie.addCookie() 覆盖原有的 cookie 键值对。

(2)方案二

  • 先找到需要修改的 Cookie 对象
  • 调用 setValue() 方法赋予新的 Cookie 值
  • 调用 response.addCookie() 通知客户端保存修改

(2-1)示例:

记得先创建 Cookie 后再进行修改。

package com.web;

import com.utils.CookieUtils;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class CookieServlet extends BaseServlet {

    protected void updateCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = CookieUtils.findCookie("key_1", req.getCookies());
        if (cookie != null) {
            cookie.setValue("newValue_1");
            resp.addCookie(cookie);
        }
        resp.getWriter().write("key_1 的值已经修改");
    }
}

5、Cookie 的生命控制

Cookie 的生命控制指的是如何管理 Cookie 什么时候被销毁(删除),使用 setMaxAge() 来控制。

(1)setMaxAge()  

  • 如果传入的参数是负数,表示关闭浏览器后,Cookie 就会被删除。(默认,-1)
  • 如果传入的参数是正数,表示在指定秒数后过期。

  • 如果传入的参数是 0,表示马上删除 Cookie。

(2)示例:

package com.web;

import com.utils.CookieUtils;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class CookieServlet extends BaseServlet {

    protected void defaultLiveTime(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("defaultLiveTime", "default");
        cookie.setMaxAge(-1);
        resp.addCookie(cookie);
    }

    protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = CookieUtils.findCookie("key_2", req.getCookies());
        if (cookie != null) {
            cookie.setMaxAge(0);
            resp.addCookie(cookie);
            resp.getWriter().write("key_2 的 Cookie 已经删除");
        }
    }

    protected void liveTime(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("liveTime", "live3600");
        cookie.setMaxAge(3600); // 3600 秒后删除
        resp.addCookie(cookie);
        resp.getWriter().write("已经创建存活一小时的 Cookie");
    }
}

6、Cookie 的 path 属性

Cookie 的 path 属性,可以有效地过滤哪些 Cookie 可以发送给服务器,哪些不发。path 属性是通过请求的地址来进行有效的过滤。

(1)举个例子

假设有两个 Cookie:

  • CookieA:path = /工程名
  • CookieB:path = /工程名/file

(1-1)此时请求地址如下:

  • http://localhost:8080/工程路径/post.html
  • 那么,CookieA 可以发送到服务器,CookieB 不能发送到服务器。

(1-2)此时请求地址如下:

  • http://localhost:8080/工程路径/file/post.html
  • 那么,CookieA 和 CookieB 都可以发送到服务器。

(2)结论

显然只要 path 是请求地址的本目录以及父目录,就可以发送 Cookie 到服务器

也就是说,请求地址 /post.html,不能发送 path 为 /file 的 Cookie;请求地址 /file/post.html,可以发送 path 为 /file 的 Cookie。

用更容易理解的来说,就是 path 的层级越小(越接近 /工程路径),那么就越容易发送到服务器。同时也意味着,请求地址的层级越大,越容易接收到 Cookie

(3)示例

(3-1)Java 代码:

package com.web;

import com.utils.CookieUtils;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class CookieServlet extends BaseServlet {

    protected void cookiePath(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("path_1", "path_1");
        cookie.setPath(req.getContextPath() + "/file");
        resp.addCookie(cookie);
        resp.getWriter().write("创建了一个带有path的Cookie");
    }
}

(3-2)结果:

(3-2-1)请求地址没有深入到 /工程路径/file:

此时第一次访问服务器,服务器为浏览器设置了 cookie:

即便设置了 Cookie,但是第二次访问服务器,并不能发送 Cookie 到服务器: 

(3-2-2)请求地址深入到 /工程路径/file:

紧接着将 /file 加入请求地址,访问服务器(观察请求标头,此时包含有path):

访问后,会发现服务器已经接收到了请求标头中的 Cookie:

7、练习之免用户名登录

(1)示例:

(1-1)LoginServlet 类:

package com.web;

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 LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        if (username.equals("admin") && password.equals("password")) {
            // 登陆成功
            Cookie cookie = new Cookie("username", username);
            // 一定要设置存活时间,否则关闭浏览器,cookie就销毁了
            cookie.setMaxAge(7 * 24 * 60 * 60); // 一周内有效
            resp.addCookie(cookie);
            System.out.println("登陆成功");
        } else {
            System.out.println("登陆失败");
        }
    }
}

(1-2)login.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="http://localhost:8080/cookie_war_exploded/start_LoginServlet" method="get">
        用户名:<input type="text" name="username" value="${ cookie.username.value }"/> <br/>
        密码:<input type="password" name="password"> <br/>
        <input type="submit" value="登录"/>
    </form>
</body>
</html>

(1-3)第一次输入正确的用户名和密码后,关闭该页面,重新访问,就会发现用户名已经自动填写上了:

cookie 中也确实存在该键值对 

二、Session 简介

1、什么是 Session 对话

  • Session 是一个 Java 中的接口(HttpSession)。
  • Session 就是会话,用来维护一个客户端和服务器之间关联的一种技术。
  • 每个客户端都有一个自己的 Session 会话。
  • Session 会话中,我们经常用来保存用户登录后的信息,前面的 Cookie 是保存在客户端,而 Session 是保存在服务器端。

2、Session 的创建和获取

(1)创建和获取 Session,都是通过 request.getSession() 来实现的。

  • 第一次调用:创建 Session 对象;
  • 之后的调用:获取之前创建好的 Session 会话对象。

(2)可以用 isNew() 方法来判断一个 Session 是不是刚创建出来的。

  • true:表示刚创建
  • false:表示获取之前创建

(3)每个会话都有一个身份证号,也就是 ID 值,且这个 ID 唯一。

  • getId() 方法获取 Session 对象的 ID 值

(4)示例:

注意前面 Cookie 第 2 小节的 BaseServlet 还要用

(4-1)SesisonServlet 类:

package com.web;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class SessionServlet extends BaseServlet {

    protected void createOrGetSession(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 创建和获取 session 会话对象
        HttpSession httpSession = req.getSession();
        // 判断是否新创建的 session
        boolean isNew = httpSession.isNew();
        // 获取 id
        String id = httpSession.getId();

        resp.getWriter().write("得到的 session 的 id 为:" + id + "\n");
        resp.getWriter().write("得到的 session 是新创建的:" + isNew + "\n");
    }
}

(4-2)session.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="pragma" content="no-cache" />
	<meta http-equiv="cache-control" content="no-cache" />
	<meta http-equiv="Expires" content="0" />
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Session</title>
	<style type="text/css">

		ul li {
			list-style: none;
		}

	</style>
	<!-- 这里的工程名是 cookie,同前面第一节的工程,因为懒没有新建 session 工程 -->
	<base href = "http://localhost:8080/cookie_war_exploded/"/>

</head>
<body>
	<iframe name="target" width="500" height="500" style="float: left;"></iframe>
	<div style="float: left;">
		<ul>
			<li><a href="./start_SessionServlet?action=createOrGetSession" target="target">Session的创建和获取(id号、是否为新创建)</a></li>
			<li><a href="" target="target">Session域数据的存储</a></li>
			<li><a href="" target="target">Session域数据的获取</a></li>			
			<li>Session的存活</li>
			<li>
				<ul>
					<li><a href="" target="target">Session的默认超时及配置</a></li>
					<li><a href="" target="target">Session3秒超时销毁</a></li>
					<li><a href="" target="target">Session马上销毁</a></li>
				</ul>
			</li>
			<li><a href="" target="target">浏览器和Session绑定的原理</a></li>
		</ul>
	</div>
</body>
</html>

(4-3)第一次点击创建,为 true:

(4-4)第二次点击创建,为 false:

3、Session 域中数据的存取

从 request 域中可以获取到 session 对象,然后调用 setAttribute 或者 getAttribute 即可。

(1)示例:

(1-1)SessionServlet 类:

package com.web;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class SessionServlet extends BaseServlet {

    protected void setSessionAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getSession().setAttribute("key_1", "value_1");
        resp.getWriter().write("往 session 中保存了 key_1");
    }

    protected void getSessionAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object attribute = req.getSession().getAttribute("key_1");
        resp.getWriter().write("从 session 中获取 key_1 的值为:" + attribute);
    }

}

(1-2)结果:

4、Session 生命周期控制

Session 超时:客户端两次请求的最大时间间隔

(1)setMaxInactiveInterval(int Interval)

设置 Session 的超时时间(以 秒 为单位),超过指定的时长,Session 就会被销毁。

  • 值为正数:设置超时时长;
  • 值为负数:设置永不超时(极少使用)

不能设置为 0;

(2)getMaxInactiveInterval()

获取 Session 的超时时长。

(3)invalidate()

让当前 Session 对话马上超时。

(4)示例:

(4-1)获取默认存活时间

Session 默认超时时长为 30 分钟。因为在 Tomcat 服务器的配置文件 web.xml 中有以下配置,使得 web 工程下的所有 session 默认超时时长都为 30 分钟:

<session-config>
    <session-timeout>30</session-timeout>
</session-config>

如果要修改,可以在自己的 Web 工程中的 web.xml 中添加类似配置,不需要到 tomcat 的 xml 中修改。

(4-2)设置超时时长

使用 setMaxInactiveInterval() 可以单独为某个 Session 设置超时时长。

比如我们点击设置 3 秒超时,当我们点击创建一个 Session 后,再次点击,会发现 isNew 返回 false 对吧?

此时只需要等待 3 秒(显然等不够 3 秒就点,会重置超时时长),再次点击创建,就会发现 isNew 返回 true 了。

(4-3)设置 Session 直接超时无效

设置直接超时后,又点击创建,就会发现 isNew 也返回 true 了。

(4-4)SessionServlet 类:

package com.web;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class SessionServlet extends BaseServlet {
    protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取了 Session 的默认超时时长
        req.getSession().invalidate();
        resp.getWriter().write("设置 Session 直接超时\n");
    }

    protected void threeSecondLiveTime(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取了 Session 的默认超时时长
        req.getSession().setMaxInactiveInterval(3);
        resp.getWriter().write("设置 Session 的存活时长为:" + 3 + " 秒\n");
    }

    protected void defaultLiveTime(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取了 Session 的默认超时时长
        int maxInactive = req.getSession().getMaxInactiveInterval();
        resp.getWriter().write("Session 的默认超时时长为:" + maxInactive + " 秒\n");
    }

}

5、浏览器 Cookie 和服务器 Session 之间的关联

Session 技术的底层,其实是基于 Cookie 技术来实现的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值