【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 ID
或 JSESSIONID
。这个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
对象的数据存储在服务器端,如果长时间不进行清理,确实会导致内存占用增加,进而可能引发性能问题甚至服务器崩溃。
程序主动清除会话数据:开发者可以通过编程方式主动清除会话中的数据或整个会话。这通常在用户执行某些操作时进行,例如注销登录。
-
移除单个属性
HttpSession session = request.getSession(); session.removeAttribute("username");
-
使会话失效
HttpSession session = request.getSession(); session.invalidate(); // 这将使整个会话失效,并释放所有与该会话相关的资源
-
注销处理示例
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"); }
服务器主动清除长时间没有再次发出请求的会话:服务器可以通过配置自动清除长时间没有活动的会话。这通常通过设置会话的超时时间来实现。
-
在代码中设置会话超时时间:
HttpSession session = request.getSession(); session.setMaxInactiveInterval(30 * 60); // 设置会话超时时间为30分钟
-
在
web.xml
中配置默认的会话超时时间:<session-config> <session-timeout>30</session-timeout> <!-- 单位为分钟 --> </session-config>
-
检查会话是否新创建:
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");
}
}
}
request
、session
和 application
都提供了存储属性的功能,但它们的作用范围和生命周期不同。
相同点
一、都可以存储属性:这三个对象都可以用来存储键值对形式的数据(即属性),这些数据可以是任何类型,只要它实现了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)!