【JavaWeb】Session详解+底层分析+代码演示

Session有什么用

思考两个问题—抛砖引玉

  1. 不同的用户登录网站后,不管该用户浏览该网站的哪个页面,都可显示登录人的名字, 还可以随时去查看自己的购物车中的商品, 是如何实现的?
  1. 也就是说,一个用户在浏览网站不同页面时,服务器是如何知道是张三在浏览这个页面, 还是李四在浏览这个页面?

解决之道—session 技术

  1. Session 是服务器端技术,服务器在运行时为每一个用户的浏览器创建一个其独享的 session 对象/集合。

  2. 由于 session 为各个用户浏览器独享,所以用户在访问服务器的不同页面时,可以从各自的 session 中读取/添加数据, 从而完成相应任务。

Session基本原理

Sesson 原理示意图

image-20230311125917379

image-20230311125929010

  1. 当用户打开浏览器,访问某个网站, 操作 session 时,服务器就会在内存(在服务端)为该 浏览器分配一个 session 对象,该 session 对象被这个浏览器独占, 如图
  2. 这个 session 对象也可看做是一个容器/集合,session 对象默认存在时间为 30min(这是在tomcat/conf/web.xml),也可修改
    image-20230311131023482
    image-20230311131117583

Session可以做什么

  1. 网上商城中的购物车
  2. 保存登录用户的信息
  3. 将数据放入到 Session 中,供用户在访问不同页面时,实现跨页面访问数据
  4. 防止用户非法登录到某个页面

如何理解Session

  1. session 存储结构示意图
    image-20230311130755315
  2. 你可以把 session 看作是一容器类似 HashMap,有两列(K-V),每一行就是 session 的一个属性。
  3. 每个属性包含有两个部分,一个是该属性的名字(String),另外一个是它的值(Object)

Session常用方法

Session文档

HttpSession (Java™ EE 7 Specification APIs) (oracle.com)

  1. getAttribute(String name) - 获取指定名称的属性值
  2. setAttribute(String name, Object value) - 设置指定名称的属性值
  3. removeAttribute(String name) - 移除指定名称的属性值
  4. getId() - 获取会话ID
  5. getCreationTime() - 获取会话创建时间
  6. getLastAccessedTime() - 获取会话最后访问时间
  7. setMaxInactiveInterval(int interval) - 设置会话的最大不活动时间间隔
  8. getMaxInactiveInterval() - 获取会话的最大不活动时间间隔
  9. invalidate() - 使会话无效
  10. isNew() - 判断会话是否为新创建的

Session基本使用

  1. 创建和获取session, API一样

    HttpSession hs = request.getSession()
    

    image-20230311132419601
    第 1 次调用是创建 Session 会话, 之后调用是获取创建好的 Session 对象

  2. 向session添加属性

    hs.setAttribute(String name,Object val);
    

    image-20230311133251959

  3. 从session获取某个属性

    Object obj=hs.getAttribute(String name);
    

    image-20230311133334589

  4. 从 session 删除调某个属性

    hs.removeAttribute(String name);
    

    image-20230311133148068

  5. 判断是不是刚创建出来的 Session

    hs.isNew();
    

    image-20230311133037443

  6. 获取session的会话ID值

    hs.getId();
    

    image-20230311133444206

session 底层实现机制

原理分析图(一图胜千言)

image-20230311134730119

针对每个会话都有一个Session。

image-20230311134817009

getSession()方法是session创建的核心,极其重要!

它先判断浏览器是否带有jsessionid这个cookie数据:

  1. 如果没有携带:就直接创建session,并且分配一个jsessionidjsessionid和session的管理通过一个Map结构维护;
  2. 如果携带了:
    1. 如果不存在id=jsessionid的对象:就创建session,同时分配id;
    2. 如果存在id=jsessionid的对象:就直接进行操作。

如果服务器在本次会话中创建了session,就返回Set-Cookie:jsessionid=xxx

演示创建session

  1. 需求: 演示 Session 底层实现机制-创建读取 Session

  2. 创建CreateSession.java

    package com.hspedu.session;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    /**
     * @ClassName CreateSession
     * @Description 演示Session的创建
     * @Author zephyr
     * @Date 2023/3/11 14:16
     * @Version 1.0
     */
    
    @WebServlet(name = "CreateSession", value = "/createSession")
    public class CreateSession extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("================CreateSession 被调用================");
    
            //1. 获取session,同时也可能创建session
            HttpSession session = request.getSession();
            //2. 获取sessionId
            System.out.println("当前sessionId = " + session.getId());
            //3. 给session存放数据
            session.setAttribute("email", "zs@qq.com");
    
            //4. 给浏览器发送回复
            response.setContentType("text/html;charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.println("<h1>创建Session成功</h1>");
            writer.flush();
            writer.close();
    
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    
    

    image-20230311144451043

发送请求的时候没有携带JsessionId,服务器收到之后为之创建一个JsessionId

image-20230311144608335

并且在响应头里返回这个Set-Cookie: JESESSION=xxxxxxx

image-20230311144644024

然后该JsessionId就被存储在了浏览器的Cookie中

image-20230311150014293


现在如果我们再次向客户端发起请求,携带了刚刚的JsessionId,那么客户端就不会再为我们创建的新的session,而是使用与JsessionId对应的session。并且,返回响应时也不会Set-Cookie: JESESSION=xxxxxxx

image-20230311150513169

演示读取session

package com.hspedu.session;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @ClassName ReadSession
 * @Description 演示读取session
 * @Author zephyr
 * @Date 2023/3/11 15:10
 * @Version 1.0
 */

@WebServlet(name = "ReadSession", value = "/readSession")
public class ReadSession extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("================ReadSession 被调用================");
        //1. 获取Session,如果没有session也会创建
        HttpSession session = request.getSession();
        //输出sessionId
        System.out.println("sessionId = " + session.getId());
        //2. 读取属性
        Object email = session.getAttribute("email");
        if (email != null){
            System.out.println("session属性 email = " + (String) email);
        } else {
            System.out.println("session没有email属性");
        }
        //给浏览器回回复
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.println("<h1>创建/操作session成功</h1>");
        writer.flush();
        writer.close();
    }

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

image-20230311152040016

image-20230311152058821

image-20230311152021201

Session实现原理动画

服务器是如何实现一个 session 为一个用户浏览器服务的

image-20230311152248702

Session 生命周期

Session 生命周期-说明

  1. public void setMaxInactiveInterval(int interval) 设置 Session 的超时时间(以秒为单位), 超过指定的时长,Session 就会被销毁。
    1. 值为正数的时候,设定 Session 的超时时长。
    2. 负数表示永不超时
  2. public int getMaxInactiveInterval()获取 Session 的超时时间
  3. public void invalidate() 让当前 Session 会话立即无效
  4. 如果没有调用 setMaxInactiveInterval() 来指定 Session 的生命时长,Tomcat 会以 Session 默认时长为准,Session 默认的超时为 30 分钟, 可以在 tomcat 的 web.xml 设置

image-20230311131117583

  1. Session 的生命周期指的是 :客户端/浏览器两次请求最大间隔时长,而不是累积时长。 即当客户端访问了自己的 session,session 的生命周期将从 0 开始重新计算。(解读: 指的是同一个会话两次请求之间的间隔时间)
  2. 底层: Tomcat 用一个线程来轮询会话状态,如果某个会话的空闲时间超过设定的最大值, 则将该会话销毁

Session 生命周期-应用实例

  • 需求:代码演示说明Session的生命周期

createSession2.java

package com.hspedu.session;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @ClassName CreateSession2
 * @Description TODO
 * @Author zephyr
 * @Date 2023/3/11 15:35
 * @Version 1.0
 */

@WebServlet(name = "CreateSession2", value = "/createSession2")
public class CreateSession2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("================CreateSession2 被调用================");

        //获取Session,如果没有session也会创建
        HttpSession session = request.getSession();
        //输出session的id
        System.out.println("sessionId = " + session.getId());
        //设置生命周期为60s
        session.setMaxInactiveInterval(60);
        //设置两个属性
        session.setAttribute("u", "zephyr666");

        //给浏览器发送回复
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.println("<h1>创建session成功,生命周期60s</h1>");
        writer.flush();
        writer.close();

    }

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

ReadSession2.java

package com.hspedu.session;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Time;

/**
 * @ClassName ReadSession2
 * @Description TODO
 * @Author zephyr
 * @Date 2023/3/11 15:37
 * @Version 1.0
 */

@WebServlet(name = "ReadSession2", value = "/readSession2")
public class ReadSession2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("================ReadSession2 被调用================");
        //获取Session
        HttpSession session = request.getSession();
        //输出session的id
        System.out.println("sessionId = " + session.getId());
        //获取session的属性
        Object u = session.getAttribute("u");
        if (u != null){
            System.out.println("u = " + u);
        } else {
            System.out.println("读取不到session属性u");
        }

        //给浏览器回回复
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.println("<h1>读取session成功</h1>");
        writer.flush();
        writer.close();
    }

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

image-20230311155110040

解读:Session 的生命周期

  1. 指的是两次访问 session 的最大间隔时间
  2. 如果你在 session 没有过期的情况下,操作 session, 则会重新开始计算生命周期
  3. session 是否过期,是由服务器来维护和管理
  4. 如我们调用了 invaliate() 会直接将该 session 删除/销毁
  5. 如果希望删除 session 对象的某个属性, 使用 removeAttribute("xx")

DeleteSession.java

package com.hspedu.session;

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

/**
 * @ClassName DeleteSession
 * @Description TODO
 * @Author zephyr
 * @Date 2023/3/11 17:26
 * @Version 1.0
 */

@WebServlet(name = "DeleteSession", value = "/DeleteSession")
public class DeleteSession extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        // 让 Session 会话立即超时
        session.invalidate();

        response.setContentType("text/html;charset=utf-8"); // 先获取 Session 对象
        response.getWriter().write("Session 已经设置为超时");
    }

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

Session 经典案例-防止非法进入管理页面

作业布置

  • 需求说明: 完成防止用户登录管理页面应用案例(如图)
    image-20230312000247733

  • 说明:

    • 只要密码为 666666, 我们认为就是登录成功
    • 用户名不限制
    • 如果验证成功,则进入管理页面 ManageServelt.java ,否则进入 error.html
    • 如果用户直接访问 ManageServet.java , 重定向到到 userlogin.html

作用讲评

  1. 创建userlogin.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>用户登录</title></head>
    <body>
    <h1>用户登录</h1>
    <form action="/cs/loginCheck"
          method="post">
      用户名:<input type="text" name="username"/><br/><br/>
      密 码:<input type="password" name="password"><br><br/>
      <input type="submit" value="登录"></form>
    </body>
    </html>
    
  2. 创建LoginCheckServlet.java

    package com.hspedu.session.homework;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    /**
     * @ClassName LoginCheckServlet
     * @Description 检测用户名和密码是否正确,正确则跳转到manage页面,错误则返回error.html
     * @Author zephyr
     * @Date 2023/3/13 11:12
     * @Version 1.0
     */
    
    @WebServlet(name = "LoginCheckServlet", value = "/loginCheck")
    public class LoginCheckServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("================LoginCheckServlet 被调用================");
    
            //1. 得到提交的用户名和密码
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            if("666666".equals(password)){// 认为合法
                //给浏览器绑定一个session
                HttpSession session = request.getSession();
                session.setAttribute("loginuser", username);
                //请求转发到ManageServlet
                request.getRequestDispatcher("/manage").forward(request, response);
            } else {
                //请求转发进入到error.html页面
                request.getRequestDispatcher("/error.html").forward(request, response);
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    
  3. ManageServlet.java

    package com.hspedu.session.homework;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    /**
     * @ClassName ManageServlet
     * @Description 管理员页面。通过session,如果已经登录过就可以直接访问,如果没有登陆过则重定向到登录页面。
     * @Author zephyr
     * @Date 2023/3/13 11:15
     * @Version 1.0
     */
    
    @WebServlet(name = "ManageServlet", value = "/manage")
    public class ManageServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("================ManageServlet 被调用================");
    
            //判断该用户是否登陆过
            HttpSession session = request.getSession();
            Object loginuser = session.getAttribute("loginuser");
            if (loginuser == null){
                //重新登陆
                response.sendRedirect(request.getContextPath() + "/userlogin.html");
            } else {
                response.setContentType("text/html;charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.println("<h1>用户管理页面</h1>");
                writer.println("欢迎你,管理员: " + loginuser.toString());
                writer.flush();
                writer.close();
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    

Session有什么用

思考两个问题—抛砖引玉

  1. 不同的用户登录网站后,不管该用户浏览该网站的哪个页面,都可显示登录人的名字, 还可以随时去查看自己的购物车中的商品, 是如何实现的?
  1. 也就是说,一个用户在浏览网站不同页面时,服务器是如何知道是张三在浏览这个页面, 还是李四在浏览这个页面?

解决之道—session 技术

  1. Session 是服务器端技术,服务器在运行时为每一个用户的浏览器创建一个其独享的 session 对象/集合。

  2. 由于 session 为各个用户浏览器独享,所以用户在访问服务器的不同页面时,可以从各自的 session 中读取/添加数据, 从而完成相应任务。

Session基本原理

Sesson 原理示意图

image-20230311125917379

image-20230311125929010

  1. 当用户打开浏览器,访问某个网站, 操作 session 时,服务器就会在内存(在服务端)为该 浏览器分配一个 session 对象,该 session 对象被这个浏览器独占, 如图
  2. 这个 session 对象也可看做是一个容器/集合,session 对象默认存在时间为 30min(这是在tomcat/conf/web.xml),也可修改
    image-20230311131023482
    image-20230311131117583

Session可以做什么

  1. 网上商城中的购物车
  2. 保存登录用户的信息
  3. 将数据放入到 Session 中,供用户在访问不同页面时,实现跨页面访问数据
  4. 防止用户非法登录到某个页面

如何理解Session

  1. session 存储结构示意图
    image-20230311130755315
  2. 你可以把 session 看作是一容器类似 HashMap,有两列(K-V),每一行就是 session 的一个属性。
  3. 每个属性包含有两个部分,一个是该属性的名字(String),另外一个是它的值(Object)

Session常用方法

Session文档

HttpSession (Java™ EE 7 Specification APIs) (oracle.com)

  1. getAttribute(String name) - 获取指定名称的属性值
  2. setAttribute(String name, Object value) - 设置指定名称的属性值
  3. removeAttribute(String name) - 移除指定名称的属性值
  4. getId() - 获取会话ID
  5. getCreationTime() - 获取会话创建时间
  6. getLastAccessedTime() - 获取会话最后访问时间
  7. setMaxInactiveInterval(int interval) - 设置会话的最大不活动时间间隔
  8. getMaxInactiveInterval() - 获取会话的最大不活动时间间隔
  9. invalidate() - 使会话无效
  10. isNew() - 判断会话是否为新创建的

Session基本使用

  1. 创建和获取session, API一样

    HttpSession hs = request.getSession()
    

    image-20230311132419601
    第 1 次调用是创建 Session 会话, 之后调用是获取创建好的 Session 对象

  2. 向session添加属性

    hs.setAttribute(String name,Object val);
    

    image-20230311133251959

  3. 从session获取某个属性

    Object obj=hs.getAttribute(String name);
    

    image-20230311133334589

  4. 从 session 删除调某个属性

    hs.removeAttribute(String name);
    

    image-20230311133148068

  5. 判断是不是刚创建出来的 Session

    hs.isNew();
    

    image-20230311133037443

  6. 获取session的会话ID值

    hs.getId();
    

    image-20230311133444206

session 底层实现机制

原理分析图(一图胜千言)

image-20230311134730119

针对每个会话都有一个Session。

image-20230311134817009

getSession()方法是session创建的核心,极其重要!

它先判断浏览器是否带有jsessionid这个cookie数据:

  1. 如果没有携带:就直接创建session,并且分配一个jsessionidjsessionid和session的管理通过一个Map结构维护;
  2. 如果携带了:
    1. 如果不存在id=jsessionid的对象:就创建session,同时分配id;
    2. 如果存在id=jsessionid的对象:就直接进行操作。

如果服务器在本次会话中创建了session,就返回Set-Cookie:jsessionid=xxx

演示创建session

  1. 需求: 演示 Session 底层实现机制-创建读取 Session

  2. 创建CreateSession.java

    package com.hspedu.session;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    /**
     * @ClassName CreateSession
     * @Description 演示Session的创建
     * @Author zephyr
     * @Date 2023/3/11 14:16
     * @Version 1.0
     */
    
    @WebServlet(name = "CreateSession", value = "/createSession")
    public class CreateSession extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("================CreateSession 被调用================");
    
            //1. 获取session,同时也可能创建session
            HttpSession session = request.getSession();
            //2. 获取sessionId
            System.out.println("当前sessionId = " + session.getId());
            //3. 给session存放数据
            session.setAttribute("email", "zs@qq.com");
    
            //4. 给浏览器发送回复
            response.setContentType("text/html;charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.println("<h1>创建Session成功</h1>");
            writer.flush();
            writer.close();
    
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    
    

    image-20230311144451043

发送请求的时候没有携带JsessionId,服务器收到之后为之创建一个JsessionId

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rJQKggQL-1678685554206)(https://img.jing10.top/uPic/20230311image-20230311144608335.png)]

并且在响应头里返回这个Set-Cookie: JESESSION=xxxxxxx

image-20230311144644024

然后该JsessionId就被存储在了浏览器的Cookie中

image-20230311150014293


现在如果我们再次向客户端发起请求,携带了刚刚的JsessionId,那么客户端就不会再为我们创建的新的session,而是使用与JsessionId对应的session。并且,返回响应时也不会Set-Cookie: JESESSION=xxxxxxx

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hjBNVb0C-1678685554207)(https://img.jing10.top/uPic/20230311image-20230311150513169.png)]

演示读取session

package com.hspedu.session;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @ClassName ReadSession
 * @Description 演示读取session
 * @Author zephyr
 * @Date 2023/3/11 15:10
 * @Version 1.0
 */

@WebServlet(name = "ReadSession", value = "/readSession")
public class ReadSession extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("================ReadSession 被调用================");
        //1. 获取Session,如果没有session也会创建
        HttpSession session = request.getSession();
        //输出sessionId
        System.out.println("sessionId = " + session.getId());
        //2. 读取属性
        Object email = session.getAttribute("email");
        if (email != null){
            System.out.println("session属性 email = " + (String) email);
        } else {
            System.out.println("session没有email属性");
        }
        //给浏览器回回复
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.println("<h1>创建/操作session成功</h1>");
        writer.flush();
        writer.close();
    }

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

image-20230311152040016

image-20230311152058821

image-20230311152021201

Session实现原理动画

服务器是如何实现一个 session 为一个用户浏览器服务的

image-20230311152248702

Session 生命周期

Session 生命周期-说明

  1. public void setMaxInactiveInterval(int interval) 设置 Session 的超时时间(以秒为单位), 超过指定的时长,Session 就会被销毁。
    1. 值为正数的时候,设定 Session 的超时时长。
    2. 负数表示永不超时
  2. public int getMaxInactiveInterval()获取 Session 的超时时间
  3. public void invalidate() 让当前 Session 会话立即无效
  4. 如果没有调用 setMaxInactiveInterval() 来指定 Session 的生命时长,Tomcat 会以 Session 默认时长为准,Session 默认的超时为 30 分钟, 可以在 tomcat 的 web.xml 设置

image-20230311131117583

  1. Session 的生命周期指的是 :客户端/浏览器两次请求最大间隔时长,而不是累积时长。 即当客户端访问了自己的 session,session 的生命周期将从 0 开始重新计算。(解读: 指的是同一个会话两次请求之间的间隔时间)
  2. 底层: Tomcat 用一个线程来轮询会话状态,如果某个会话的空闲时间超过设定的最大值, 则将该会话销毁

Session 生命周期-应用实例

  • 需求:代码演示说明Session的生命周期

createSession2.java

package com.hspedu.session;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @ClassName CreateSession2
 * @Description TODO
 * @Author zephyr
 * @Date 2023/3/11 15:35
 * @Version 1.0
 */

@WebServlet(name = "CreateSession2", value = "/createSession2")
public class CreateSession2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("================CreateSession2 被调用================");

        //获取Session,如果没有session也会创建
        HttpSession session = request.getSession();
        //输出session的id
        System.out.println("sessionId = " + session.getId());
        //设置生命周期为60s
        session.setMaxInactiveInterval(60);
        //设置两个属性
        session.setAttribute("u", "zephyr666");

        //给浏览器发送回复
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.println("<h1>创建session成功,生命周期60s</h1>");
        writer.flush();
        writer.close();

    }

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

ReadSession2.java

package com.hspedu.session;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Time;

/**
 * @ClassName ReadSession2
 * @Description TODO
 * @Author zephyr
 * @Date 2023/3/11 15:37
 * @Version 1.0
 */

@WebServlet(name = "ReadSession2", value = "/readSession2")
public class ReadSession2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("================ReadSession2 被调用================");
        //获取Session
        HttpSession session = request.getSession();
        //输出session的id
        System.out.println("sessionId = " + session.getId());
        //获取session的属性
        Object u = session.getAttribute("u");
        if (u != null){
            System.out.println("u = " + u);
        } else {
            System.out.println("读取不到session属性u");
        }

        //给浏览器回回复
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.println("<h1>读取session成功</h1>");
        writer.flush();
        writer.close();
    }

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

image-20230311155110040

解读:Session 的生命周期

  1. 指的是两次访问 session 的最大间隔时间
  2. 如果你在 session 没有过期的情况下,操作 session, 则会重新开始计算生命周期
  3. session 是否过期,是由服务器来维护和管理
  4. 如我们调用了 invaliate() 会直接将该 session 删除/销毁
  5. 如果希望删除 session 对象的某个属性, 使用 removeAttribute("xx")

DeleteSession.java

package com.hspedu.session;

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

/**
 * @ClassName DeleteSession
 * @Description TODO
 * @Author zephyr
 * @Date 2023/3/11 17:26
 * @Version 1.0
 */

@WebServlet(name = "DeleteSession", value = "/DeleteSession")
public class DeleteSession extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        // 让 Session 会话立即超时
        session.invalidate();

        response.setContentType("text/html;charset=utf-8"); // 先获取 Session 对象
        response.getWriter().write("Session 已经设置为超时");
    }

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

Session 经典案例-防止非法进入管理页面

作业布置

  • 需求说明: 完成防止用户登录管理页面应用案例(如图)
    image-20230312000247733

  • 说明:

    • 只要密码为 666666, 我们认为就是登录成功
    • 用户名不限制
    • 如果验证成功,则进入管理页面 ManageServelt.java ,否则进入 error.html
    • 如果用户直接访问 ManageServet.java , 重定向到到 userlogin.html

作用讲评

  1. 创建userlogin.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>用户登录</title></head>
    <body>
    <h1>用户登录</h1>
    <form action="/cs/loginCheck"
          method="post">
      用户名:<input type="text" name="username"/><br/><br/>
      密 码:<input type="password" name="password"><br><br/>
      <input type="submit" value="登录"></form>
    </body>
    </html>
    
  2. 创建LoginCheckServlet.java

    package com.hspedu.session.homework;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    /**
     * @ClassName LoginCheckServlet
     * @Description 检测用户名和密码是否正确,正确则跳转到manage页面,错误则返回error.html
     * @Author zephyr
     * @Date 2023/3/13 11:12
     * @Version 1.0
     */
    
    @WebServlet(name = "LoginCheckServlet", value = "/loginCheck")
    public class LoginCheckServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("================LoginCheckServlet 被调用================");
    
            //1. 得到提交的用户名和密码
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            if("666666".equals(password)){// 认为合法
                //给浏览器绑定一个session
                HttpSession session = request.getSession();
                session.setAttribute("loginuser", username);
                //请求转发到ManageServlet
                request.getRequestDispatcher("/manage").forward(request, response);
            } else {
                //请求转发进入到error.html页面
                request.getRequestDispatcher("/error.html").forward(request, response);
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    
  3. ManageServlet.java

    package com.hspedu.session.homework;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    /**
     * @ClassName ManageServlet
     * @Description 管理员页面。通过session,如果已经登录过就可以直接访问,如果没有登陆过则重定向到登录页面。
     * @Author zephyr
     * @Date 2023/3/13 11:15
     * @Version 1.0
     */
    
    @WebServlet(name = "ManageServlet", value = "/manage")
    public class ManageServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("================ManageServlet 被调用================");
    
            //判断该用户是否登陆过
            HttpSession session = request.getSession();
            Object loginuser = session.getAttribute("loginuser");
            if (loginuser == null){
                //重新登陆
                response.sendRedirect(request.getContextPath() + "/userlogin.html");
            } else {
                response.setContentType("text/html;charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.println("<h1>用户管理页面</h1>");
                writer.println("欢迎你,管理员: " + loginuser.toString());
                writer.flush();
                writer.close();
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 对于JavaWeb Vscode酒店系统页面代码的实现,我将按照以下步骤进行解答: 首先,我们需要在Vscode中创建一个JavaWeb项目,并导入所需的相关库文件。接下来,在项目的WebContent文件夹下,创建对应酒店系统的页面文件,如首页、登录页面、注册页面、房间列表页面等。 在首页页面中,我们可以通过HTML和CSS来编写页面布局和样式,包括导航栏、轮播图、推荐房间等内容。此外,我们还可以通过JavaScript和AJAX实现动态效果和部分交互功能,如搜索框的自动提示、房间列表的滚动加载等。 登录页面和注册页面可以采用类似的方式进行实现,通过HTML和CSS编写页面布局和样式,包括表单、按钮等元素。在后台,我们可以使用Java编写相应的Servlet来处理登录和注册的逻辑,如验证用户输入的账号和密码是否正确、将新用户的信息保存到数据库等。 房间列表页面可以通过HTML和CSS实现房间的展示和筛选功能,如按价格、地点、房型等条件进行筛选。我们可以使用JSP来动态生成房间列表的内容,并通过调用JavaBean来获取数据库中的房间信息。 在编写这些页面的同时,我们还需要编写相应的Java代码来处理页面的请求和响应,如通过Servlet进行用户登录和注册的逻辑处理。此外,还需要与后台数据库进行交互,如查询房间信息、插入用户信息等。 最后,我们可以使用Vscode提供的Tomcat插件将项目部署到本地服务器上进行测试。通过访问对应的URL,我们可以查看到所编写的酒店系统页面,并验证它们的功能和交互效果是否符合预期。 总的来说,实现JavaWeb Vscode酒店系统页面代码需要综合运用HTML、CSS、JavaScript、JSP和Java等技术,并与后台数据库进行交互,同时结合Vscode的开发环境进行代码编写和调试。这样能够提供用户友好的页面界面,并实现相应的业务逻辑。 ### 回答2: 酒店系统是一个较为复杂的系统,涉及到多个页面的设计与开发。在使用JavaWeb和VSCode进行开发的过程中,需要遵循一定的规范和流程。 首先,在VSCode中创建一个JavaWeb项目,可以使用Maven进行项目的管理。在项目目录下创建一个名为"HotelSystem"的文件夹用于存放所有相关代码。 接着,在"HotelSystem"文件夹下创建一个名为"WEB-INF"的文件夹,用于存放页面的JSP文件以及与之相关的资源文件,如图片、CSS样式文件等。 在"WEB-INF"文件夹下,创建一个名为"views"的子文件夹,用于存放各个页面的JSP文件。比如,可以创建一个名为"index.jsp"的文件作为系统的首页,还可以创建"login.jsp"作为用户登录页面,"booking.jsp"作为房间预订页面等等。每个JSP文件都需要编写对应的HTML结构和相关的Java代码,以实现页面的功能和交互。 在"WEB-INF"文件夹下,还需要创建一个名为"servlet"的子文件夹,用于存放各个页面的Servlet文件。Servlet文件负责接收来自页面的请求,并对请求进行处理和响应。比如,可以创建一个名为"LoginServlet.java"的文件用于处理用户登录请求,还可以创建"BookingServlet.java"用于处理房间预订请求等等。 在"WEB-INF"文件夹下,还应该创建一个名为"lib"的子文件夹,用于存放相关的Java类库文件。这些类库文件是项目中所需要的一些依赖,可以通过Maven进行管理和导入。 除了上述文件夹之外,还需要在项目的根目录下创建一个名为"WEB-INF"的文件夹用于存放系统的配置文件,比如数据库配置文件、日志配置文件等。 总而言之,酒店系统的页面代码主要包含了JSP文件和Servlet文件,需要按照一定的规范进行组织和开发。这些页面代码需要与后台的Java代码进行交互,实现系统的功能和逻辑。在使用JavaWeb和VSCode进行开发时,我们需要遵循一定的开发流程,保持代码的可读性和可维护性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值