自学内容网 自学内容网

【Java Web】JSP实现数据传递和保存(下)四大作用域 Cookie

四大作用域

四个主要的作用域(Scope),它们分别用于不同的场景来存储数据:

Page Scope:页面作用域。作用域最小,仅限于当前JSP页面内有效,当页面执行完毕后,该作用域内的数据就会被销毁。

Request Scope:请求作用域。数据在一次请求中有效,即从客户端发出请求到服务器处理完这个请求并返回响应之前,数据都是有效的。

Session Scope:会话作用域。数据在整个会话期间有效,即从用户打开浏览器与服务器建立连接开始,直到用户关闭浏览器断开连接为止。

Application Scope:应用作用域。作用域最大,数据在整个Web应用运行期间都有效,直到服务器重启或应用被卸载。

pageContext

// 存入值
pageContext.setAttribute("name","张三");
// 获取值
String name = pageContext.getAttribute("name").toString();

// servlet 获取 pageContext
PageContext pageContext = JspFactory.getDefaultFactory().getPageContext(this, request, response, null, true, 8192, true);

request

// 存入值
request.setAttribute("name","张三");
// 获取值
String name = request.getAttribute("name").toString();

session

session 通常指的是用户与Web应用之间的交互会话。

会话是一个抽象的概念,指代用户从开始访问网站到离开网站的整个过程。在这段时间内,用户可能执行多个请求,服务器需要记住用户的某些状态信息。

HttpSession 是 Java Servlet API 提供的一个接口,它提供了一种机制来创建和维护会话状态。通过 HttpSession 接口,开发者可以在服务器端存储关于用户会话的数据,并在多个请求之间共享这些数据。

public void setAttribute(String name, Object value);

  • 将一个对象绑定到当前会话,并用给定的名字标识它。
HttpSession session = request.getSession();
session.setAttribute("username", "john.doe");

public Object getAttribute(String name);

  • 根据指定的名字从会话中获取对象。
String username = (String) session.getAttribute("username");

public void removeAttribute(String name);

  • 从当前会话中删除指定名称的对象。
session.removeAttribute("name"); // 清空session中name键中的值

public void setMaxInactiveInterval(int interval)

  • 设置会话的最长非活动时间间隔(以秒为单位)。如果超过这个时间没有访问,会话将被失效。
session.setMaxInactiveInterval(60); // 设置60秒非活动时间后清除session中的值

public void invalidate()

  • 使当前会话失效。这会立即删除所有与该会话相关的数据,并使会话ID无效。
session.invalidate(); // 设置所有session失效

工作方式

每个 HttpSession 对象都有一个唯一的标识符,称为 session IDJSESSIONID。这个ID用于在客户端和服务器之间唯一地标识一个会话。getId() 方法是 HttpSession 接口中的一个方法,用来获取当前会话的ID。

public String getId();

  • 功能:返回当前会话的唯一标识符(session ID)。
  • 返回值:一个字符串,表示会话的唯一ID。

使用 getId() 方法来获取会话ID的示例

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 获取当前会话
    HttpSession session = request.getSession();

    if (session != null) {
        // 获取会话ID
        String sessionId = session.getId();
        System.out.println("Current Session ID: " + sessionId);

        // 可以将session ID发送到客户端,例如通过响应头或作为页面内容的一部分
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h1>Session Information</h1>");
        out.println("<p>Session ID: " + sessionId + "</p>");
        out.println("</body></html>");
    } else {
        response.sendRedirect("login.jsp?error=no_session");
    }
}

会话清除

HttpSession 对象的数据存储在服务器端,如果长时间不进行清理,确实会导致内存占用增加,进而可能引发性能问题甚至服务器崩溃。

程序主动清除会话数据:开发者可以通过编程方式主动清除会话中的数据或整个会话。这通常在用户执行某些操作时进行,例如注销登录。

  1. 移除单个属性

    HttpSession session = request.getSession();
    session.removeAttribute("username");
    
  2. 使会话失效

    HttpSession session = request.getSession();
    session.invalidate(); // 这将使整个会话失效,并释放所有与该会话相关的资源
    
  3. 注销处理示例

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession(false); // 不创建新的会话
        if (session != null) {
            session.invalidate(); // 使会话失效
        }
        response.sendRedirect("login.jsp?message=logged_out");
    }
    

服务器主动清除长时间没有再次发出请求的会话:服务器可以通过配置自动清除长时间没有活动的会话。这通常通过设置会话的超时时间来实现。

  1. 在代码中设置会话超时时间

    HttpSession session = request.getSession();
    session.setMaxInactiveInterval(30 * 60); // 设置会话超时时间为30分钟
    
  2. web.xml 中配置默认的会话超时时间

    <session-config>
        <session-timeout>30</session-timeout> <!-- 单位为分钟 -->
    </session-config>
    
  3. 检查会话是否新创建

    HttpSession session = request.getSession();
    if (session.isNew()) {
        // 会话是新创建的
    } else {
        // 会话已经存在
    }
    

application

application对象(也称为ServletContext)是一个全局的上下文对象,它在整个Web应用中是唯一的,并且可以在所有用户之间共享。这意味着使用application对象存储的数据可以被同一个Web应用中的所有Servlet访问。

使用application对象实现计数器,统计整个网站的访问次数的示例代码

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class VisitCounterServlet extends HttpServlet {
    private static final String COUNTER_KEY = "visitCount";
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取application对象
        ServletContext application = getServletContext();
        // 从application中获取计数器
        Integer count = (Integer) application.getAttribute(COUNTER_KEY);
        // 如果计数器不存在,则初始化为0
        if (count == null) {
            count = 0;
        }
        // 计数器加1
        count++;
        // 将更新后的计数器设置回application
        application.setAttribute(COUNTER_KEY, count);
        // 可以将计数显示给用户
        response.getWriter().println("Total visits: " + count);
    }
}

Cookie

当浏览器关闭时,通常情况下会话(session)数据会被清除,因为会话通常是存储在服务器端,并且与用户的浏览器保持连接。但是,如果用户再次进入某个论坛并且状态为已登录,这可能是因为该网站使用了持久化 Cookie 来记住用户的登录状态。

持久化 Cookie 是一种存储在用户计算机上的小文件,它包含了一些信息,比如用户ID等,用于识别用户身份。当用户第一次成功登录后,服务器可以发送一个带有长期有效时间的 Cookie 到用户的浏览器。即使用户关闭了浏览器,这个 Cookie 仍然保存在用户的电脑上。当下次用户访问该网站时,浏览器会自动将这个 Cookie 发回给服务器,服务器通过读取 Cookie 中的信息识别出这是之前已经登录过的用户,并自动恢复其登录状态。

Cookie 操作

// 添加数据
public void addCookie(Cookie cookie)

向响应中添加一个新的 Cookie 对象,当响应被发送到客户端时,Cookie也会被发送过去,并由浏览器存储。

// 获取数据
public Cookie[] getCookies()

从请求中获取所有与当前请求相关的Cookie数组。

// 设置 Cookie 有效期
public void setMaxAge(int expiry)

expiry:时间长度单位,秒。

  • 正数,从现在开始计算的有效期;
  • 0,删除Cookie;
  • 负数,该Cookie仅在浏览器会话期间有效,一旦关闭浏览器,Cookie就会被删除。

用户可以通过浏览器设置来选择是否接受Cookie。如果用户禁用了Cookie,那么依赖于Cookie的功能(如自动登录、记住用户名等)将无法正常工作。

使用 Cookie 来存储和读取用户信息

设置 Cookie

// 对中文进行编码,防止乱码
username = URLEncoder.encode(username, "utf-8");
// 创建Cookie对象
Cookie cookie = new Cookie("username", username);
// 设置Cookie的有效路径,使整个应用都能访问到这个Cookie
cookie.setPath("/");
// 设置Cookie的生命周期,单位为秒,这里设置为1小时
cookie.setMaxAge(60 * 60);
// 将Cookie添加到响应中
response.addCookie(cookie);

获取 Cookie

// 获取请求中所有的Cookie
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length != 0) {
    // 遍历所有的Cookie,找到名为username的Cookie
    for (int i = 0; i < cookies.length; i++) {
        System.out.println(cookies[i].getName());
        if (cookies[i].getName().equals("username")) {
            username = cookies[i].getValue();
            // 对Cookie的值进行解码,恢复原始的中文字符
            username = URLDecoder.decode(username, "utf-8");
        }
    }
}

requestsessionapplication 都提供了存储属性的功能,但它们的作用范围和生命周期不同。

相同点

一、都可以存储属性:这三个对象都可以用来存储键值对形式的数据(即属性),这些数据可以是任何类型,只要它实现了Serializable接口或者是一个基本数据类型。

二、提供相似的方法来操作属性:对于每个对象,都有类似的方法来设置、获取、删除属性等,比如:

  • 设置属性: setAttribute(String name, Object value)
  • 获取属性: getAttribute(String name)
  • 删除属性: removeAttribute(String name)

不同点

一、请求范围 (Request Scope) - request:

  • 存储的数据仅在一个HTTP请求期间有效。

当服务器处理完一个请求后,该请求相关的request对象就会被销毁,其中的数据也会随之消失。主要用于在一个请求内部传递信息,例如从一个Servlet到另一个Servlet或JSP页面。

在这里插入图片描述

二、会话范围 (Session Scope) - session:

  • 存储的数据在一个用户的会话期间内有效。

用户访问网站时,服务器为用户创建一个会话(通常是通过Cookie实现的)。只要会话没有过期(默认情况下可能为30分钟不活动时间)或被显式地使无效,会话中的数据就可以一直存在。适合存放一些需要在整个会话周期内保持一致性的数据,如登录状态、购物车内容等。

在这里插入图片描述

三、应用范围 (Application Scope) - application:

  • 存储的数据在整个Web应用运行期间都有效,并且可以在所有用户之间共享。

一旦Web应用部署并启动,application对象就被创建;直到应用关闭或重新部署,这个对象才会被销毁。适用于存放全局配置信息、应用程序级别的统计数据等,需要注意线程安全问题,因为多用户可能会同时访问和修改同一个数据。

在这里插入图片描述

升级示例2

美化登录界面,加入记住密码选项,获取 Cookie

<body>
    <%
        String uname = "";
        String upwd = "";
        boolean jzpwd = false;
        // 获取请求中所有的Cookie
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length != 0) {
            // 遍历所有的Cookie,找到名为username的Cookie
            for (int i = 0; i < cookies.length; i++) {
                if ("uname".equals(cookies[i].getName())) {
                    uname = URLDecoder.decode(cookies[i].getValue(), "utf-8");
                }
                if ("upwd".equals(cookies[i].getName())) {
                    upwd = cookies[i].getValue();
                }
                if ("jzpwd".equals(cookies[i].getName()) && "on".equals(cookies[i].getValue())) {
                    jzpwd = true;
                }
            }
        }
    %>


    <div class="login-form">
        <h2>欢迎登录</h2>
        <form action="dologin.jsp" method="post">
            <input type="text" name="uname" placeholder="账号" value="<%=uname%>"/><br/>
            <input type="password" name="upwd" placeholder="密码" value="<%=upwd%>"/><br/>
            <label>
                <input type="checkbox" name="jzpwd" value="on" <%= jzpwd ? "checked" : "" %>/>记住密码
            </label><br/><br/>
            <button type="submit">登录</button>
        </form>
    </div>
</body>

若登录成功,判断用户是否选择了“记住密码”,是则将保存到 Cookie 中,否则删除相关的 Cookie

<%
    request.setCharacterEncoding("utf-8");
    // 接收参数
    String uname = request.getParameter("uname");
    String upwd = request.getParameter("upwd");
    boolean jzpwd = "on".equals(request.getParameter("jzpwd"));

    // 调用 Java 方法 登录
    SmbmsUserDao smbmsUserDao = new SmbmsUserDaoImpl();
    SmbmsUser smbmsUser =  smbmsUserDao.login(uname,upwd);

    // 判断登录是否成功
    if (smbmsUser != null) {
        // session 存储登录信息
        session.setAttribute("smbmsUser",smbmsUser);
        Cookie cookieUname = null;
        Cookie cookieUpwd = null;
        Cookie cookieJzpwd = null;
        // 如果用户选择了“记住密码”,则将保存到Cookie中
        if (jzpwd) {
            cookieUname = new Cookie("uname", URLEncoder.encode(uname, "UTF-8"));
            cookieUpwd = new Cookie("upwd", upwd);
            cookieJzpwd = new Cookie("jzpwd", "on");

            // 设置Cookie的有效期为5小时
            cookieUname.setMaxAge(60 * 60 * 5);
            cookieUpwd.setMaxAge(60 * 60 * 5);
            cookieJzpwd.setMaxAge(60 * 60 * 5);

            // 将Cookie添加到响应中
            response.addCookie(cookieUname);
            response.addCookie(cookieUpwd);
            response.addCookie(cookieJzpwd);
        } else {
            // 如果用户没有选择“记住密码”,则删除相关的Cookie
            cookieUname = new Cookie("uname", "");
            cookieUpwd = new Cookie("upwd", "");
            cookieJzpwd = new Cookie("jzpwd", "");

            // 设置Cookie的有效期为0,表示立即过期
            cookieUname.setMaxAge(0);
            cookieUpwd.setMaxAge(0);
            cookieJzpwd.setMaxAge(0);

            // 将Cookie添加到响应中
            response.addCookie(cookieUname);
            response.addCookie(cookieUpwd);
            response.addCookie(cookieJzpwd);
        }
        // 转发
        request.getRequestDispatcher("/doindex.jsp").forward(request,response);
        // 重定向
        // response.sendRedirect("/doindex.jsp");
    } else {
        // 登录失败则重定向回登录界面
        response.sendRedirect("/login.jsp");
    }
%>

doindex.jsp 中间处理页面不变,index.jsp 修改如下:改用 session 存储和获取登录用户信息;添加安全退出功能。

<%
    // session.getAttribute 获取登录信息
    SmbmsUser smbmsUser =  (SmbmsUser)session.getAttribute("smbmsUser");
    // getAttribute 获取供应商信息
    List<SmbmsProvider> smbmsProviderList =  (List<SmbmsProvider>)request.getAttribute("providerList");
%>
<h1>
    <%=smbmsUser.getUserName()%>
    欢迎您登录 供应商信管理系统!!!
</h1>
<form action="logout.jsp" method="get">
    <input type="submit" value="安全退出"/>
</form>
<table>
    <tr>
        <th>ID</th>
        <th>proCode</th>
        <th>proName</th>
        <th>proDesc</th>
    </tr>
    <% for(SmbmsProvider smbmsProvider : smbmsProviderList){ %>
    <tr>
        <td><%= smbmsProvider.getId()%></td>
        <td><%= smbmsProvider.getProCode()%></td>
        <td><%= smbmsProvider.getProName()%></td>
        <td><%= smbmsProvider.getProDesc()%></td>
    </tr>
    <% } %>
</table>

logout.jsp 页面清除所有 session 并重定向回首页

<%
    // 清除所有 session
    session.invalidate();
    // 重定向回首页
    response.sendRedirect("/login.jsp");
%>

原文地址:https://blog.csdn.net/m0_66584716/article/details/143599394

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!