会话技术Cookie&Session

会话技术Cookie&Session

1. 会话: 一次会话中包含多次请求和响应.
  	* 一次会话: 浏览器第一次给服务器资源发送请求, 会话建立, 知道有一方断开为止
2. 功能: 在一次会话的范围内的多次请求键, 共享数据
3. 方式:
		1. 客户端会话技术: Cookie
		2. 服务器端会话技术: Session

Cookie

1. 概念: 客户端会话技术, 将数据保存到客户端.
  
  
2. 快速入门:
		* 使用步骤:
				1. 创建Cookie对象, 绑定数据
						* new Cookie(String name, String value)
				2. 发送Cookie对象
						* response.addCookie(Cookie cookie)
				3. 获取Cookie, 拿到数据
						* Cookie[] request.getCookies()
		        4. 代码:
					* CookieDemo1
		                    // 1. 创建cookie
		                    Cookie cookie = new Cookie("username", "zhangsan");
		
		                    // 2. 发送cookie
		                    response.addCookie(cookie);
									
					* CookieDemo2
						 	// 3. 获取cookie
		                    Cookie[] cookies = request.getCookies();
		
		                    // 获取数据, 遍历Cookie
		                    if(cookies != null) {
		                        for (Cookie cookie : cookies) {
		                            String name = cookie.getName();
		                            String value = cookie.getValue();
		                            System.out.println("name: " + name + " value: " + value);
		                        }
		                    }
		
					* 运行结果:
						   name: Pycharm-abaea751 value: c588d849-c872-49ed-b318-b3fef725eeed
		                   name: Idea-6310fadd value: bf2d1837-2817-4f2e-8e3f-888e375ac004
		                   name: JSESSIONID value: 17EEEBEB0FF62472EDDEA353A769297D
		                   name: username value: zhangsan
     
     
3. Cookie访问原理:
		* 基于响应头set-cookie和请求头cookie实现	
              * 第一次请求CookieDemo1: 
                    * 访问服务器, 会话建立, 服务器创建cookie, 设置cookie, 返回cookie给浏览器客户端, 浏览器默认将cookie本地存储到浏览器.

              * 第二次请求CookieDemo2: 
                    * 浏览器默认携带cookie, 访问服务器, 所以服务器能拿到cookie.
                    			.....
                      
  
4. cookie的细节
	    1. 一次可不可以发送多个cookie?
              * 可以
              * 可以创建多个Cookie对象, 使用response使用多次addCookie方法发送cookie即可.
              * 代码:
              	// 1. 创建Cookie对象
                  Cookie c1 = new Cookie("gender", "male");
                  Cookie c2 = new Cookie("age", "18");

                  // 2. 发送cookie
                  response.addCookie(c1);
                  response.addCookie(c2);


        2. cookie在浏览器中保存多长时间?
        		1. 默认情况, 当浏览器关闭后, Cookie数据被销毁
          		2. 持久化存储:
					* setMaxAge(int seconds)
     					1. 正数:Cookie数据写到硬盘的文件中. 持久化存储. cookie存活时间.
     					2. 负数: 默认值
                      	3.: 删除Cookie信息
                      	4. 代码:
							  /*
                                  注意: 这里指的是同一个浏览器访问.
                               */

                              // 1. 创建Cookie对象
                              Cookie cookie = new Cookie("msg", "setMaxAge");

                              // 2. 设置Cookie的存活时间, 300秒
                              // cookie.setMaxAge(300); // 将cookie持久化到硬盘, 300秒后自动删除cookie文件.

                              // cookie.setMaxAge(-1); // 当浏览器关闭后, Cookie数据被销毁

                              cookie.setMaxAge(0); // 重新把这个cookie文件给删除掉

                              // 3. 发送Cookie
                              response.addCookie(cookie);
                      	

        3. cookie能不能存中文?
          		* 在tomcat 8 之前, cookie中不能直接存储中文数据.
          					* 需要将中文数据转码---一般采用URL编码(%E3)
          		* 在tomcat 8 之后, cookie支持中文数据. 特殊字符还是不支持, 建议使用URL编码存储, URL解码解析.
          					* 代码:
								  // 1. 创建Cookie对象
		                          Cookie cookie = new Cookie("msg", "你好");
		
		                          // 2. 发送Cookie
		                          response.addCookie(cookie);
							* 取的时候还是和原来一样的取法.
        
                      
        4. cookie共享问题?
              1. 假设在一个tomcat服务器中, 部署了多个web项目, 那么在这些web项目中cookie能不能共享?
                   * 默认情况下cookie不能共享
                   * 就是代码中不使用: setPath
                   
                   * setPath(String path): 设置cookie的获取范围, 默认情况下, 设置当前的虚拟目录
                   		* 如果要共享, 则可以将path设置为"/"
                      	* 代码:
							  // 1. 创建Cookie对象
                              Cookie cookie = new Cookie("msg", "你好");

                              // 设置path, 让当前服务器下部署的所有项目共享Cookie信息
                              cookie.setPath("/");

                              // 2. 发送Cookie
                              response.addCookie(cookie);

			  2. 不同的tomcat服务器间cookie共享问题?
                 		* setDomain(String path): 如果设置一级域名相同, 那么多个服务器之间cookie可以共享
                 				* setDomain(".baidu.com"), 那么tieba.baidu.com和news.baidu.com中的cookie可以共享
                 				
                 				
5. Cookie的特点和作用
		1. cookie存储数据在客户端浏览器
		2. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20)
                 
        * 作用:
			1. cookie一般用于存储少量的不太敏感的数据
			2. 在不登入的情况下, 完成服务器对客户端的身份识别.
                
                
 6. 案例: 记住上一次访问时间
 		 1. 需求:
			 1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
			 2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
						
		 2. 分析:
				1. 可以采用Cookie完成
					
					
				2. 在服务器中的Servlet判断是否有一个名为lastTime的cookie
							1.: 不是第一次访问
									1. 响应数据: 欢迎回来, 您上次访问时间为:2020013016:31:26
                    				2. 协会Cookie: lastTime=2020013016:31:26
							2. 没有: 是第一次访问
									1. 响应数据: 您好, 欢饮您首次访问
									2. 写回Cookie: lastTime=2020013016:31:26
                      
                      
          3. cookie 存储的 名称 相同 会被 替换掉   
          
          
          4. cookie 存储特殊字符, 需要编码存储
          
          
          5. 代码:
                // 设置服务器响应编码, 告知浏览器怎么解码
                response.setContentType("text/html;charset=utf-8");

                // 获取所有的Cookie
                Cookie[] cookies = request.getCookies();

                boolean flag = false; // 没有cookie为lastTime

                // cookies不为null时
                if (cookies != null) {

                    // 遍历cookies
                    for (Cookie cookie : cookies) {

                        // 获取cookie名字是否等于lastTime
                        if ("lastTime".equals(cookie.getName())) {

                            flag = true; // 有lastTime这个cookie了

                            // 创建SimpleDateFormat对象, 构造方法中传递指定的模式
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");

                            // 获取当前系统时间
                            Date date = new Date();

                            // 格式化时间
                            String dateFormat = sdf.format(date);

                            System.out.println("编码前: " + dateFormat);

                            // URL编码
                            dateFormat = URLEncoder.encode(dateFormat, "utf-8");

                            System.out.println("编码后: " + dateFormat);

                            // 设置Cookie的value
                            // 把当前时间的字符串, 重新设置Cookie的值, 重新发送Cookie
                            cookie.setValue(dateFormat);

                            cookie.setMaxAge(300);

                            response.addCookie(cookie);

                            // 获取cookie的value, 时间
                            String value = cookie.getValue();

                            System.out.println("解码前: " + value);

                            // URL解码
                            value = URLDecoder.decode(value, "utf-8");

                            System.out.println("解码后: " + value);

                            // 回写给客户端的内容
                            response.getWriter().write("欢迎回来, 您上次访问时间为:" + value);

                            return; // 结束该访问
                        }
                    }
                }

                if (cookies == null || cookies.length == 0 || flag == false) {
                    // 第一次访问

                    // 创建Cookie对象, 因为是第一次, 不需要显示时间, 所以可以随便值
                    Cookie cookie = new Cookie("lastTime", "xxx");

                    // 设置有效期
                    cookie.setMaxAge(300);

                    // 发送cookie
                    response.addCookie(cookie);

                    // 第一次访问
                    response.getWriter().write("您好, 欢迎您首次访问");
                }               

Session

1. 概念: 服务器端会话技术, 在一次会话的多次请求间共享数据, 将数据保存在服务器端的对象中. HttpSession
2. 快速入门:
	1. 获取Session对象:
			* HttpSession	session = request.getSession();

	2. HttpSession对象:
		  Object	getAttribute(String name): 从session中获取该键的值
          void 	setAttribute(String name, Object value): 存储键值对到session中
          void	removeAttribute(String name):删除session存储的键值对
          void  invalidate(): 销毁session
            
      3. 代码:
			* SessionDemo1:
				  // 使用session共享数据

                  // 1. 获取session
                  HttpSession session = request.getSession();

                  // 2. 存储数据
                  session.setAttribute("msg", "hello session");

			* SessionDemo2:
				 // 使用session共享数据

                  // 3. 获取session
                  HttpSession session = request.getSession();

                  // 4. 获取数据
                  Object msg = session.getAttribute("msg");


3. 原理:
	  * Session的实现是依赖于Cookie.
        
      * 两个获取的session对象是同一个
						
	  * SessionDemo1第一次获取Session, 没有Cookie, 会在内存中创建一个新的Session对象, 并给这个Session对象设置了一个JSESSIONID为xxx, 响应给客户端set-cookie: JSESSIONID=xxx.
              
      * 当浏览器请求SessionDemo2的时候会自动携带一个请求头: cookie: JSESSIONID=xxx, 当在此获取Session对象时, 发现内存中有一个JSESSIONID为xxx, 直接把这个session给返回回去了. 所以一次会话内, 多次请求的Session对象时同一个.
        
        
4. 细节:
	1. 当客户端关闭后, 服务器不关闭, 两次获取session是否为同一个?
      		* 默认情况下. 不是.
      		* 如果需要相同, 则可以创建cookie, 键为JSESSIONID, 设置最大存活时间, 让cookie持久化保存
      		* 代码:
				  // 1. 获取session
	              HttpSession session = request.getSession();
	              System.out.println(session);
	
	              // 期望客户端关闭后, session也能相同    session.getId() 获取session的id
	              Cookie cookie = new Cookie("JSESSIONID", session.getId());
	
	              // 设置cookie存活时间
	              cookie.setMaxAge(60 * 60);
	
	              response.addCookie(cookie);
      
      
    2. 客户端不关闭, 服务器关闭后, 两次获取的session是否为同一个?
    	 * 不是同一个, 但是要确保数据不丢失
				* session的钝化:
						* 在服务器正常关闭之前, 将session对象系列化到硬盘上
				* session的活化:
						* 在服务器启动后, 将session文件转化为内存中的session对象即可.
                      
          * session的钝化和活化, tomcat自动帮我们完成了, 所以虽然session对象不是同一个, 但是数据不会丢失.
                      
          * IDEA只能钝化不能活化, 因为IDEA服务器停止时, 会在work(IDEA自己的)下项目里创建SESSIONS.ser(钝化), 而当IDEA再次启动tomcat是, 它会删除work(IDEA自己的work)目录, 在创建一个新的work(IDEA自己的)目录, 所以不能实现活化, 而tomcat不会删除work(tomcat自己的), 所以可以实现活化.
      
          * 注意: 一般部署项目都会部署在tomcat上, 而不是IDEA, 所以不用担心这个问题.
      
            
    3. session的失效时间?   
          1. 服务器关闭
          
          2. session对象调用invalidate()方法
          
          3. session默认失效时间, 30分钟
          		* 选择性配置修改:
					* tomcat里的conf/web.xml找到session-config修改时间 单位 分钟
					<session-config>
                          <session-timeout>30</session-timeout>
                      </session-config>		
                      
                        
5. 案例: 用户登入
	1. 案例需求:
		1. 访问带有验证码的登录页面login.jsp
        2. 用户输入用户名,密码以及验证码。
          * 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
          * 如果验证码输入有误,跳转登录页面,提示:验证码错误
          * 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您
          
    2. 代码(这里我只附上了逻辑代码, 验证码的servlet就不附上了, 还有用户类, 数据库连接池的工具类, 查询数据库的类, 都不附上了):
		* 登入逻辑的代码
              // 设置request编码
              request.setCharacterEncoding("utf-8");
              // 告诉浏览器, 回写的数据以什么方式解码
              response.setContentType("text/html;charset=utf-8");

              // 1. 接受参数
              Map<String, String[]> userMap = request.getParameterMap();
              User user = new User();
              try {
                	// 用它需要导入jar包
                	// BeanUtils->JavaBean工具类, 简化封装的
                  BeanUtils.populate(user, userMap);
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              } catch (InvocationTargetException e) {
                  e.printStackTrace();
              }

              // 单独接收验证码
              String checkCode = request.getParameter("checkCode");

              // 2. 校验参数
              if ("".equals(checkCode) || "".equals(user.getUsername()) || "".equals(user.getPassword())) {
                  request.setAttribute("param_error", "参数不完整...");
                  request.getRequestDispatcher("/login.jsp").forward(request, response);
                  return;
              }

              // 获取session
              HttpSession session = request.getSession();
              String code = (String)session.getAttribute("checkCode");

              // 删除验证码, 让验证码是一次性的
              session.removeAttribute("checkCode");

              // 先校验验证码防止查询数据库开销
              // code == null 或 验证码不相等
              if (code == null || !(code.equalsIgnoreCase(checkCode))) {
                  request.setAttribute("cc_error", "验证码错误");
                  request.getRequestDispatcher("/login.jsp").forward(request, response);
                  return;
              }

              // 查询数据库 获取 用户信息
              User loginUser = new UserDao().login(user);

              // 校验用户名和用户密码
              if (loginUser == null) {
                  request.setAttribute("login_error", "用户名或密码错误");
                  request.getRequestDispatcher("/login.jsp").forward(request, response);
                  return;
              }

              // 3. 业务处理
              // 把用户信息存储到session中
              session.setAttribute("user", loginUser);
              // 4. 返回应答
              // 登入成功跳转到success.jsp页面
              response.sendRedirect(request.getContextPath() + "/success.jsp");
					
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只因为你温柔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值