会话管理(Cookie、Session)
-
- javaee 的三大组件
-
- servlet的启动时机
-
- 从java application -> java web (servlet ,filter)原来程序“main”作为程序的入口。现在java web的主函数在哪里?
- 3.1. 如果,我希望,tomcat启动的时候,就执行一些代码,该怎么做?
-
- 对http协议“无状态”特征的理解
- 4.1. 具体来说,HTTP协议的无状态特征表现在以下几个方面:
- 4.2. HTTP协议的无状态特征有以下优点和缺点:
-
- 还原http无状态
- 5.1. Cookie 访问服务器之后服务器可以发送cookie给客户端,客户端默认就会保存这个cookie,下次自动发送!
- 5.2. Session
-
- 解释request.getSession()方法
- 6.1. 示例:
1. javaee 的三大组件
Servlet 大部分定义的业务对象
Filter 被调用的时机不同,运行方式不同(横切业务逻辑)
Listener 监听器
2. servlet的启动时机
servlet是单例的,创建的时机默认是:第一次访问的时候创建。
如果每个第一次访问都创建对象,慢。
可以配置servlet的启动时机
在web.xml中对Servlet进行配置
<load-on-startup>0</load-on-startup>
该Servlet就会在启动tomcat服务器的时候,自动地创建对象并且完成初始化工作
servlet可以通过配置创建对象。
Filter:自动地在tomcat启动的时候会创建并且初始化!
3. 从java application -> java web (servlet ,filter)原来程序“main”作为程序的入口。现在java web的主函数在哪里?
目前为止Servlet,Filter,是通过浏览器发起http访问被调用。
java web的主函数在tomcat启动。
tomcat启动,运行tomcat中定义的main,tomcat程序执行。
我们的java web项目,部署在tomcat中,被tomcat管理,为相应url访问,提供服务!
3.1. 如果,我希望,tomcat启动的时候,就执行一些代码,该怎么做?
做一些java web项目的“初始化”工作!
方式1:
人工地创建一个初始化的initServlet,不要提供服务,
利用0配置,
可以把初始化的语句定义在这个servlet中。
方式2:
能够让tomcat启动的,立即就执行
有没有什么方式实现!
ServletContextListener
定义:class InitListener implements ServletContextListener
把需要整个项目“初始化”的代码,定义在
public void contextInitialized(ServletContextEvent servletContextEvent)
方法中
在DD中配置:
<listener>
<listener-class>com.woody.listener.InitListener</listener-class>
</listener>
tomcat服务器,启动的时候就自动调用本方法
在javaee中一共8种监听器,可以在“不同”场景中被调用。
ServletContextListener : 上下文监听
场景:tomcat启动时、tomcat关闭时
还有与属性,会话相关的监听!
4. 对http协议“无状态”特征的理解
HTTP协议是一种无状态协议,也被称为无状态传输协议(Stateless Transfer Protocol)。这意味着每个HTTP请求都是相互独立的,服务器不会记住之前任何请求的状态或上下文信息。
4.1. 具体来说,HTTP协议的无状态特征表现在以下几个方面:
-
每个HTTP请求都是独立的:HTTP协议并不保留先前的请求或响应的状态信息。每个HTTP请求都是独立的,服务器无法判断该请求是否来自同一用户或是否与之前的请求相关。
-
无法跟踪会话状态:由于HTTP协议的无状态特性,服务器无法跟踪用户的会话状态。因此,Web应用程序必须使用其他机制来跟踪用户的状态,如使用Cookies、URL重写等方式。
-
无法保持长连接:由于HTTP协议的无状态特性,服务器在处理完一个HTTP请求后会立即关闭连接,无法保持长时间的连接,这样会增加了连接开销。
4.2. HTTP协议的无状态特征有以下优点和缺点:
优点:
简化服务器设计:服务器不必维护每个客户端的状态,这简化了服务器的设计和维护工作。
提高可伸缩性:由于服务器不需要为每个客户端维护状态,可以更轻松地处理大量的并发请求,提高了服务器的可伸缩性。
缺点:
不适合某些场景:在一些应用场景中,如在线支付、购物车等需要跟踪用户状态的应用中,HTTP协议的无状态特性会带来一些不便,需要采用其他机制来实现。
增加了一些额外的开销:为了解决HTTP协议的无状态特性带来的不便,Web应用程序需要采用一些额外的机制来跟踪用户状态,这会增加一些额外的开销和复杂性。
5. 还原http无状态
LoginServlet:验证的用户名密码,登入成功,应该把数据放在下一次可以访问到地方
AdminManageServlet: 从登入成功设置的“地方”获取数据,服务端就不需要再次验证。
思路:
- 浏览器应该存储一些数据
- 服务器应该有存储区别哪个用户的集合。
“记住密码”
- 浏览器中勾选“记住密码”复选框,点击登录
- 服务器验证用户名密码正确的情况下,发现用户需要“记住密码”。
- 服务器就会发回“记住密码”数据。
- 浏览器下次提交时,就会把用户名和密码数据,“自动”填入表单
- 因为用户名和密码已经填入,客户端只要点击登入。
- 就完成用户登入。
- 用户登入成功,没有构造“记住密码”或,用户登入不成功。
- 服务器就会发回不要“记住密码”数据。
- 用户需要再次添加用户名和密码!
5.1. Cookie 访问服务器之后服务器可以发送cookie给客户端,客户端默认就会保存这个cookie,下次自动发送!
- 服务端,创建cookie对象,添加到响应中,发回给客户端。
- 客户端接收到响应,把cookie的数据保存“浏览器”中。
- 下次访问同一个“网站”时(服务器的服务),会自动携带cookie数据
- 通过cookie的方式,实现了 “不同请求”之间数据“共享”。
DOM: document object model 文档对象模型(节点 元素,属性,文本)
BOM: browser object model 浏览器对象 (window, location, navigator, history, cookie)
5.2. Session
JsessionId = 1FC8720928E10F773699F28BAC174BCE
有没有一种“标记”能够,让服务器“知道”是哪个客户端。
通过这种“标记”把数据,保存在服务器。客户端只要提供这个标记就可以"jsessionId"
session保存在服务器。
通过getSession()方法
根据jsessionId查询session对象
如果找不到就创建对象,并且以键值对作为cookie返回给浏览器,还会在服务器申请空间存储该客户端的数据
如果找到,就直接可以获取操作数据的键值对对象
底层原来还是cookie ,只是用“特殊”的键值对“自动”帮助开发人员完成设置(addCookie, 查找)
session简化了对cookie的遍历操作!
6. 解释request.getSession()方法
request.getSession()方法用于获取当前请求对应的Session对象。Session对象是一种在Web应用中存储用户状态信息的机制,通过Session对象可以在多个请求之间共享数据。通常情况下,Session对象存储在服务器端,由服务器维护和管理,客户端通过Cookie或者URL重写等方式来进行Session的管理和维护。
实现原理流程:
-
当用户第一次访问Servlet时,Servlet容器会检查此用户是否已经有一个Session,如果没有则创建一个新的Session对象,同时给这个Session分配一个唯一的Session ID(通过使用一定算法生成),并将该Session对象与此次请求相关联。
-
Servlet容器会将该Session ID 以cookie的形式发送给客户端(浏览器),并在浏览器本地存储该Session ID。
-
当客户端再次发送请求时,浏览器会将该Session ID 以cookie的形式附着在请求头中一起发送给服务器。
-
Servlet容器接收到该请求后,根据请求头中包含的Session ID,利用该ID在服务器端查找已有的Session 对象。
-
如果查找成功,则表示客户端与服务器之前已经建立起连接(也就是说,客户端在请求头中携带的Session ID 与服务器中的Session ID 相匹配)。此时服务器就可以使用该Session对象,根据需要创建、读取、修改、删除Session中的数据,最后将响应数据写回客户端。
-
如果查找失败,则表示客户端与服务器之前还没有建立连接(也就是说,客户端在请求头中携带的Session ID 与服务器中的Session ID 不匹配)。此时Servlet容器会创建一个新的Session对象,并给该Session分配一个新的Session ID,以此来保证每一个Session对象的唯一性。然后将新的Session ID 以cookie的形式发送给客户端,并在服务器端与该ID相关联,最后将响应数据写回客户端。
综上所述,使用request.getSession()方法的实现原理就是:当客户端第一次请求Servlet时,Servlet容器会创建一个新的Session对象并为其分配一个唯一的Session ID,将该ID发送给客户端,并在服务器端与该ID相关联,从而实现对话的建立和记录。而当客户端再次请求服务器时,Servlet容器将在服务器端根据请求携带的Session ID 找到相应的Session对象,并根据需要进行数据的读取、修改、删除等操作。
需要注意的是,Session对象属于服务器端的对象,保存在服务器端的内存中或者磁盘中,而Session ID需要通过cookie或者其他方式发送给客户端,在客户端本地保存。因此,在使用Session时需要注意安全性问题,避免Session ID 被篡改或者伪造,导致安全风险。
6.1. 使用示例:
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
public class MyServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 获取Session对象
HttpSession session = request.getSession();
// 在Session对象中存储数据
session.setAttribute("username", "Alice");
session.setAttribute("age", 20);
// 从Session对象中读取数据
String username = (String) session.getAttribute("username");
int age = (int) session.getAttribute("age");
// 将数据返回给客户端
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><head><title>Session Demo</title></head>");
out.println("<body>");
out.println("<h1>Welcome, " + username + "!</h1>");
out.println("<p>Your age is " + age + ".</p>");
out.println("</body></html>");
}
}
ody>");
out.println("<h1>Welcome, " + username + "!</h1>");
out.println("<p>Your age is " + age + ".</p>");
out.println("</body></html>");
}
}