1.session是什么
- session是服务端为每个用户创建的session对象,在会话期间(可以有多个请求和响应)可以共享存放在session中的数据。
- 服务端为每个用户创建不同的session对象,使用SessionID来区分不同的客户,session对象在页面之间共享其存储的数据。
- 一个session的建立是从一个用户向服务器发第一个请求开始,而以用户显式结束或session超时为结束。
- session是HttpSession接口的一个实例。
2.session是如何创建的
当用户发起第一次请求时,服务器自动创建session,并为其创建一个唯一的sessionid,在随后用户与服务器端的多次请求或响应的过程中都使用这个sessionid标识该用户。
3.session是如何维持的
服务端通过三种方式维持session会话
3.1 指定一个唯一的sessionID作为cookie来代表每个客户端,用来识别这个客户端接下来的请求。优点:简单方便,
在谷歌浏览器中可以查看所有cookie的存放地址和内容
只要不关闭浏览器,服务端的SESSIONID与客户端的JSESSIONID这个键值对就是一样的,服务端就以此来识别是否是同一个用户。
3.2发送一个隐藏的HTML表单域和一个唯一的session ID。
<input type="hidden" name="sessionid" value="B9A55B6DF01250337F52425C13BDA2FC">
3.3(url重写)在每个URL后面添加一些额外的数据来区分会话,服务器能够根据这些数据来关联session标识符。
http://localhost:8080/index.jsp;jsessionid=5AC6268DD8D4D5D1FDF5D41E9F2FD960?param=3&a=1。
注意:url后面的;jsessionid用分号来分隔的。
URL重写功能,为了防止一些用户把Cookie禁止而无法使用session而设置的功能.jsessionid后面的一长串就是你服务器上的session的ID号,这样无需cookie也可以使用session.
4.session是如何删除的(会话结束)
- 程序调用HttpSession.invalidate()
- 客户端距离上一次收到sessionid的时间间隔超过了session的最大有效时间
- 服务器进程被停止
简单例子1——用户登录
Login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户登录界面</title>
</head>
<body>
<h2>用户登录</h2>
<form action="CheckLogin.jsp" method="post">
<table>
<tr>
<td>用户名:</td><td><input type="text" name="username" value="<%=request.getSession().getAttribute("uname") %>"></td>
</tr>
<tr>
<td>密码:</td><td><input type="text" name="password" value="<%=request.getSession().getAttribute("upwd") %>"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交"></td></td>
</tr>
</table>
</form>
<%="sessionID:"+request.getSession().getId() %><br>
<%="session对象被创建的时间:"+(new Date(request.getSession().getCreationTime())).toString() %><br>
<%="session失效时间:"+request.getSession().getMaxInactiveInterval() %><br>
<%="当前用户:"+request.getSession().getAttribute("uname") %><br>
<%="最后访问时间"+(new Date(request.getSession().getLastAccessedTime())).toString() %>
</body>
</html>
CheckLogin.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录验证</title>
</head>
<body>
<%
//设置编码方式
request.setCharacterEncoding("utf-8");
//获得登录的用户名和密码
String username=request.getParameter("username");
String password=request.getParameter("password");
if(username.equals("admin")&&password.equals("123"))
{
//验证通过,创建session对象
session.setAttribute("uname",username);
session.setAttribute("upwd",password);
//获得sessionID,并将session在控制台输出
System.out.println("sessionID:"+session.getId());
response.sendRedirect("Main.jsp");
}else{
response.sendRedirect("Login.jsp");
}
%>
</body>
</html>
Main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>欢迎登录</title>
</head>
<body>
欢迎您:
<%
String name=(String)session.getAttribute("uname");
if(name==null){
response.sendRedirect("Login.jsp");
}else {
out.println(name);
}
%>
<a href="LoginOut.jsp">注销</a><br>
<%="sessionID:"+request.getSession().getId() %><br>
</body>
</html>
LoginOut.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>注销处理</title> </head> <body> <% session.invalidate();//session失效 response.sendRedirect("Login.jsp"); //session.removeAttribute("uname");//移除指定的属性 %> </body> </html>
第一次访问的时候就可以获取Sessionid,在Login.jsp页面显示,与是否登录成功无关
输入用户名和密码登录成功后跳转到CheckLogin.jsp页面,此时控制台打印的sessionid与Login.jsp页面是一样的。也就是说同一个用户,session创建后,多次请求和响应时传送的sesssid都是一样的。
重定向到Main.jsp页面
登录成功后,后退到Login.jsp页面,两个文本框默认显示session保存的用户名和密码。
回到Main.jsp页面点击注销连接,手动在代码中清除session,清除后跳转回Login.jsp页面
清除原来的session以后,重新向服务器发出请求,此时的sessionid已经是服务端重新生成的了。
简单例子2——实现简单购物车功能
Buy.jsp 商品浏览页,通过勾选商品前的复选框选中商品,在数量的文本框中输入购买数量。
Processbuy.jsp 购物车商品使用Map<String,Integer>结构存储,并存入session域对象。
Show.jsp 提取session域对象中的值,并在页面显示。
Buy.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>商品列表</title> </head> <body> <h2 align="center">商品列表</h2> <div align="center"> <form action="Processbuy.jsp" method="post"> <table border="0" cellspacing="10"> <tr> <th>商品名称</th> <th>购买</th> <th>价格</th> <th>数量</th> </tr> <tr> <td>笔记本</td> <td><input type="checkbox" name="item" value="computer"></td> <td>¥5000</td> <td><input type="text" name="comnum" value="1" style=" 25px"></td> </tr> <tr> <td>汽车</td> <td><input type="checkbox" name="item" value="car"></td> <td>¥200000</td> <td><input type="text" name="carnum" value="1" style=" 25px"></td> </tr> <tr> <td>香水</td> <td><input type="checkbox" name="item" value="flower"></td> <td>¥500</td> <td><input type="text" name="fnum" value="1" style=" 25px"></td> </tr> <tr> <td>书籍</td> <td><input type="checkbox" name="item" value="book"></td> <td>¥20</td> <td><input type="text" name="bnum" value="1" style=" 25px"></td> </tr> </table> <input type="submit" value="购买"> </form> </div> </body> </html>
Processbuy.jsp
<%@page import="java.util.HashMap"%> <%@page import="java.util.Map"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <% String path = request.getContextPath()+"/ShoppingCart"; String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; String url = basePath+"Buy.jsp"; %> <% request.setCharacterEncoding("utf-8"); Map<String,Integer> map1 =(Map<String,Integer>)session.getAttribute("map1"); if(map1 == null){ map1 = new HashMap<String, Integer>(); map1.put("笔记本", 0); map1.put("汽车", 0); map1.put("香水", 0); map1.put("书籍", 0); } String[] buys = request.getParameterValues("item"); //判断是否勾选了复选框 if(buys==null) { out.print("请勾选商品信息!"); //实现页面自动跳转 response.addHeader("Refresh","2;URL="+url); return; } for(String item:buys) { if(item.equals("computer")) { int num1 = map1.get("笔记本").intValue(); int comnum = Integer.parseInt(request.getParameter("comnum")); map1.put("笔记本",num1+comnum); } else if(item.equals("car")) { int num1 = map1.get("汽车").intValue(); int carnum = Integer.parseInt(request.getParameter("carnum")); map1.put("汽车",num1+carnum); } else if(item.equals("flower")) { int num1 = map1.get("香水").intValue(); int fnum = Integer.parseInt(request.getParameter("fnum")); map1.put("香水",num1+fnum); } else { int num1 = map1.get("书籍").intValue(); int bnum = Integer.parseInt(request.getParameter("bnum")); map1.put("书籍",num1+bnum); } } session.setAttribute("map1", map1); request.getRequestDispatcher("Show.jsp").forward(request, response); %> </body> </html>
Show.jsp
<%@page import="java.util.Map"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>商品结算</title> </head> <body> <h2>结算</h2> <% Map<String,Integer> map1 = (Map<String,Integer>)session.getAttribute("map1"); %> <table border="0" cellspacing="30"> <tr> <th>商品名称</th> <th>数量</th> <th>总价</th> </tr> <tr> <td>笔记本</td> <td><%=map1.get("笔记本") %></td> <td><%=map1.get("笔记本") %>*5000</td> </tr> <tr> <td>汽车</td> <td><%=map1.get("汽车")%></td> <td><%=map1.get("汽车")%>*200000</td> </tr> <tr> <td>香水</td> <td><%=map1.get("香水")%></td> <td><%=map1.get("香水")%>*500</td> </tr> <tr> <td>书籍</td> <td><%=map1.get("书籍") %></td> <td><%=map1.get("书籍") %>*20</td> </tr> </table> <p>总金额:<%=map1.get("笔记本")*5000+map1.get("汽车")*200000+map1.get("香水")*500+map1.get("书籍")*20 %></p> <p><a href="Buy.jsp">继续购买</a></p> </body> </html>
运行截图:
选中商品,点击购买,结算如下显示:
点击继续购买,保留之前购买的数量,合并结算:
参考文章:
https://www.runoob.com/jsp/jsp-session.html
https://www.cnblogs.com/shenbing/p/5372717.html
https://www.cnblogs.com/zhaoYuQing-java2015/p/4621384.html
https://www.cnblogs.com/ym77/p/11323742.html
https://blog.csdn.net/collonn/article/details/5698906
https://blog.csdn.net/qq_35756383/article/details/81632119