目录
一:Session监听器
1:session种类简介
2:session生命周期 (HttpSessionListener)
2.1:创建:
2.2:销毁
2.3:session的创建和销毁以及活化、钝化的流程;
3:session域中属性的变化(HttpSessioniAttributeListener)
4:session钝化和活化监听器(HttpSessionActivationListener)
5:session的绑定对象和解绑监听器
1:Cookie(总结:浏览器端保存少量数据的一种技术;)
1.1:什么是 Cookie?
1.2:特点
2:如何创建 Cookie
3:服务器如何获取 Cookie
4:Cookie 值的修改(同名cookie覆盖)
6:Cookie 生命控制
三:Session会话
1:什么是 Session 会话?
2:如何创建 Session 和获取(id 号, 是否为新)
2.1request.getSession()
2.2:isNew(); 判断到底是不是刚创建出来的(新的)
2.3:getId() 得到 Session 的会话 id 值。
3:Session 域数据的存取
3.1:向Session中存数据
3.2:从Session中取数据
4:Session 生命周期控制
4.1Session 默认的超时时长是多少!Session 默认的超时时间长为 30 分钟。
4.2:修改默认Session超时时间
4.3:设置Session超时时间
5: 浏览器和 Session 之间关联的技术内幕
五:令牌机制
1:页面代码:
2:后台代码:
六:token机制认证方法
前言:
他们的执行顺序:spring的注入是在filter和listener之后的,(顺序是这样的listener >> filter >> servlet >> spring )
- ServletContext
¨ 生命周期监听:ServletContextListener,它有两个方法,一个在出生时调用,一个在死亡时调用;
² void contextInitialized(ServletContextEvent sce):创建SErvletcontext时
² void contextDestroyed(ServletContextEvent sce):销毁Servletcontext时
¨ 属性监听:ServletContextAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
² void attributeAdded(ServletContextAttributeEvent event):添加属性时;
² void attributeReplaced(ServletContextAttributeEvent event):替换属性时;
² void attributeRemoved(ServletContextAttributeEvent event):移除属性时;
- HttpSession
¨ 生命周期监听:HttpSessionListener,它有两个方法,一个在出生时调用,一个在死亡时调用;
² void sessionCreated(HttpSessionEvent se):创建session时
² void sessionDestroyed(HttpSessionEvent se):销毁session时
¨ 属性监听:HttpSessioniAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
² void attributeAdded(HttpSessionBindingEvent event):添加属性时;
² void attributeReplaced(HttpSessionBindingEvent event):替换属性时
² void attributeRemoved(HttpSessionBindingEvent event):移除属性时
- ServletRequest
¨ 生命周期监听:ServletRequestListener,它有两个方法,一个在出生时调用,一个在死亡时调用;
² void requestInitialized(ServletRequestEvent sre):创建request时
² void requestDestroyed(ServletRequestEvent sre):销毁request时
¨ 属性监听:ServletRequestAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
² void attributeAdded(ServletRequestAttributeEvent srae):添加属性时
² void attributeReplaced(ServletRequestAttributeEvent srae):替换属性时
² void attributeRemoved(ServletRequestAttributeEvent srae):移除属性时
javaWeb中完成编写监听器:
注:还有两个是关于session的监听器,和上边的不一样;
HttpSessionBindingListener:当某个类实现了该接口后,可以感知本类对象添加到session中,以及感知从session中移除。例如让Person类实现HttpSessionBindingListener接口,那么当把Person对象添加到session中,或者把Person对象从session中移除时会调用下面两个方法:
- public void valueBound(HttpSessionBindingEvent event):当把监听器对象添加到session中会调用监听器对象的本方法;
- public void valueUnbound(HttpSessionBindingEvent event):当把监听器对象从session中移除时会调用监听器对象的本方法;
- 这里要注意,HttpSessionBindingListener监听器的使用与前面介绍的都不相同,当该监听器对象添加到session中,或把该监听器对象从session移除时会调用监听器中的方法。并且无需在web.xml文件中部署这个监听器.
HttpSessionActivationListener:Tomcat会在session从时间不被使用时钝化session对象,所谓钝化session,就是把session通过序列化的方式保存到硬盘文件中。当用户再使用session时,Tomcat还会把钝化的对象再活化session,所谓活化就是把硬盘文件中的session在反序列化回内存。当session被Tomcat钝化时,session中存储的对象也被纯化,当session被活化时,也会把session中存储的对象活化。如果某个类实现了HttpSessionActiveationListener接口后,当对象随着session被钝化和活化时,下面两个方法就会被调用:
- public void sessionWillPassivate(HttpSessionEvent se):当对象感知被活化时调用本方法;
- public void sessionDidActivate(HttpSessionEvent se):当对象感知被钝化时调用本方法;
HttpSessionActivationListener监听器与HttpSessionBindingListener监听器相似,都是感知型的监听器,例如让Person类实现了HttpSessionActivationListener监听器接口,并把Person对象添加到了session中后,当Tomcat钝化session时,同时也会钝化session中的Person对象,这时Person对象就会感知到自己被钝化了,其实就是调用Person对象的sessionWillPassivate()方法。当用户再次使用session时,Tomcat会活化session,这时Person会感知到自己被活化,其实就是调用Person对象的sessionDidActivate()方法。
注意,因为钝化和活化session,其实就是使用序列化和反序列化技术把session从内存保存到硬盘,和把session从硬盘加载到内存。这说明如果Person类没有实现Serializable接口,那么当session钝化时就不会钝化Person,而是把Person从session中移除再钝化!这也说明session活化后,session中就不在有Person对象了。
package com.wkl.lisener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* Description:
* Date: 2020/8/28 - 上午 10:37
* author: wangkanglu
* version: V1.0
*/
public class SessionLisener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("session创建。。。"+se.getSession().getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("session销毁。。。"+se.getSession().getId());
}
}
注册:
1):第一次访问jsp;因为session是内置的;没有就要创建
2):以后任意一次访问都会携带cookie中的sessionid,服务器中有这个session就不用创建;否则应该创建
session超时自动销毁
session手动销毁
HttpSession session = request.getSession();
session.invalidate();
1:服务器第一次启动时;因为默认访问首页(index.jsp),所以自动创建session;
2:当服务器访问其他的jsp或者访问接口;返回系统现在的session时;都会放回第一次创建的session;因为访问时请求头会带着session的信息;
3:如果服务器关闭重新启动,之前的session钝化(存在硬盘中),服务启动有重新活化(从银盘中读取);这时候服务器访问首页又创建新的session;这时候浏览器cookie存的是过去的sessionid;浏览器带着过去的sessionid访问接口;这时候服务器会将新的session返回来;浏览器重新保存在cookie中;
4:如果浏览器关闭了;cookie清空了;那么下次访问时,浏览器带着空白的session访问服务器;这时候服务器会重新创建新的session;
package com.wkl.lisener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* Description:
* Date: 2020/8/28 - 上午 10:37
* author: wangkanglu
* version: V1.0
*/
public class SessionLisener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
String name = event.getName();
Object value = event.getValue();
System.out.println("session中添加【"+name+"】属性了。。。。。值是:【"+value+"】");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
String name = event.getName();
Object value = event.getValue();
System.out.println("session中移除【"+name+"】属性了。。。。。值是:【"+value+"】");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
String name = event.getName();
//这是旧值
Object value = event.getValue();
//这是新的值
Object attribute = event.getSession().getAttribute(name);
System.out.println("session中修改替换【"+name+"】属性了。。。。。旧值是:【"+value+"】新的值是【"+attribute+"】");
}
}
在jsp中:
<%
session.setAttribute("user","admin");
Thread.sleep(3000);
session.setAttribute("user","lisi");
Thread.sleep(3000);
session.removeAttribute("user");
%>
结果:
所谓钝化session,就是把session通过序列化的方式保存到硬盘文件中。当用户再使用session时,Tomcat还会把钝化的对象再活化session,所谓活化就是把硬盘文件中的session在反序列化回内存。当session被Tomcat钝化时,session中存储的对象也被纯化,当session被活化时,也会把session中存储的对象活化
javabean代码:
package com.wkl.bean;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;
/**
* Description:
* 这两个监听器都不用在web.xml中注册
* HttpSessionActivationListener:活化,钝化监听器
* HttpSessionAttributeListener:监听对象调用的监听器
*
* Date: 2020/8/31 - 下午 3:22
* author: wangkanglu
* version: V1.0
*/
public class User implements Serializable,HttpSessionActivationListener{
//session将要钝化
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println("我【"+this+"】要和session一起被钝化了。。。。。。");
}
//sssion活化了
@Override
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println("我【"+this+"】要和session又活了。。。。。。");
}
}
在jsp中将javabean加入session中;
当关闭服务器时发生钝化:
当再次开启服务器时他们又会活化过来
他和session域中属性变化的监听器的区别就是;绑定属性监听器的范围小;这个只监听这个对象;
package com.wkl.bean;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;
/**
* Description:
* 这两个监听器都不用在web.xml中注册
* HttpSessionActivationListener:活化,钝化监听器
* HttpSessionAttributeListener:监听对象调用的监听器
*
* Date: 2020/8/31 - 下午 3:22
* author: wangkanglu
* version: V1.0
*/
public class User implements Serializable,HttpSessionAttributeListener{
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println("user绑定了。。。。");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
System.out.println("user移除了。。。。");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
System.out.println("user替换了。。。。");
}
}
1、Cookie 翻译过来是饼干的意思。
2、Cookie 是服务器通知客户端保存键值对的一种技术。
3、客户端有了 Cookie 后,每次请求都发送给服务器。
4、每个 Cookie 的大小不能超过 4kb
5、一个cookie是一个名字-值对,可以保存多个的
1:保存少量
2:都是纯文本
3:保存的当前网站的cookie;每次访问网站都会携带过去(该网站所有的cookie);如果我们是浏览器;那么银行卡就是银行网站给我们的cookie;
1:默认是会话期间有效(浏览器只要不关,cookie就在;cookie存在于浏览器的进程中)
2:public void setMaxAge(int expiry) 来设置cookie的有效时间;
expiry
- 一个指明cookie的最大生存时间的以秒计时的整数。
如果是一个负值,意味着cookie不会被存储;
如果为零,则删除该cookie。
Cookie cookie = new Cookie("test","wkl");
cookie.setMaxAge(10);
response.addCookie(cookie);
请求返回的响应通过在请求头中的设置;让浏览器来保存cookie;
package com.wkl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Description:
* Date: 2020/6/14 - 下午 9:10
* author: wangkanglu
* version: V1.0
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置了响应头
// 此方法一定要在获取流对象之前调用才有效
resp.setContentType("text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("我知道了,回去吧");
//1 创建 Cookie 对象
Cookie cookie = new Cookie("key4", "value4");
//2 通知客户端保存 Cookie
resp.addCookie(cookie);
//1 创建 Cookie 对象
Cookie cookie1 = new Cookie("key5", "value5");
//2 通知客户端保存 Cookie
resp.addCookie(cookie1);
resp.getWriter().write("Cookie 创建成功");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet的post方法被请求了。。。");
}
}
服务器获取客户端的 Cookie 只需要一行代码:req.getCookies():Cookie[]
package com.wkl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Description:
* Date: 2020/6/14 - 下午 9:10
* author: wangkanglu
* version: V1.0
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置了响应头
// 此方法一定要在获取流对象之前调用才有效
resp.setContentType("text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("我知道了,回去吧");
//获取cookie
Cookie[] cookies = req.getCookies();
for (Cookie cookie : cookies) {
getName 方法返回 Cookie 的 key (名)
getValue 方法返回 Cookie 的 value 值
resp.getWriter().write("Cookie[" + cookie.getName() + "=" + cookie.getValue() + "]
");
}
//1 创建 Cookie 对象
Cookie cookie = new Cookie("key4", "value4");
//2 通知客户端保存 Cookie
resp.addCookie(cookie);
//1 创建 Cookie 对象
Cookie cookie1 = new Cookie("key5", "value5");
//2 通知客户端保存 Cookie
resp.addCookie(cookie1);
resp.getWriter().write("Cookie 创建成功");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet的post方法被请求了。。。");
}
}
方案一:
1、先创建一个要修改的同名(指的就是 key)的 Cookie 对象
2、在构造器,同时赋于新的 Cookie 值。
3、调用 response.addCookie( Cookie );
Cookie cookie = new Cookie("key1","newValue1");
// 3 、调用 response.addCookie( Cookie ); 通知 客户端 保存修改
resp.addCookie(cookie);
方案二:
1、先查找到需要修改的 Cookie 对象
2、调用 setValue()方法赋于新的 Cookie 值。
3、调用 response.addCookie()通知客户端保存修改
方案二:
// 1 、先查找到需要修改的 Cookie 对象
Cookie cookie = CookieUtils.findCookie("key2", req.getCookies());
if (cookie != null) {
// 2 、调用 setValue() 方法赋于新的 Cookie 值。
cookie.setValue("newValue2");
// 3 、调用 response.addCookie() 通知客户端保存修改
resp.addCookie(cookie);
}
setMaxAge()
正数,表示在指定的秒数后过期
负数,表示浏览器一关,Cookie 就会被删除(默认值是-1)
零,表示马上删除 Cookie
Cookie cookie = new Cookie("life3600", "life3600");
cookie.setMaxAge(60 * 60); // 设置 Cookie 一小时之后被删除。无效
resp.addCookie(cookie);
resp.getWriter().write(" 已经创建了一个存活一小时的 Cookie");
// 先找到你要删除的 Cookie 对象
Cookie cookie = CookieUtils.findCookie("key4", req.getCookies());
if (cookie != null) {
// 调用 setMaxAge(0);
cookie.setMaxAge(0); // 表示马上删除,都不需要等待浏览器关闭
// 调用 response.addCookie(cookie);
resp.addCookie(cookie);
resp.getWriter().write("key4 的 的 Cookie 已经被删除");
}
Cookie cookie = new Cookie("defalutLife","defaultLife");
cookie.setMaxAge(-1);// 设置存活时间
resp.addCookie(cookie);
1、Session 就一个接口(HttpSession)。
2、Session 就是会话。它是用来维护一个客户端和服务器之间关联的一种技术。
3、每个客户端都有自己的一个 Session 会话。
4、Session 会话中,我们经常用来保存用户登录之后的信息。
如何创建和获取 Session。它们的 API 是一样的。
第一次调用是:创建 Session 会话
之后调用都是:获取前面创建好的 Session 会话对象。
true 表示刚创建
false 表示获取之前创建
每个会话都有一个身份证号。也就是 ID 值。而且这个 ID 是唯一的。
req.getSession().setAttribute("key1", "value1");
resp.getWriter().write(" 已经往 Session 中保存了数据");
Object attribute = req.getSession().getAttribute("key1");
resp.getWriter().write("从 从 Session 中获取出 key1 的数据是:" + attribute);
值为正数的时候,设定 Session 的超时时长。
负数表示永不超时(极少使用)
因为在Tomcat服务器的配置文件web.xml中默认有以下的配置,它就表示配置了当前Tomcat服务器下所有的Session
超时配置默认时长为:30 分钟。
30
如果说。你希望你的 web 工程,默认的 Session 的超时时长为其他时长。你可以在你自己的 web.xml 配置文件中做
以上相同的配置。就可以修改你的 web 工程所有 Seession 的默认超时时长
20
如果你想只修改个别 Session 的超时时长。就可以使用上面的 API。setMaxInactiveInterval(int interval)来进行单独的设置。
session.setMaxInactiveInterval(int interval)单独设置超时时长。
// 先获取 Session 对象
HttpSession session = req.getSession();
// 设置当前 Session3 秒后超时
session.setMaxInactiveInterval(3);
resp.getWriter().write(" 当前 Session 已经设置为 3 秒后超时");
Session 技术,底层其实是基于 Cookie 技术来实现的
1:我们和服务器交互期间;可能存放一些数据;服务器专门为每个会话创建一个map(session);这个map用来保存数据
2:100个会话会有100个session,每次创建session的时候会有一个唯一标识(jsessionid,会话id)
利用浏览器每次请求都会带上所有的cookie的特性;
服务器只要创建一块能保存数据的map,给map一个唯一标识(jsessionid),创建好以后命令浏览器cookie保存这个id;
以后浏览器只要访问就会带上这个jsessionid;服务器按照这个标识;找到存储的数据;
注意:
1:会话关闭,默认是coolie没了;挺过cookie持久化技术继续找到之前的sessionid;
2:session失效;自动超时或者手动失效
防止表单重新提交;
原理:在页面加载时,一个token放在session中,另一个用form提交传递到后台,后台接收到两个token进行对比,相同则是第一次提交,清空token
添加商品的页面
<%
String token = UUIDUtils.getUUID();
session.setAttribute("token", token);
%>
// 判断是否是重复提交:
String token1 = (String)request.getSession().getAttribute("token");
String token2 = request.getParameter("token");
// 清空session中的令牌:
request.getSession().removeAttribute("token");
if(!token2.equals(token1)){
request.setAttribute("msg", "亲!您已经提交过!请不要重复提交了!");
request.getRequestDispatcher("/jsp/msg.jsp").forward(request, response);
return;
}
使用token机制的身份验证方法,在服务器端不需要存储用户的登录记录。大概的流程:
客户端使用用户名和密码请求登录。
服务端收到请求,验证用户名和密码。
验证成功后,服务端会生成一个token,然后把这个token发送给客户端。
客户端收到token后把它存储起来,可以放在cookie或者Local Storage(本地存储)里。
客户端每次向服务端发送请求的时候都需要带上服务端发给的token。
服务端收到请求,然后去验证客户端请求里面带着token,如果验证成功,就向客户端返回请求的数据。