美文网首页
4/19day37_session

4/19day37_session

作者: 蹦蹦跶跶的起床啊 | 来源:发表于2020-04-24 15:36 被阅读0次

    回顾

    1. 会话技术
        http是无状态协议,多次请求之间相互独立,不能共享数据
        会话技术为了解决多次请求之间,共享数据问题
        cookie将数据存储到客户端
    
    2. cookie快速入门
        设置cookie
            Cookie cookie = new Cookie(String name,String value);
            response.addCookie(cookie);
        接收cookie
            Cookie[] cookies = rqeuest.getCookies();
    
    3. cookie使用细节
        服务器一次可以发送多个cookie
        tomcat8及以上版本支持中文,但不支持特殊符号(空格、逗号、分号、加号)
            URLEncoder 编码
            URLDecoder 解码
        cookie.setPath(String path);设置cookie的携带路径
        cookie.setMaxAge(int second);
            正数
            负数
            零
    
    4. cookie特点
        数据存储在客户端,只能存中文,单个大小不能超过4KB,数量不能超过50个,数据不太安全..
    
    5. 综合案例
        上次访问时间 --> jsp
        上次访问记录
    

    Session&三大域对象总结

    今日目标

    1. session【重点】
         它也是一个域对象
         
    2. 三大域对象总结
        servletContext
        session
        request
        
    3. 综合案例
        商品购物车
        用户登录(验证码)
    

    一 Session

    1.1 概述

    使用Cookie问题

    1. 最多存储4K字符串
    2. 存储数据不太安全

    session作用:在一次会话的多次请求之间共享数据,将数据保存到服务器端

    1.2 快速入门

    HttpSession也是一个域对象

    * API
        1. 存储数据
                void setAttribute(String name,Object value)
        2. 获取数据
                Object getAttribute(String name)
        3. 删除数据
                void removeAttribute(String name)
    

    步骤分析

    1. 将数据存储到session中
        // 1.通过rquest对象,获取session对象
            HttpSession session = request.getSession();
        // 2.操作session的API,存储数据
            session.setAttribute("username","哈哈,呵呵");
    
    2. 从session中获取数据
        // 1.通过rquest对象,获取session对象
            HttpSession session = request.getSession();
        // 2.操作session的API,获取数据
            session.getAttribute("username");
    
    @WebServlet("/SetSession")
    public class SetSession extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.通过rquest对象,获取session对象
            HttpSession session = request.getSession();
            // 2.操作session的API,存储数据
            session.setAttribute("username", "哈哈,呵呵");
        }
    
    }
    
    @WebServlet("/GetSession")
    public class GetSession extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.通过rquest对象,获取session对象
            HttpSession session = request.getSession();
            // 2.操作session的API,获取数据
            String username = (String) session.getAttribute("username");
            System.out.println("GetSession获取:" + username);
        }
    
    }
    

    1.3 工作原理

    Session基于Cookie技术实现

    1.4 Session细节

    1.4.1 客户端关闭,服务器不关闭

    两次获取的Session数据是否为相同?

    * 默认情况下,浏览器关闭,再次打开二次获取的session不一样
        基于cookie实现(浏览器关闭,cookie销毁)
        
    * 设置cookie的存活时间(JESSIONID)
        这里我们代替服务器,做一个小操作,覆盖这个JSESSIONID,指定持久化时间
    

    1.4.2 客户端不关闭,服务器关闭

    两次获取的Session数据是否为相同?

    * 当服务器正常关闭,重启后,二次获取的session数据一样
        tomcat这哥们实现以下二个功能
        钝化(序列化)
            当服务器正常关闭时,session中的数据,会序列化到磁盘
        活化(反序列化)
            当服务器开启后,从磁盘文件中,反序列化到内存中
    

    我们使用的idea工具有坑....

    支持钝化

    我们可以强制设置idea重启时,不清除session会话

    1.4.3 生命周期

    * 何时创建
            用户第一次调用request.getSession()方法时,创建
            
    * 何时销毁
            服务器非正常关闭        
            非活跃状态30分钟后
                tomcat进行配置  /tocmat安装目录/conf/web.xml
            session.invalidate(); 自杀
    
    * 作用范围
            一次会话中,多次请求之间
            注意:每一个浏览器跟服务器都是独立的会话...
    

    1.4.4 URL重写(了解)

    Session基于Cookie技术实现;浏览器的Cookie是可以禁用的,一旦禁用了之后,Session就会出现问题了。

    开发中,一般我们是不关注用户的cookie是否禁用的,若用户禁用了cookie,只能别用网站了

    若真想处理用户端的cookie禁用,我们可以使用url重写技术:

    @WebServlet("/SessionDemo2")
    public class SessionDemo2 extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 获取session对象
            HttpSession session = request.getSession();
            // 向session中存数据
            session.setAttribute("username", "哈哈,即使浏览器禁用了cookie,也不影响我使用");
    
            // 定义url
            String url = "/day12_session/GetSession";
    
            // 重写url,拼接JSESSIONID
            url = response.encodeURL(url); // /day12_session/GetSession?JSESSIONID=xxsdfasdf
            System.out.println(url);
    
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write("<a href='" + url + "'>跳转到获取session内容</a>");
        }
    
    }
    

    1.5 Session特点

    1. session存储数据在服务器
    
    2. session存储类型任意(Object)
    
    3. session存储大小和数量没有限制(相对于内存)
    
    4. session存储相对安全
    

    cookie和session的选择

    1. cookie将数据保存在浏览器端,数据相对不安全.建议敏感的数据不要放在cookie中,而且数据大小是有限制的
      1. 成本低,对服务器要求不高
      2. 浏览器,解决这个不足,localStroage【项目二中讲解...】
    2. session将数据保存在服务器端,数据相对安全.数据的大小要比cookie中数据灵活很多
      1. 成本较高,对服务器压力较大

    二 三大域对象总结

    request、session、ServletContext

    2.1 API

    1. 设置数据
            void setAttribute(String name, Object o)
            
    2. 获取数据
            Object getAttribute(String name)
            
    3. 删除数据
            void removeAttribute(String name)
    

    2.2 生命周期

    2.2.1 ServletContext域对象

    * 何时创建
            服务器正常启动,项目加载时,创建
    
    * 何时销毁
            服务器关闭或项目卸载时,销毁
    
    * 作用范围
            整个web项目(共享数据)
    

    2.2.2 HttpSession域对象

    * 何时创建
            用户第一次调用request.getSession()方法时,创建【不太标准..】
            用户访问携带的jsessionid与服务器不匹配时,创建
            
    * 何时销毁
            服务器非正常关闭
            未活跃状态30分钟
            自杀
    
    * 作用范围
            一次会话中,多次请求间(共享数据)
    

    2.2.3 HttpServletRequest域对象

    * 何时创建
            用户发送请求时,创建
            
    * 何时销毁
            服务器做出响应后,销毁
    
    * 作用范围
            一次请求中,多次转发间(共享数据)
    

    2.3 小结

    • 能用小的不用大的:request<session<servletContext

    • 常用的场景:

      • request:一次查询的结果(servlet转发jsp)
      • session:存放当前会话的私有数据
        • 用户登录状态
        • 验证码
        • 购物车
    • servletContext:若需要所有的servlet都能访问到,才使用这个域对象.

      • spring课程中会涉及到

    三 综合案例

    3.1 商品购物车

    需求

    有一个商品页面,可以点击超链接将商品添加到购物车,还有一个超链接,点击它的时候可以查看购物车中商品信息

    3.1.1 需求分析

    3.1.2 代码实现

    ① goods.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>goods.jsp</title>
    </head>
    <body>
    <h3>商品列表</h3>
    <a href="/day12_session/AddCartServlet?name=电视机">电视机,加入购物车</a><br>
    <a href="/day12_session/AddCartServlet?name=冰箱">冰箱,加入购物车</a><br>
    <a href="/day12_session/AddCartServlet?name=洗衣机">洗衣机,加入购物车</a><br>
    <a href="/day12_session/AddCartServlet?name=电脑">电脑,加入购物车</a><br>
    </body>
    </html>
    
    

    ② AddCartServlet

    @WebServlet("/AddCartServlet")
    public class AddCartServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8"); // 请求解码
            response.setContentType("text/html;charset=utf-8");// 响应编码
    
            // 1.获取请求参数
            String product = request.getParameter("name");
            // 2.返回结果
            response.getWriter().write(product + ",商品已成功加入购物车 <br>");
    
            // 3.从session中获取购物车
            Map<String, Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");
    
            // 4.判断购物车是否为空
            if (cart == null) {
                cart = new HashMap<>();
            }
            // 5.判断购物车中是否包含本次添加的商品
            if (cart.containsKey(product)) {// 6.存在,数量+1
                Integer oldCount = cart.get(product); // 之前数量
                cart.put(product, oldCount + 1);// 数量加1
            } else { // 7.不存在,直接添加商品,数量为1
                cart.put(product, 1);
            }
            // 8.重新将购物车,写入到session中
            request.getSession().setAttribute("cart", cart);
    
            // 9.继续浏览
            response.getWriter().write("<a href='/day12_session/goods.jsp'>继续浏览</a><br>");
            // 10.查看购物车
            response.getWriter().write("<a href='/day12_session/cart.jsp'>查看购物车</a><br>");
        }
    
    }
    

    ③cart.jsp

    <%@ page import="java.util.Map" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>cart</title>
    </head>
    <body>
    <h3>购物车页面</h3>
    
    <table border="1" width="200px" align="center">
        <tr>
            <th>商品</th>
            <th>数量</th>
        </tr>
        <%
             // 1.从session中获取购物车
            Map<String,Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");
            // 2.判断是否为空
            if(cart == null){
                out.write("购物车内暂时没有商品<br>");
            }else{
                for (String s : cart.keySet()) {
                    out.write("<tr><td>"+s+"</td><td>"+cart.get(s)+"</td></tr>");
                }
            }
    
        %>
    </table>
    </body>
    </html>
    

    3.2 用户登录(验证码)

    需求

    用户访问带有验证码的登录页面,输入用户名,密码以及验证码实现登录功能。

    3.2.1 需求分析

    3.2.2 代码实现

    • 明天休息,感觉那丑自己优化...问题自己解决.....

    ① 创建web项目

    ② 导入验证码Servlet

    ③ login.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>login.jsp</title>
    </head>
    <body>
    <h3>用户登录</h3>
    <form action="/day12_login/LoginServlet" method="post">
        用户:<input type="text" name="username"> <br>
        密码:<input type="password" name="password"><br>
        验证码:<input type="text" name="checkcode"> <img src="/day12_login/CheckcodeServlet" alt=""><br>
        <input type="submit" value="登录">
        <span style="color:red">
            <%
                String error = (String) request.getAttribute("error");
                if (error != null) {
                    out.write(error);// 输出提示信息
                }
            %>
        </span>
    </form>
    </body>
    </html>
    
    

    ④ LoginServlet

    @WebServlet("/LoginServlet")
    public class LoginServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    
        // 课下作业,实现非空判断...
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            // 1.获取用户输入的验证码
            String checkcode = request.getParameter("checkcode");
            // 2.获取session中验证码
            String codeSession = (String) request.getSession().getAttribute("code_session");
            // 3.校验是否匹配
            if (!checkcode.equalsIgnoreCase(codeSession)) {
                // 验证码不配,友情提示...
                request.setAttribute("error", "验证码输入错误...");
                // 转发到login.jsp
                request.getRequestDispatcher("/login.jsp").forward(request, response);
                // 代码不在往下执行....
                return;
            }
    
            // 4.获取用户输入的用户名和密码
            String username = request.getParameter("username");
            String password = request.getParameter("password");
    
            // 5.判断用户名密码不正确
            if (!("jack".equals(username) && "123".equals(password))) {
                // 友情提示
                request.setAttribute("error", "用户名或密码错误...");
                // 转发到login.jsp
                request.getRequestDispatcher("/login.jsp").forward(request, response);
                // 代码不在往下执行....
                return;
            }
    
            // 6. 将用户名存入到session中
            request.getSession().setAttribute("username", username);
            // 7.重定向到success.jsp
            response.sendRedirect(request.getContextPath() + "/success.jsp");
    
        }
    
    }
    

    ⑤ success.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>success</title>
    </head>
    <body>
    <h3><%
        // 获取用户信息
        String username = (String) request.getSession().getAttribute("username");
        if (username != null) {
            out.write("用户您好,登录成功:"+username);
        }
    %></h3>
    </body>
    </html>
    
    

    老师下午总结

    疑惑点|易错点|拓展

    session钝化要注意的事项

    • 关闭tomcat服务器的时候,tomcat服务器会对session的数据进行钝化,重启

      服务器的时候可以重新读取到session的数据。

    • 钝化的数据所属类一定要实现Serializable接口,否则无法钝化。

    User类

    package com.itheima.model;
    
    import java.io.Serializable;
    
    public class User implements Serializable {
    
        private int id;
    
        private String name;
    
    
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
    

    设置session数据

    package com.itheima.web;
    
    import com.itheima.model.User;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    @WebServlet("/setSession")
    public class SetSessionServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1.  创建一个User对象
            User user = new User();
            user.setId(110);
            user.setName("狗娃");
            //2. 获取sesison
            HttpSession session = request.getSession();
    
    
            //3. 把User对象存储到Session中
            session.setAttribute("user",user);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    }
    
    

    获取Session的数据

    package com.itheima.web;
    
    import com.itheima.model.User;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    @WebServlet("/getSession")
    public class GetSessionServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=utf-8");
            HttpSession session = request.getSession();
            //从session获取User
            User user = (User) session.getAttribute("user");
    
            response.getWriter().write("从session获取到的数据:"+user);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    }
    
    

    如何检查用户是否关闭cookie

    • 在用户浏览商品页面的时候,我们就发送一个cookie

    • 在添加购物车的我们就检查是否有我们刚刚发送的cookie,如果没有该用户肯定是关闭了cookie的功能,

      如果存在这个cookie,那么用户没有关闭。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
      <%
    //    在用户浏览器商品的时候,我们就向用户发送一个cookie
        Cookie cookie = new Cookie("cookieFlag","true");
        response.addCookie(cookie);
      %>
    
        <h1>商品列表页面</h1>
          电视机 <a href="/day37_session/addShopCart">添加购物车</a><br/>
          洗衣机 <a href="/day37_session/addShopCart">添加购物车</a><br/>
      </body>
    </html>
    
    
    package com.itheima.web;
    
    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;
    import java.io.PrintWriter;
    
    @WebServlet("/addShopCart")
    public class AddShopCartServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=utf-8");
            PrintWriter out = response.getWriter();
            boolean flag = true; // 浏览器是否关闭cookie的一个标记, 默认浏览器是关闭
            //添加购物车之前,我先检查是否有刚刚添加的cookie带过来。
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if(cookie.getName().equals("cookieFlag")){
                        //有cookie过来,那么用户则没有关闭
                        flag = false;
                        break;
                    }
                }
            }
    
          if(flag){
            //关闭了cookie
              out.write("<h1>尊敬的用户,我们的购物车功能需要开启cookie才可以使用!</h1>");
          }else{
                //没有关闭
              out.write("<h1>尊敬的用户,添加成功!</h1>");
          }
    
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    }
    
    

    今日重点

    • 获取或创建Session

      • request.getSession();
    • session域的操作方法

      • setAttribute()
      • getAttribute()
      • removeAttribute()
    • session的原理

      • 第一次获取session的时候,服务器会创建一个session,并且把该session的编号以cookie的形式发送给浏览器
    • 关闭浏览器,如何找回session

      • 我们需要创建一个同名的cookie,保存session的id,并且设置有效时间。
    • 关闭服务器,如何保存session的数据

      • tomcat会完成钝化的工作,只不过钝化的数据所属的类一定要实现Serializable接口。
    • session的生命周期

      • 第一次调用request.getSesion()方法创建
      • 默认情况session的销毁时间是30分钟.
      • invildate() 立即销毁

    相关文章

      网友评论

          本文标题:4/19day37_session

          本文链接:https://www.haomeiwen.com/subject/djdfwhtx.html