• HttpSession 入门


    1. HttpSession 概述

    • 位于 javax.servlet.http 包;
    • HttpSession 是由 JavaWeb 提供的功能, 用来会话跟踪的类, session 是服务器端对象, 保存在服务器端!!!
    • HttpSession 底层依赖 Cookie, 或是 URL 重写!

    2. HttpSession 的作用

    1. 会话范围: 从某个用户首次访问服务器开始, 到该用户关闭浏览器结束!
      • 会话: 一个用户对服务器的多次连贯性请求! 所谓连贯性请求, 就是该用户多次请求中间没有关闭浏览器!
    2. 服务器会为每个用户创建一个 Session 对象, session 就好比用户在服务器端的账户, 它们被服务器保存到
      一个 Map 中, 这个 Map 被称之为 session 的缓存.
      - Servlet 中得到 session 对象: HttpSession session = request.getSession();
      - JSP 中得到 session 对象: session 是 JSP 内置对象之一, 不用创建就可以直接使用!
    3. session 域相关方法:
      • void setAttribute(String name, Object value);
      • Object getAttribute(String name); : 返回值为 Object 类型, 需要强转!
      • void removeAttribute(String name);

    // 示例: 保存用户登录信息
        /*
         * 相关页面和 Servlet
         *   login.jsp: 登录页面
         *   succ1.jsp: 只有登录成功才能访问的页面
         *   LoginServlet: 校验用户是否登录成功
         *
         * 各页面和 Servlet 内容:
         *    login.jsp: 提供登录表单, 将表单请求数据提供给 LoginServlet, 如果登录失败,需要显示错误信息
         *    LoginServlet: 获取请求参数, 校验用户是否登录成功
         *         失败: 保存错误信息到 request 域, 转发到 login.jsp( login.jsp 显示 request 域中的错误信息)
         *         成功: 保存用户信息到 session 域中, 重定向到 succ1.jsp 页面, 显示 session 域中的用户信息
         *
         *    succ1.jsp: 从 session 域获取用户信息, 如果不存在, 显示"您还没有登录", 存在则显示用户信息
         *    succ2.jsp: 从 session 域获取用户信息, 如果不存在, 显示"您还没有登录", 存在则显示用户信息
         *    
         * 只要用户没有关闭浏览器, session 就一直存在, 那么保存在 session 中的用户信息也就一直存在! 那么用户访问
         * succ1 就会成功!
         *
         * 附加项(浏览器保存用户信息):
         *     把用户名保存到 cookie 中, 发送给客户端浏览器
         *     当再次打开 login.jsp 时, login.jsp 会读取 request 中的 cookie, 把它显示到用户名文本框中.
         */
    
    // login.jsp
    
        <head>
            // 换一张的函数
            <script type="text/javascript">
                function _change(){
                    // 获取 img 节点
                      var imgEle = document.getElementById("img");
                    // 对该节点的 src 属性重新赋值
                    imgEle.src = "/day11_1/VerifyCodeServlet?a="+new Date().getTime();
                } 
            </script>
        </head>
    
    
        <body>
            // 获取 cookie 中的信息
            <%
                // 定义变量, 并赋值为空
                String uname = "";
                Cookie[] cks = request.getCookies();
                // 如果有 cookie 存在
                if(cks != null){
                        // 遍历数组
                        for(Cookie ck:cks){
                                if("uname".equals(ck.getName())){
                                uname = ck.getValue();
                                }
                        }
                }
            %>
    
            // 显示错误信息
            <%
                String message = "";
                String msg = (String)request.getAttribute("msg");
                if(msg != null){
                    message = msg;
                }
            %>
    
    
            <h1>登录</h1>
            // 显示错误信息
            <font color="red"><b><%=message %></b></font>
    
            // 正常表单
            <form action="" method="POST">
                // 注意: <%=uname %> 需要使用引号引起来
                // value 是 cookie 中的用户名, 显示到文本框中
                用户名:<input type="text" name="username" value="<%=uname %>"/><br/>
                密 码:<input type="password" name="psw"/><br/>
                验证码:<input type="text" name="verifyCode" size="3"/>
                         <img id="img" src="/day11_1/VerifyCodeServlet" />
                         <a href="javascript:_change()">换一张</a><br/>
                <input type="submit" value="提交"/>
            </form>
        </body>
    
    // LoginServlet
            public void doPost(HttpServletRequest request, HttpServletResponse response){
                //首先处理 POST 编码问题
                request.setCharacterEncoding("uft-8");
    
                // 获取 request 请求表单中的数据, 不是 request 域
                String name = request.getParameter("username");
    
                // 获取 session 域中验证码数据
                String sessionCode = request.getSession().getAttribute("session_vcode");
                // 获取 request 请求中的验证码
                String paramCode = request.getParamter("verifyCode");
                // 比较两者
                if(!paramCode.equalsIgnoreCase(sessionCode)){
                    request.setAttribute("msg","您填写的验证码有误!");
                    //转发
                    request.getRequestDispatcher("login.jsp").forward(request,response);
                    return;
                }
    
                // 判断,只要不是 "itcast",就能登录成功, 重定向至 succ1.jsp
                // 否则,保存错误信息到 request域中, 转发至 login.jsp
                if(!"itcast".equalsIgnoreCase(name)){
                    // 附加项: 浏览器保存用户信息, 方便第二次登录
                    Cookie ck = new Cookie("uname",name);
                    ck.setMaxAge(60*60*24);  // 最长在浏览器保存 1 天
                    response.addCookie(ck);
    
                    // 获取 session 域
                    HttpSession session = request.getSession();
                    // 保存用户名到session域
                    session.setAttribute("username",name);
                    // 重定向到 succ1.jsp, 路径中需要加入项目名
                    response.sendRedirect("/day11_1/succ1.jsp");
                } else {
                    // 保存错误信息到 request 域
                    request.setAttribute("msg","用户名或密码错误!");
                    // 转发至login.jsp
                    request.getRequestDispatcher("/login.jsp").forward(request,response);
                }
            }
    
    // VerifyCodeServlet
            public class VerifyCodeServlet extends HttpServlet{
                    pubilc void doGet{
                        VerifyCode vc = new VerifyCode();
                        BufferedImage bi = vc.getImage();
                        // 将图片中的文本保存到 session 域中
                        request.getSession().setAttribute("session_vcode",vc.getText());
                        // 将图片显示在 login.jsp 页面
                        VerifyCode.output(bi,response.getOutputStream());
                    }
            }
    
    // succ1.jsp
        <body>
        // 如果用户通过输入地址来访问该页面, 需要判断 session 中的用户名
            <%
                String name = (String)session.getAttribute("username");
                if(name == null){
                    // 保存错误信息
                    request.setAttribute("msg","您还没有登录!");
    
                    // 转发到 login.jsp, 留头不留体
                    request.getRequestDispatcher("/login.jsp").forward(request,response);
                    // 结束程序, 下面的内容不会输出
                    return;
                }
            %>
            <h1>Succ1</h1>
            欢迎<%=name %>光临本网站!!
        </body>
    

    3. HttpSession 原理

    • 如果 sessionId 不存在, 服务器创建 session 对象, 把 session 保存起来, 把新创建的 sessionID 保存到 Cookie 中;
    • 如果 sessionId 存在, 通过 sessionId 查找 session 对象, 如果没有找到, 创建 session, 把 session 保存
      起来, 把新创建的 sessionId 保存到 Cookie 中;
    • 如果 sessionId 存在, 通过 sessionId 查找到了 session 对象, 那么就不会创建 session 对象了.
    • 返回 session 对象

    备注: session 对象存储在服务器端的 Map 集合中, 键为:sessionId, 值为: session 对象.

    1. 如果创建了新的 session, 浏览器会得到一个包含了 sessionId 的 Cookie, 这个 Cookie 的生命为 -1,
      即只在浏览器内存中存在. 浏览器关闭后,该 Cookie 会被删除.

    2. 服务器并不会在访问页面时,马上给你创建 session 对象, 只有在第一次获取 session 对象时, 才会调用
      request.getSession()方法创建 session 对象.

      • 访问 ".jsp" 文件会自动调用 request.getSession(); 方法;
      • 访问 Servlet 页面, 需要人工写入 request.getSession(); 方法.
    3. 多次请求: 如果第一次请求创建了 session 对象. 第二次请求, 服务器端再次执行 request.getSession()
      法,服务器端可以通过 Cookie 中的 JSESSIONID 找到第一次请求创建的 session 对象. 所以与上一次请求使
      用的是同一个 session 对象.

    4. 方法比较:

      • request.getSession(true); : 与 request.getSession(); 效果相同;
      • request.getSession(false);: 如果 session 缓存中,不存在 session,返回 null,而不会创建 session
        对象. 如果 cookie 不存在, 也不会创建 session 对象.

    4. HttpSession 其他方法

    • String getId(); : 获取 sessionId(32 位长字符串);
    • int getMaxInactiveInterval(); : 获取 session 对象的最大不活动时间(秒), 默认为 30 分钟;
      当 session 对象在30分钟内没有使用, 那么会被 Tomcat 从 session 池中移除.
    • void invalidate(); : 让 session 失效!
    • boolean isNew(); : 查看 session 对象是否为新
    // 获取 UUID, 也就是 sessionId
    // J2SE 中的 java.util 中有 UUID 类
    UUID uuid = UUID.randomUUID();
    String str = uuid.toString();
    str = str.replace("-","");
    str = str.toUpperCase();
    

    5. web.xml 中配置 session 的最大不活动时间(分钟)

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

    6. URL 重写 (理解)

    • session 依赖 Cookie, 目的是让客户端发送请求时,归还 sessionId, 这样才可能找到对应的 session 对象;
    • 如果客户端禁用了 Cookie, 那么就无法得到 sessionId, 那么 session 也就没法使用了!
    • 这时, 可以使用 URL 重写来替代 Cookie
      • 让网站的所有超链接, 和表单中都添加一个特殊的请求参数, 即 sessionId;
      • 这样服务器可以通过获取请求参数得到 sessionId, 从而找到 session 对象;
    • response.encodeURL(String url);
      • 该方法会对 url 进行智能的重写, 当请求中没有归还 sessionId 这个 cookie, 那么该方法会重写 url,
        在指定的 url 后添加 JESSIONID 参数. 否则, 不会重写.

    参考资料:

  • 相关阅读:
    119. Pascal's Triangle II
    118. Pascal's Triangle
    112. Path Sum
    111. Minimum Depth of Binary Tree
    110. Balanced Binary Tree
    108. Convert Sorted Array to Binary Search Tree
    88. Merge Sorted Array
    83. Remove Duplicates from Sorted List
    70. Climbing Stairs
    陌陌面试经历
  • 原文地址:https://www.cnblogs.com/linkworld/p/7593713.html
Copyright © 2020-2023  润新知