java中session的用法与原理

article/2025/6/30 0:14:08

https://www.cnblogs.com/xdp-gacl/p/3855702.html

session简介

在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。

session实现原理

当服务器创建完session对象后,会把session对象的id以cookie形式返回给客户端。这样,当用户保持当前浏览器的情况下再去访问服务器时,会把session的id传给服务器,服务器根据session的id来为用户提供相应的服务。这里给出了一个实现案例:

package xdp.gacl.session;import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class SessionDemo1 extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setCharacterEncoding("UTF=8");response.setContentType("text/html;charset=UTF-8");//使用request对象的getSession()获取session,如果session不存在则创建一个HttpSession session = request.getSession();//将数据存储到session中session.setAttribute("data", "孤傲苍狼");//获取session的IdString sessionId = session.getId();//判断session是不是新创建的if (session.isNew()) {response.getWriter().print("session创建成功,session的id是:"+sessionId);}else {response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId);}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}
}

第一次访问时,服务器会创建一个新的sesion,并且把session的Id以cookie的形式发送给客户端浏览器,如下图所示:
在这里插入图片描述
点击刷新按钮,再次请求服务器,此时就可以看到浏览器再请求服务器时,会把存储到cookie中的session的Id一起传递到服务器端了,如下图所示:
在这里插入图片描述
这里,当服务端调用request.getSession()时,如果session是新建的,可能内部做了如下处理:

//获取session的Id
String sessionId = session.getId();
//将session的Id存储到名字为JSESSIONID的cookie中
Cookie cookie = new Cookie("JSESSIONID", sessionId);
//设置cookie的有效路径
cookie.setPath(request.getContextPath());
response.addCookie(cookie);

禁用cookie后session处理

  1. IE8禁用cookie步骤
    工具->internet选项->隐私->设置->将滑轴拉到最顶上(阻止所有cookies)
    在这里插入图片描述在这里插入图片描述

  2. 解决方案:URL重写

response.encodeRedirectURL(java.lang.String url) 用于对sendRedirect方法后的url地址进行重写。
response.encodeURL(java.lang.String url)用于对表单action和超链接的url地址进行重写
  1. 禁用cookie后实现session的数据共享案例

IndexServlet

package xdp.gacl.session;import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;//首页:列出所有书
public class IndexServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();//创建Sessionrequest.getSession();out.write("本网站有如下书:<br/>");Set<Map.Entry<String,Book>> set = DB.getAll().entrySet();for(Map.Entry<String,Book> me : set){Book book = me.getValue();String url =request.getContextPath()+ "/servlet/BuyServlet?id=" + book.getId();//response. encodeURL(java.lang.String url)用于对表单action和超链接的url地址进行重写url = response.encodeURL(url);//将超链接的url地址进行重写out.println(book.getName()  + "   <a href='"+url+"'>购买</a><br/>");}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}
}/*** @author gacl* 模拟数据库*/
class DB{private static Map<String,Book> map = new LinkedHashMap<String,Book>();static{map.put("1", new Book("1","javaweb开发"));map.put("2", new Book("2","spring开发"));map.put("3", new Book("3","hibernate开发"));map.put("4", new Book("4","struts开发"));map.put("5", new Book("5","ajax开发"));}public static Map<String,Book> getAll(){return map;}
}class Book{private String id;private String name;public Book() {super();}public Book(String id, String name) {super();this.id = id;this.name = name;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

BuyServlet

package xdp.gacl.session;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class BuyServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String id = request.getParameter("id");Book book = DB.getAll().get(id);  //得到用户想买的书HttpSession session = request.getSession();List<Book> list = (List) session.getAttribute("list");  //得到用户用于保存所有书的容器if(list==null){list = new ArrayList<Book>();session.setAttribute("list", list);}list.add(book);//response. encodeRedirectURL(java.lang.String url)用于对sendRedirect方法后的url地址进行重写String url = response.encodeRedirectURL(request.getContextPath()+"/servlet/ListCartServlet");System.out.println(url);response.sendRedirect(url);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}

ListCartServlet

package xdp.gacl.session;import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class ListCartServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();HttpSession session = request.getSession();List<Book> list = (List) session.getAttribute("list");if(list==null || list.size()==0){out.write("对不起,您还没有购买任何商品!!");return;}//显示用户买过的商品out.write("您买过如下商品:<br>");for(Book book : list){out.write(book.getName() + "<br/>");}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}
}

在禁用了cookie的IE8下的运行效果如下:
在这里插入图片描述
通过查看IndexServlet生成的html代码可以看到,每一个超链接后面都带上了session的Id,如下所示

本网站有如下书:<br/>javaweb开发   <a href='/JavaWeb_Session_Study_20140720/servlet/BuyServlet;jsessionid=96BDFB9D87A08D5AB1EAA2537CDE2DB2?id=1'>购买</a><br/>
spring开发   <a href='/JavaWeb_Session_Study_20140720/servlet/BuyServlet;jsessionid=96BDFB9D87A08D5AB1EAA2537CDE2DB2?id=2'>购买</a><br/>
hibernate开发   <a href='/JavaWeb_Session_Study_20140720/servlet/BuyServlet;jsessionid=96BDFB9D87A08D5AB1EAA2537CDE2DB2?id=3'>购买</a><br/>
struts开发   <a href='/JavaWeb_Session_Study_20140720/servlet/BuyServlet;jsessionid=96BDFB9D87A08D5AB1EAA2537CDE2DB2?id=4'>购买</a><br/>
ajax开发   <a href='/JavaWeb_Session_Study_20140720/servlet/BuyServlet;jsessionid=96BDFB9D87A08D5AB1EAA2537CDE2DB2?id=5'>购买</a><br/>

所以,当浏览器禁用了cookie后,就可以用URL重写这种解决方案解决Session数据共享问题。而且response. encodeRedirectURL(java.lang.String url) 和response. encodeURL(java.lang.String url)是两个非常智能的方法,当检测到浏览器没有禁用cookie时,那么就不进行URL重写了。我们在没有禁用cookie的火狐浏览器下访问,效果如下:
在这里插入图片描述
从演示动画中可以看到,浏览器第一次访问时,服务器创建Session,然后将Session的Id以Cookie的形式发送回给浏览器,response. encodeURL(java.lang.String url)方法也将URL进行了重写,当点击刷新按钮第二次访问,由于火狐浏览器没有禁用cookie,所以第二次访问时带上了cookie,此时服务器就可以知道当前的客户端浏览器并没有禁用cookie,那么就通知response. encodeURL(java.lang.String url)方法不用将URL进行重写了。

session对象的创建和销毁时机

  1. session对象的创建时机
    在程序中第一次调用request.getSession()方法时就会创建一个新的Session,可以用isNew()方法来判断Session是不是新创建的
//使用request对象的getSession()获取session,如果session不存在则创建一个
HttpSession session = request.getSession();
//获取session的Id
String sessionId = session.getId();
//判断session是不是新创建的
if (session.isNew()) {response.getWriter().print("session创建成功,session的id是:"+sessionId);
}else {response.getWriter().print("服务器已经存在session,session的id是:"+sessionId);
}
  1. session对象的销毁时机
    session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间,例如:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><display-name></display-name><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><!-- 设置Session的有效时间:以分钟为单位--><session-config><session-timeout>15</session-timeout></session-config></web-app>

当需要在程序中手动设置Session失效时,可以手工调用session.invalidate方法,摧毁session。

1 HttpSession session = request.getSession();
2 //手工调用session.invalidate方法,摧毁session
3 session.invalidate();

session和cookie的区别

  • session是服务端存储,cookie是浏览器端存储
  • Cookie是把用户的数据写给用户的浏览器。
  • Session技术把用户的数据写到用户独占的session中。
  • Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。

http://chatgpt.dhexx.cn/article/JQo7jQ5w.shtml

相关文章

python二维表转一维表_Excel中如何将二维表转换成一维表

在办公过程中处理数据做报表时有时候需要我们将二维表转换为一维表&#xff0c;一维表与二维表最大的区别在于列字段中是否有相同性质的字段&#xff0c;有两个或两个以上相同性质字段的则是二维表&#xff0c;今天小编就教一下大家用Excel将二维表转换成一维表。 首先&#xf…

c++vector实现二维表

一、向量的介绍 向量 vector 是一种对象实体, 能够容纳许多其他类型相同的元素, 因此又被称为容器。 与string相同, vector 同属于STL(Standard Template Library, 标准模板库)中的一种自定义的数据类型, 可以广义上认为是数组的增强版。 在使用它时, 需要包含头文…

二维st表

摘要 我们知道一维的st表在经过预处理后可以在O(1)时间内查询任意区间的极值&#xff0c;虽然其是离线算法&#xff0c;但胜在代码短小易写。而在二维RMQ&#xff08;区间最值查询&#xff09;问题中&#xff0c;我们依然可以采用st算法解决问题&#xff0c;只不过我们需要从一…

【C#】读取txt、csv等二维表

程序要读文件&#xff0c;在实战中主要还是以二维表为主&#xff0c;类似下图这种&#xff1a; 基本上除了掌握《【C#】txt的读写》&#xff08;点击打开链接&#xff09;的文件流的读写&#xff0c;还需要与《【C#】利用正则表达式判断输入是否为纯数字、容器类》&#xff08;…

MySQL一维表变二维表_二维表转换一维表,三种方法一网打尽!

小伙伴们&#xff0c;早上好&#xff01;新的一天又开始了&#xff0c;学习的脚步不能停。 今天向大家分享二维表格转一维表的三种方法&#xff0c;分别用到函数、数据透视表和VBA代码。三种方法各有利弊&#xff0c;表亲可以自行选择。 如下图&#xff0c;A1:E5是数据源&#…

给二维表添加时间序列索引

一&#xff0c;读取数据 import pandas as pd open_dataspd.read_csv(./data328/open328.csv,headerNone) open_datas.head()(可以看到索引为数字) 二&#xff0c;创建时间序列 import pandas as pd open_dataspd.read_csv(./data328/open328.csv,headerNone) open_datas.h…

excel二维表转化为一维表

1、什么是二维表和一维表 二维表即表中有两个维度&#xff0c;纵向维度的哪列值唯一 一维表即只有列名一个维度 2、 添加工具并转换 我们需要添加【数据透视表和数据透视图向导】功能来完成&#xff0c;如果已经设置可以忽略这步 文件--选项--自定义功能区--不在功能区的命令…

Excel如何快速将一维表转为二维表

如下图左侧是某公司销售一维表&#xff0c;现在想要将其快速转换成右侧这种二维表。 选中姓名列所有数据区域&#xff0c;然后点击下图选项&#xff08;Excel工具箱&#xff0c;具体安装方法百度即可&#xff0c;本文不作过多叙述&#xff09; 选择【随机重复】&#xff0c;然后…

【Python】Pandas DataFrame 一维表二维表的转换

目录 一、stack & unstackunstack 将一维表转换为二维表stack 将二维表转换为一维表 二、pivot & meltpivot 将一维表转换为二维表melt将二维表转换为一维表 Tips 用pandas处理数据&#xff0c;我们经常获取到的是从数据库或者excel中获取的一维表。而常常需要重排&…

Excel:一维表和二维表 互转

一、一维表转二维表 数据源&#xff1a; 一份流水账式的值班表&#xff0c;为了便于打印张贴&#xff0c;现在需要使其变成这样的样式&#xff1a; 也就是从一维表变成传说中的二维表。 1、新建查询 依次单击【数据】→【新建查询】 →【从文件】→【从工作簿】 找到存放的工作…

mysql 二维表 查询_二维报表数据表设计

报表原型: 这里随便挑了一个二维报表 二维报表设计分析: 上面的报表原型行和列都有数据项,我们可以根据地理位置的经纬度定坐标点的思想来进行设计 这里使用列行来表示 c1r1表示第一列第一行 c1r2表示第一列第二行 ..... c2r1表示第二列第一行 c2r2表示第二 报表原型: 这里随便…

MySQL一维表变二维表_一维表转化为二维表,你会吗?

原标题&#xff1a;一维表转化为二维表&#xff0c;你会吗&#xff1f; 在产品的一些销售数据处理中&#xff0c;我们经常看到这样的一维表数据: 我们在进行数据的统计分析时&#xff0c;需要用这样的一维表作为数据源&#xff0c;所以正常情况下我们会用一维表的格式进行数据的…

python一维列表变二维列表_使用Python轻松应对一维表与二维表相互转换

数据分析时,同事经常给你一份二维表,是不是分分钟有想哭的冲动,一大堆的东西在一块,怎么透视?想要做进一步分析,也是特别麻烦。今天给你一种方便的方法。 一、入门版 先来看看可能要处理的文件是什么样的? 看看,别提多闹心了。当然我们不可能一开始就处理这么复杂的样…

Python实现一维表与二维表之间的相互转化

对已有数据表进行一维和二维之间的转化&#xff1a; import pandas as pd# 读入数据&#xff1a; df pd.read_excel(2dims.xls,Sheet1) df df的结构为&#xff1a; 如上图所示df是一个二维表。 # 将二维数据表转化为一维数据表&#xff1a; new_data df.set_index(地区) #…

java 二维表格_实现二维表

create or replace function getGoodsMsgForProtocol( str_in in varchar2,str_classId in varchar2)--分类字 return varchar2 is str_list varchar2(4000) default null;--连接后字符串 str_int number(2) default 0; begin for x in ( select goods.goodsname,goods.specs f…

二维表 转一维表 mysql_Excel二维表转换成一维表(2种方法)

今天大年初四&#xff0c;春节假期还剩三天了&#xff0c;每逢佳节胖三斤&#xff0c;亲们可要注意控制饮食了&#xff0c;要不然春节后无脸见人哟。闲话少说&#xff0c;今日分享如下。 在做数据处理的时候&#xff0c;有的时候为了处理方便我们需要将二维的数据表处理成一维的…

【一起学Rust | 进阶篇 | Grid库】二维表数据结构——Grid

文章目录 前言一、Grid安装和引入二、使用1. 运行官方案例2. Grid宏3. new4. init5. from_vec6. get7. get_mut8. size9. rows10. cols11. is_empty12. clear13. iter14. iter_mut15. iter_col16. iter_col_mut17. iter_row18. iter_row_mut19. push_row20. push_col21. pop_ro…

数据库中的二维表—巧借Excel

一维表和二维表的区别 一维表也常称为流水线表格&#xff0c;它和二维表做出的数据透视表最大的区别在于"行总计"。判断数据是一维表格还是二维表格的一个最简单的办法&#xff0c;就是看其列的内容--每一列是否是一个独立的参数。如果每一列都是独立的参数那就是一维…

倾向得分加权匹配分析方法的R实现

1.1 PSW Package 简介 PSW : Propensity Score Weighting Methods for Dichotomous Treatments. 该包由Huzhang Mao 和LiangLi两位作者贡献&#xff0c;首次发布于2017年10月&#xff1b;该包主要运用倾向得分加权分析方法实现因果效应的推断&#xff1b;主要由5个函数模块构成…

python倾向匹配得分_手把手教你做倾向评分匹配 -PSM

原标题:手把手教你做倾向评分匹配 -PSM 本文首发于“百味科研芝士”微信公众号,转载请注明:百味科研芝士,Focus科研人的百味需求。 各位科研芝士的朋友大家好,今天和大家分享一下新的知识点—PSM,或许大家早已听过这个名词了,或许你对它还是半知半解,不过没关系,希望…