cookie&session

Cookie和Session

第一章 会话的基本概念

1.1 什么是会话

在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。

Web应用中的会话过程类似于生活中的打电话过程,它指的是一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应过程,例如,一个用户在某网站上的整个购物过程就是一个会话。

在打电话过程中,通话双方会有通话内容,同样,在客户端与服务器端交互的过程中,也会产生一些数据。为了保存会话过程中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象,分别是Cookie和Session。

第二章 cookie

2.1 cookie的概念

2.1.1 什么是cookie

浏览器端的会话技术,它通过在浏览器中记录一些服务器传递过来的数据,解决会话从什么时候开始,到什么时候结束。

2.2 cookie的应用场景

  1. 记住用户名
  2. 自动登录(记住用户名和密码)

2.3 cookie的基本使用

2.3.1 cookie常用的方法介绍

API介绍

Cookie:

方法返回值描述
Cookie(String name, String value)Cookie构造方法,创建cookie对象
getName()String获取cookie的名称
getValue()String获取cookie的值
setPath(String uri)void设置cookie的路径——浏览器根据这个路径判断哪些cookie要发送给服务器

HttpServletResponse:

方法返回值描述
addCookie(Cookie cookie)void将cookie发送给浏览器

HttpServletRequest:

方法返回值描述
getCookies()Cookie[]获取浏览器发送的cookie
演示代码

CookieServlet1:

@WebServlet(name = "CookieServlet1",urlPatterns = "/cookie1")
public class CookieServlet1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建cookie
        Cookie cookie = new Cookie("username","tom");
        //设置cookie的路径——浏览器根据这个路径判断那些cookie要发送给服务器
        cookie.setPath("/day04");
        //将cookie发送给浏览器
        response.addCookie(cookie);
    }
}

CookieServlet2:

@WebServlet(name = "CookieServlet2",urlPatterns = "/cookie2")
public class CookieServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取浏览器发送的cookie
        Cookie[] cookies = request.getCookies();
        if(cookies != null){
            for (Cookie coo : cookies) {
                if("username".equals(coo.getName())){
                    //打印cookie的名称和值
                    System.out.println(coo.getName()+":"+coo.getValue());
                }
            }
        }
    }
}

2.3.2 删除cookie

API介绍
方法返回值描述
setMaxAge(int expiry)void设置cookie的最大生存时间(单位:秒)
setPath(String uri)void设置cookie的路径——浏览器根据这个路径判断那些cookie要发送给服务器
注意事项
  1. cookie的生存时间单位为:秒
  2. 要删除已经存在的cookie,后一个用来覆盖cookie必须名称与路径与原来的cookie一致
演示代码
@WebServlet(name = "MaxAgeServlet",urlPatterns = "/maxage")
public class MaxAgeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建cookie
       /* Cookie cookie = new Cookie("name","tom");
        //设置cookie的生存时间
        cookie.setMaxAge(60*60*24*7);
        //设置cookie的路径
        cookie.setPath("/day04");
        //发送cookie给浏览器
        response.addCookie(cookie);*/
        
        //=====如果需要立刻删除cookie======
        //创建空数据的cookie,名称保持一致
        Cookie cookie = new Cookie("name","");
        //设置cookie的生存时间为0立刻死亡
        cookie.setMaxAge(0);
        //设置cookie的路径,与原来的cookie路径保持一致
        cookie.setPath("/day04");
        //发送cookie给浏览器
        response.addCookie(cookie);
    }
}

2.3.3 案例:记录用户上一次访问时间

案例需求

展示用户上一次访问服务器的时间

实现代码
@WebServlet(name = "TimeServlet",urlPatterns = "/time")
public class TimeServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//第一次访问操作
		// 1 获取用户当前访问的时间
		 Date date = new Date();
		 //格式化时间数据(注意:在cookie值中不能使用分号(;)、逗号(,)、等号(=)以及空格,否则会出现异常)
		 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd/hh:mm:ss");
		 String format1 = format.format(date);
		 System.out.println(format1);
		// 2 将数据存入cookie
		 Cookie cookie = new Cookie("time", format1);
		 cookie.setMaxAge(60*60*24);
		// 3 将数据发送给浏览器
		 response.addCookie(cookie);
		
		//第二次访问操作
		 //获取cookie数组
		 Cookie[] cookies = request.getCookies();
		if(cookies != null) {
			for (Cookie cookie2 : cookies) {
				//选择获取名称为time的cookie
				if("time".equals(cookie2.getName())) {
					//将数据发送页面
					response.getWriter().write(cookie2.getValue());
				}
			}
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

第三章 session

3.1 session的基本概念

当人们去医院就诊时,就诊病人需要办理医院的就诊卡,该卡上只有卡号,而没有其它信息。但病人每次去该医院就诊时,只要出示就诊卡,医务人员便可根据卡号查询到病人的就诊信息。

Session技术就好比医院发放给病人的就医卡和医院为每个病人保留病例档案的过程。当浏览器访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性,其中,Session对象就相当于病历档案,ID就相当于就诊卡号。当客户端后续访问服务器时,只要将标识号传递给服务器,服务器就能判断出该请求是哪个客户端发送的,从而选择与之对应的Session对象为其服务。

需要注意的是,由于客户端需要接收、记录和回送Session对象的ID,因此,通常情况下,Session是借助Cookie技术来传递ID属性的。

3.1.1 什么要存在Session

  • 使用servlet生成验证码时,我们需要在服务器记录一份生成的随机字符,当用户提交填写的数据时,将用户输入的数据和服务器缓存的数据进行比对。

  • 将随机字符串保存在ServletContext中或者request中是否可以?

    不可以,通过下面的两种情况可知,将数据保存到ServletContext和request中是存在问题的,那么就需要使用会话技术保存用户的私有信息.

**情况一:**将数据存放到ServletContext,多个用户共享一个验证码。

**情况二:**将数据存放到request作用域,多次请求不能共享数据。

3.2 session的与cookie的区别

cookiesession
会话数据保存的位置浏览器服务器
数据的安全性不安全安全
存储数是否有限制

3.3 session的应用场景

  1. 保存购物车数据
  2. 保存用户浏览器记录数据
  3. 保存用户登录信息数据
  4. 保存验证码

3.4 session作为域对象使用

3.4.1 session存储数据与获取数据

API介绍

HttpServletRequest:

方法返回值描述
getSession()HttpSession获取session对象

HttpSession:

方法返回值描述
setAttribute(String name, Object value)void在session中保存数据
etAttribute(String name)Object从session中获取数据
removeAttribute(String name)void从session中移除数据
注意事项

getAttribute方法返回值是Object,因此需要将返回值强制转换才能方便使用。

演示代码

SessionServlet1:

@WebServlet(name = "SessionServlet1",urlPatterns = "/session1")
public class SessionServlet1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取session对象
        HttpSession session = request.getSession();
        //添加数据
        session.setAttribute("addr","广州");
        
    }
}

SessionServlet2:

@WebServlet(name = "SessionServlet2",urlPatterns = "/session2")
public class SessionServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取session对象
        HttpSession session = request.getSession();
      	//获取数据
        String addr = (String) session.getAttribute("addr");
        System.out.println(addr);
        //移除数据
        session.removeAttribute("addr");
        //再次获取,查看效果
        String addr1 = (String) session.getAttribute("addr");
        System.out.println(addr1);
    }
}

3.4.2 session的原理分析

3.4.3 session实现关闭浏览器继续可以访问数据

通过上面的原理图,我们发现记录sessionid的cookie在关闭浏览器之后就到期了,那么如果我们希望——关闭浏览器继续可以访问session数据,该怎么做呢?

案例需求

关闭浏览器继续可以访问session数据

实现:访问一次服务器,然后关闭浏览器,再访问一次:两次session对象一致

案例分析
  1. 创建一个servlet

  2. 通过request对象获取session的id

  3. 自定义一个cookie对象,保存session的id,注意cookie名称为"JSESSIONID",设置一个比较长的生存时间

  4. 发送给浏览器

代码实现
@WebServlet(name = "SessionServlet3",urlPatterns = "/session3")
public class SessionServlet3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//获取session对象
		HttpSession session = request.getSession();
		System.out.println(session);
		//自己创建一个cookie,要求被浏览器持久化保存起来(setMaxAge(10000))放便后期使用
		Cookie cookie = new Cookie("JSESSIONID", session.getId());
		//活的久一点
		cookie.setMaxAge(10000);
		response.addCookie(cookie);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

3.5 案例:使用session存储验证码完成登录功能

3.5.1 案例需求

  1. 在登录页面用户登录的时候要查看到验证码,如图所示:

    [外链图片转存失败(img-e1YL1bHh-1567135892676)(img\16.png)]

  2. 在生成页面验证码图片的同时,使用session存储验证码

  3. 在处理用户登录请求的时候,首先校验验证码

  4. 校验通过才能执行登录操作

3.5.2 案例分析

3.5.3 代码实现

  1. 页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
            <title>login</title>
            <script type="text/javascript">

                function changeCode(){
                    document.getElementById("img").src = "/day04/checkcode?r="+new Date().getTime();
                }
            </script>
        </head>
        <body>
            <form action="/day04/login" method="post">
                <table>
                    <tr><td>用户名:</td><td><input type="text" name="username"></td></tr>
                    <tr><td>密码:</td><td><input type="password" name="password"></td></tr>
                    <tr><td>验证码:</td><td><input type="text" name="code"></td></tr>
                    <!-- 通过向服务器发送请求,从服务器获取验证码数据 -->
                    <tr><td></td><td><img id="img" src="/day04/checkcode" οnclick="changeCode();"/><a href="javascript:;" οnclick="changeCode();">换一换</a><span><% if(request.getAttribute("msg")!=null){out.write(request.getAttribute("msg").toString());}%></span></td></tr>
                    <tr><td></td><td><input type="submit" value="登陆"></td></tr>
                </table>
            </form>
        </body>
    </html>
  1. 配置验证码servlet
@WebServlet(name = "CheckcodeServlet",urlPatterns = "/checkcode")
public class CheckcodeServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//  创建画布
		int width = 120;
		int height = 40;
		BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		//  获得画笔
		Graphics g = bufferedImage.getGraphics();
		//  填充背景颜色
		g.setColor(Color.white);
		g.fillRect(0, 0, width, height);
		//  绘制边框
		g.setColor(Color.red);
		g.drawRect(0, 0, width - 1, height - 1);
		//  生成随机字符
		//  准备数据
		String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
		//  准备随机对象
		Random r = new Random();
		//  声明一个变量 保存验证码
		String code = "";
		//  书写4个随机字符
		for (int i = 0; i < 4; i++) {
			//  设置字体
			g.setFont(new Font("宋体", Font.BOLD, 28));
			//  设置随机颜色
			g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

			String str = data.charAt(r.nextInt(data.length())) + "";
			g.drawString(str, 10 + i * 28, 30);

			//  将新的字符 保存到验证码中
			code = code + str;
		}
		//  绘制干扰线
		for (int i = 0; i < 6; i++) {
			//  设置随机颜色
			g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

			g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
		}

		//  将验证码 打印到控制台
		System.out.println(code);

		//  将验证码放到session中
		request.getSession().setAttribute("code_session", code);

		//  将画布显示在浏览器中
		ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}
  1. 登录servlet
@WebServlet(name = "LoginServlet",urlPatterns = "/login")
public class LoginServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//用户请求中的验证码获取
		String code = request.getParameter("code");
		//获取session中保存的验证码
		String code_session = (String)request.getSession().getAttribute("code_session");

		//与session中保存的验证码进行校验
		if(!code_session.equalsIgnoreCase(code)){
			//验证码错误,告诉用户,页面提示
			request.setAttribute("msg","验证码错误");
			request.getRequestDispatcher("/login.jsp").forward(request,response);
			return;
		}
		//验证码正确,登录逻辑执行
		//获取用户名和密码
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		//调用Service方法,登录用户
		UserDao userDao = new UserDao();

		User loginUser = userDao.login(username,password);
		if(loginUser == null){
			request.setAttribute("msg","用户名或则密码错误");
			request.getRequestDispatcher("/login.jsp").forward(request,response);
			return;
		}else{
			//登陆成功,跳转主页
			response.sendRedirect(request.getContextPath());
			return;
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}
  1. service:
public class UserService {
    private UserDao userDao = new UserDao();

    public User login(String username, String password) {

        return userDao.login(username, password);
    }
}
  1. dao:
public class UserDao {
    private QueryRunner queryRunner = queryRunner = new QueryRunner(JdbcUtils.getDataSource());

    /**
     * 查询用户名和密码是否匹配的方法
     */
    public User login(String username, String password) {
        try {
            String sql = "select * from user where username = ? and password = ?";

            //查询并封装
            User user = queryRunner.query(sql, new BeanHandler<User>(User.class), username, password);
            return user;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
}

相关jar包、jdbc工具类、c3p0配置文件、User类、数据库user表,请自行编写

3.6 案例:模拟简易session购物车

3.6.1 案例需求

完成session购物车案例

  • 保证中文的正常显示

  • 购物车数据通过Session保存,窗口关闭以后数据消失。

3.6.2 案例分析

  1. 在第一个购物界面选择商品添加到购物车,手动回退到购物界面

  2. 在购物车选好物品后,可以选择“买点别的”,跳转到第二个购物页面选购

  3. 在第二个购物界面选择商品添加到购物车,手动回退到购物界面

  4. 查看购物车页面

3.6.3 代码实现

  • shopping cart1.jsp:购物车一页面球类
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>购物球类</title>
</head>
<body>

<h4>各种球大甩卖,一律八块</h4>
<form action="/day04/data" method="post" name="Ball" id="ball">
    <input type="checkbox" name="data" value="篮球">篮球<br>
    <input type="checkbox" name="data" value="足球">足球<br>
    <input type="checkbox" name="data" value="排球">排球<br><br>
    <input type="submit" value="提交">
    <input type="reset" value="全部重写"><br><br>
    <a href="ShoppingCart2.jsp">买点别的</a>&nbsp;&nbsp;<a href="display.jsp">查看购物车</a>
</form>

</body>
</html>

  • shopping cart2.jsp:购物车二页面肉类
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>肉类购物车</title>
</head>
<body>
<h4>各种肉大甩卖,一律十块:</h4>
<form name="Meet" id="Meet" action="/day04/data" method="post">
    <input type="checkbox" name="data" value="猪肉">猪肉<br>
    <input type="checkbox" name="data" value="牛肉">牛肉<br>
    <input type="checkbox" name="data" value="羊肉">羊肉<br><br>
    <input type="submit" value="提交">
    <input type="reset" value="全部重写"><br><br>
    <a href="ShoppingCart1.jsp">买点别的</a>&nbsp;&nbsp;<a href="display.jsp">查看购物车</a>
</form>
</body>
</html>

  • DataServlet:数据处理
@WebServlet(name = "DataServlet",urlPatterns = "/data")
public class DataServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        String goods[] = request.getParameterValues("data");

        HttpSession session = request.getSession();
        //获取表单传过来的数据存入字符串数组中
        Set<String> now= (Set <String>)session.getAttribute("list");

        //当前session内的东西
        //新建集合将数据存入
        Set <String> set = new HashSet<String>();
        if(goods!=null){
            //将货物添加到集合中
            Collections.addAll(set,goods);
        }
        if(now!=null){
            //将session内当前的东西添加到集合中
            set.addAll(now);
        }
        //将集合存入session中,命名为list
        session.setAttribute("list",set);

        //浏览器输出添加成功
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("<h1>添加到购物车成功</h1>");

    }
}

  • display.jsp:显示数据页面
<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" %>
<html>
<head>
    <title>显示购物车内容</title>
</head>
<body>
    <h3>你选择的结果是:</h3>
    <%
        Set <String> goods = (Set<String>)session.getAttribute("list");
        if (goods!= null){
            for (String good : goods){
                out.print(good + "<br/>");
            }
        }
    %>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值