状态管理之Cookie
为什么需要状态管理
HTTP协议是无状态,不能保存每次提交信息,即当服务器返回与请求相对应的应答之后,这次事务的所有信息将丢失。
如果用用户发来一个新的请求服务器无法知道是否与上次的请求有联系
对于那些需要多次提交数据才能完成web操作就会出现问题?比如:登录
什么是状态管理
WEB应用中的**【会话】是指一个客户端浏览器与WEB服务器之间连续发生一些列请求和响应过程**
WEB应用的**【会话状态】是指WEB服务器与浏览器在会话过程中产生的状态信息,借助会话状态,WEB服务器能够把属于同一个会话中,一些列请求和响应关联起来**
状态管理的两种常见模式
客户端状态管理技术:将状态保存在客户端【浏览器】,代表性的技术Cookie技术
服务器状态管理技术:将状态保存在服务器端。代表性的技术Session技术
PS:服务器传递SessionID的时候需要使用Cookie方式
Cookie的应用
什么是Cookie
Cookie是在浏览器访问WEB服务器的某个资源时,由WEB服务器在HTTP响应消息中附带传送给浏览器的一小段数据WEB服务器传送给各个客户端浏览器的数据是可以各不相同
一旦WEB浏览器保存某个Cookie,那么它在以后每次访问该WEB服务器时,都应在HTTP请求头中将这个Cookie回传给WEB服务器
WEB服务器通过在HTTP响应消息中增加set-cookie响应字段将Cookie信息发送给浏览器,浏览器则通过在HTTP请求消息中增加Cookie请求字段将Cookie回传给WEB服务器
一个Cookie只能标识一种信息,它至少包含一个标识该信息的名称(NAME)和设置值(VALUE)
一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览也可以存储多个WEB站点提供的Cookie
PS:一般浏览器只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB
如何创建Cookie
ps:以下的操作都需要使用到cookie.html文件需要进行 一些修改
package com.qfedu.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//创建Cookie
@WebServlet(name = "CookieServletDemo1",value="/csd1")
public class CookieServletDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie
//ps:Cookie本身是一个类这个类是没有无参构造方法的
//所以创建Cookie对象的时候必须传入name和value--》即kv键值对[参数是String类型]
Cookie ck = new Cookie("key1","value1");
//2.给你浏览器发送
response.addCookie(ck);
//3.结果
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("Cookie创建成功");
}
}
如何查询Cookie
服务器获取客户端的Cookie只需要一行代码,**request.getCookies()**返回的式存储着Cookie的对象的数组
package com.qfedu.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//获取cookie
@WebServlet(name = "CookieServletDemo2",value="/csd2")
public class CookieServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
//1.获取所有cookie对象
Cookie[] cookies = request.getCookies();
for(Cookie ck : cookies){
response.getWriter().println("Cookie["+ck.getName()+"="+ck.getValue()+"]<br/>");
}
}
}
如果此时通过getCookies()获取了Cookie对象数组,在实际开发中若需要获取其中某一个Cookie怎么做?
package com.qfedu.cookie;
import sun.rmi.transport.ObjectTable;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.util.Objects;
//获取cookie
@WebServlet(name = "CookieServletDemo2",value="/csd2")
public class CookieServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
//1.获取所有cookie对象
Cookie[] cookies = request.getCookies();
// for (Cookie ck : cookies) {
// //如果需要获取某个Cookie,可以直接在数组遍历中判断key的名字[不太推荐]
// //if(ck.getName().equals("key1")) {
// response.getWriter().println("Cookie[" + ck.getName() + "=" + ck.getValue() + "]<br/>");
// // }
// }
Cookie ck = findCookie("key1",cookies);
if(Objects.nonNull(ck)){
response.getWriter().println("Cookie[" + ck.getName() + "=" + ck.getValue() + "]<br/>");
}
}
//可以提供一个工具类来专门查找Cookie对象,这里就简便完成[推荐封装成方法,可以在方法中进行合理化判断]
public static Cookie findCookie(String name,Cookie[] cookies){
if(name == null || cookies == null || cookies.length == 0){
return null;
}
for(Cookie cookie: cookies){
if(name.equals(cookie.getName())){
return cookie;
}
}
return null;
}
}
如何修改Cookie
方式一:【适用于直接修改无需其他操作】
1.先创建一个需要修改的同名(指的是key【即name是同名】)的Cookie对象
2.在构造方法,同时赋予新的Cookie值
3.调用response.addCookie(新的cookie对象)
Cookie ck = new Cookie("key1","value2");
response.addCookie(ck);
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("Cookie中key1的值已经被修改了");
方法二:【适用于获取cookie对象并加以操作之后要修改值】
1.先查找要修改的Cookie对象
2.调用setValue方法进行新值赋值操作
3.调用response.addCookie()通知客户端保存修改
Cookie cookie = CookieFindUtil.findCookie("key1", request.getCookies());
cookie.setValue("value3");
response.addCookie(cookie);
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("Cookie中key1的值已经被修改了");
Cookie的生存时间
Cookie的生命控制是指:如何管理Cookie什么时候 被销毁(删除)
核心方法setMaxAge() 参数是一个int类型【单位是秒】
正数(即>0),表示在指定秒数之后过期【自动删除】
负数(即<0),表示浏览器一关闭,Cookie就会被立即删除(默认值是-1)
零(即=0),表示马上删除Cookie
默认
package com.qfedu.cookie;
import com.qfedu.utils.CookieFindUtil;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//立即删除cookie
@WebServlet(name = "CookieServletDemo4",value="/csd4")
public class CookieServletDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("defaultLife","defaultLife");
//不调用设在默认值就是-1
cookie.setMaxAge(-1);
response.addCookie(cookie);
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("Cookie声明周期使用默认值");
}
}
PS:Cookie的会话☞的是:会话开始就是浏览器打开,会话结束就是浏览器关闭【在这个过程中浏览器启动网页是无关的】
立即
package com.qfedu.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.util.Objects;
//获取cookie
@WebServlet(name = "CookieServletDemo5",value="/csd5")
public class CookieServletDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
//查找到某个cookie立即删除
//1.获取所有cookie对象
Cookie[] cookies = request.getCookies();
Cookie ck = findCookie("key1",cookies);
if(Objects.nonNull(ck)){
//设置立即删除,都不需要等待浏览器关闭
ck.setMaxAge(0);
response.addCookie(ck);
response.getWriter().println("key1的Cookie已经被删除了");
}
}
//可以提供一个工具类来专门查找Cookie对象,这里就简便完成[推荐封装成方法,可以在方法中进行合理化判断]
public static Cookie findCookie(String name,Cookie[] cookies){
if(name == null || cookies == null || cookies.length == 0){
return null;
}
for(Cookie cookie: cookies){
if(name.equals(cookie.getName())){
return cookie;
}
}
return null;
}
}
设置存储时长
package com.qfedu.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.util.Objects;
//设置时长
@WebServlet(name = "CookieServletDemo6",value="/csd6")
public class CookieServletDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
//1.创建Cookie
Cookie cookie = new Cookie("life3600","life3600");
cookie.setMaxAge(60*60);//设置一小时之后删除【单位是秒】
response.addCookie(cookie);
response.getWriter().println("已经创建了一个存活一小时的Cookie");
}
}
扩展:Cookie的编码和解码(了解)
Cookie在设置名字(name)和值(value),还可以进行修改value 值
这些操作的时候不需要给name和value进行一下操作:
【不应包含空格、方括号、圆括号、等号、逗号、双引号、斜杠、问号、at符号@、冒号和分号,以上至不是所有浏览器都禁用,不允许有中文(中文会出现编码问题)】
ps:中文和英文字符不同,中文属于Unicode字符,在内存中占用的字节一般是3~4,而英文属于ASCII字符,内存中只占用2个字节
如果需要对Cookie中文设置,就需要进行编码和解码
1.编码类 java.net.URLEncoder类
2.解码类 java.net.URLDecoder类
//使用cookie对象存储值的时候
Cookie ck = new Cookie(URLEncoder.encode("姓名","UTF-8"),URLEncoder.encode("张三","UTF-8"));
//取出Cookie对象之后需要进行解码操作
String name = URLDecoder.decode(ck.getName,"UTF-8");
String value = URLDecoder.decode(ck.getValue,"UTF-8");
Cookie的路径问题
什么是Cookie的路径问题
Cookie一般都是由用户访问页面而被创建出来,可并不是只创建在Cookie的页面才可以访问到这个Cookie,在默认情况下,处于安全访问的考虑,只有与创建Cookie的页面处于同一个目录或在创建Cookie页面子目录下的网页才可以访问,那么如果需要子其他位置也可以访问出Cookie,这个时候需要设置路径
Cookie有一个属性path,可以有效过滤那些cookie可以发送给服务器,那些不发送
path属性是通过请求地址来进行有效过滤
发送Cookie的条件
浏览器在发送请求之前,首先会根据url中域名在Cookie列表中查找所有与当前域名一样的Cookie,然后在根据指定的路径在进行匹配,如果当前请求在【域】匹配的基础上还与路径匹配,那么会将所有匹配的Cookie发送给服务器
/*假如两个Cookie path分别对应不同的路径
CookieA path = /工程路径
CookieB paht = /工程路径/abc
请求地址如下
http://ip:port/工程路径/a.html
CookieA 发送 原因是 CookieA的path正好满足 / 工程路径
CookieB 不会送 原因是 CookieB的路径多了 abc
请求地址如下
http://ip:port/工程路径/abc/a.html
CookieA 发送 原因是 CookieA的path正好满足 /工程路径 在工程路径后有什么的无所谓只要满足要求
CookieB 发送 原因是 CookieB的path正好满足
ps:工程路径必须一致【例如:百度Cookie 怎么可能出现在 sohu搜狐】
核心方法setPath()参数是一个String类型,需要设置路径
package com.qfedu.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//设置Cookie路径
@WebServlet(name = "CookieServletDemo7",value="/csd7")
public class CookieServletDemo7 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
//1.创建Cookie
Cookie cookie = new Cookie("path1","path");
//2.设置可以一访问到cookie的路径
//如何获取工程路径【核心】 只需要通过request对象 getContextPath()
cookie.setPath(request.getContextPath()+"/abc");
response.addCookie(cookie);
response.getWriter().println("创建饿有一个带有Path路径的cookie");
}
}
ps:这个效果在火狐浏览器演示不是很明显,这个在谷歌演示
Cookie免登录
PS:这里需要使用到一个界面,但是这个界面现阶段还没有正式的接触,暂时先知道可以这样用【JSP页面】
Cookie的特点
作⽤:
Cookie是⼀种通过Web浏览器将⽤户信息等存储于客户端的⼿段,Cookie不同于session,它的内容被
存储在客户端⽽不是服务器端,因此cookie最常⻅的⼀个功能就是:记住⽤户名和密码。这种免密登录
⽅式在私⼈环境下,给⽤户带来了很⼤的便捷,⽤户不⽤每次都要输⼊⽤户名和密码信息就能轻松登录
web系统。
优点:
可配置到期规则:Cookie 可以在浏览器会话结束时到期,或者可以在客户端计算机上⽆限期存在,这取
决于客户端的到期规则,不需要任何服务器资源,Cookie 存储在客户端并在发送后由服务器读取。
简单性:Cookie 是⼀种基于⽂本的轻量结构,包含简单的键值对。
数据持久性:虽然客户端计算机上 Cookie 的持续时间取决于客户端上的 Cookie 过期处理和⽤户⼲预,
Cookie 通常是客户端上持续时间最⻓的数据保留形式
缺点:
⼤⼩受到限制:⼤多数浏览器对 Cookie 的⼤⼩有 4096 字节的限制,尽管在当今新的浏览器和客户端设
备版本中,⽀持 8192 字节的 Cookie ⼤⼩已愈发常⻅。
⽤户配置为禁⽤:有些⽤户禁⽤了浏览器或客户端设备接收 Cookie 的能⼒,因此限制了这⼀功能。
潜在的安全⻛险:Cookie 可能会被篡改。⽤户可能会操纵其计算机上的 Cookie,这意味着会对安全性造成潜在⻛险或者导致依赖于Cookie 的应⽤程序失败。
状态管理之Session
什么是Session
Session用于跟踪客户端的状态,Session指的式在一段时间内,单个客户端与Web服务器的一连串相关的交互过程,在一个Session中,客户端可能会多次请求同一个网页,也有可能请求访问各种不同的服务器资源
PS:Session在网络应用层中被称为会话
具体到Web中的Session指的是用户在浏览某个网站,从进入网站到浏览器关闭所经过的这都时间,也就是说用户浏览这个网站所花费的时间,因为从概述上我们可以看到,Session实际上就是一个【特定的时间概念】
需要特别注意:一个session的概念需要包括特定的客户端,特定的服务器以及不中断的操作时间
A用户和C服务器建立连接时所处的Session,同B用户和C服务器建立连接时所处的Session是两个完全不同Session
简单说明:
1.Session就是一个接口(HttpSession)
2.Session就是会话,它用来维护一个客户端和服务器之间的关联技术
3.每个客户端都有自己的一个session会话
4.session会话中,我们经常用来保存用户登录之后的信息
如何创建获取Session
ps:Session创建和获取和Cookie是类似
如何获取session核心方法:request.getSession()
第一次调用时:会创建Session会话
之后的每次调用:获取前面创建好Session的会话对象
isNew():判断到底是否是新创建出来的
true 表示刚创建好 false 表示获取之前的出创建
每个会话都有一个自己的【身份证号】。也就是ID值,而且这个ID值是唯一的
getId():得到Session的会话ID值,唯一标记
ps:以下的操作会使用session.html页面
package com.qfedu.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//1.创建和获取Session会话对象
@WebServlet(name = "SessionServletDemo",value="/ssd1")
public class SessionServletDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建和获取Session会话对象
/*
getSession会先获取session对象
如果session对象不存能在,则新建一个session对象
如果session对象存在,则返回这个session对象
*/
HttpSession session = request.getSession();
/*
request.getSession()有一个boolean类型参数的方法
参数为true,实现方式和无参getSession效果是一样的
参数为false,如果session对象存在,则返回,否则返回NULL
*/
//判断session是否是新创建出来的
boolean aNew = session.isNew();
//获取session的唯一表示ID
String id = session.getId();
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("得到Session,它的id是:"+id+"<br/>");
response.getWriter().println("得到Session,它是新创建的吗?:"+aNew+"<br/>");
}
}
PS:出现了一个异常
org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/cas]原因在于两个位置,如果注解(查看配置路径中是否写了/) 如果web.xm配置(servlet-mapping标签下 url-pattern --》标签中是否路径添加了/ )
Session域数据的存取
存储
package com.qfedu.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//对session进行数据存储
@WebServlet(name = "SessionServletDemo2",value="/ssd2")
public class SessionServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.向session中存储数据【需要先获取Session对象】
//setAttribute方法参数是一个kv键值对, key是String类型 value是Object类型
//如果在存储值的时候,key已经存在了,那么会替换当前key对应的value【相当修改值】
request.getSession().setAttribute("key1","value1");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("已向Session中保存了数据<br/>");
//获取存储在Session中的值
response.getWriter().println("查看SessionID:"+request.getSession().getId()+"<br/>");
}
}
获取
package com.qfedu.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//对session进行数据获取
@WebServlet(name = "SessionServletDemo3",value="/ssd3")
public class SessionServletDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.session中存储数据获取出来【需要先获取Session对象】
//getAttribute这个方法参数是key值 key参数类型是string
Object key1 = request.getSession().getAttribute("key1");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("获取Session中存的数据:"+key1+"<br/>");
response.getWriter().println("查看SessionID:"+request.getSession().getId()+"<br/>");
}
}
小总结:Session是可以实现数据共享的,为什么可以数据共享?我么可以发现用一个项目的SessionID都是相同【分别点击了(创建、存储、获取这三个操作),所有获取到的SessionID都是同一个】,所以就可以达到数据共享的目的
Session超时
什么是Session超时
HTTPSession的最后一次访问的时间和当前时间大于了指定的最大空闲时间,这时服务器就会销毁Session对象,【Session的默认空闲时间为30分钟】
PS:Session是需要发送给服务器的,为什么需要设置Session超时?
原因在于,如果不设置Session超时,大量用户恶意持有当前Session会话,那么会造成服务器大量资源浪费,session如果存的时间是当前会话结束【浏览挂关闭】,如果1000用户不关闭浏览器,那么就会出现问题
获取session时间
package com.qfedu.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//对session进行超时操作
@WebServlet(name = "SessionServletDemo4",value="/ssd4")
public class SessionServletDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取session对象
HttpSession session = request.getSession();
response.setContentType("text/html;charset=UTF-8");
//getMaxInactiveInterval获取Session的超时时间,默认单位是秒
response.getWriter().println("session的默认超时时间是:"+session.getMaxInactiveInterval()+"秒"+"<br/>");
//获取Session的创建时间,默认单位是毫秒
response.getWriter().println("session的创建时间是:"+session.getCreationTime()+"毫秒"+"<br/>");
//获取最后一次访问时间,默认是毫秒
response.getWriter().println("session的最后一次访问时间是:"+session.getLastAccessedTime()+"毫秒"+"<br/>");
}
}
如果修改session时间
ps:在tomcat启动打印的控制台中
Using CATALINA_BASE: "C:\Users\jkmaster\.IntelliJIdea2019.3\system\tomcat\Tomcat_8_5_53_Java2002_web_CookieAndSession"
这个路径是IDEA自动整个Tomcat的目录,这个目录中有一个文件夹conf,这个文件夹中,有一个web.xml文件,这个文件就是tomcat的配置文件 ,文件中有一个Session默认时间配置
<session-config>
<session-timeout>30</session-timeout>
</session-config>
修改Session的时长方式一:
通过修改工程目录中的web.xml文件【整合tomcat目录的路径下文件】
有一个简便方式,你可以在你自己的工程中web.xml文件中做Session时长的配置
<session-config>
<!--以分钟为单位进行修改-->
<session-timeout>30</session-timeout>
</session-config>
修改Session的时长方式二:
可以用过获取Session对象的同时,对session进行时长设置setMaxInactiveInterval(),这个参数是一个int类型,并且参数是以秒为单位的
核心方法setMaxInactiveInterval() 参数是int类型,单位是秒
package com.qfedu.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//对session进行超时操作
@WebServlet(name = "SessionServletDemo5",value="/ssd5")
public class SessionServletDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取session对象
HttpSession session = request.getSession();
//设置3秒后超时
//ps:很少这样做,因为这个参数类型是int,就意味着这个参数值可以设置为负数【永远不超时】
session.setMaxInactiveInterval(3);
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("session是3秒后超时"+"<br/>");
}
}
ps:Session设置删除时间后,会进入倒计时状态【3,2,1,0】删除,如果在这个时间范围内,再次点击了删除,会重新进入倒计时状态【3,2,1,0】
session立即删除
当前Session会立马删除,核心方法:invalidate()
package com.qfedu.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//对session进行超时操作
@WebServlet(name = "SessionServletDemo6",value="/ssd6")
public class SessionServletDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取session对象
HttpSession session = request.getSession();
//立即删除
session.invalidate();
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("session是立即删除"+"<br/>");
}
}
小总结:session失效的集中情况
1.超过了设置超时时间
2.主动调用了invalidate【立即删除】方法
3.服务器主动或异常关闭
ps:浏览器关闭的时候不让Session失效,如果服务器正常关闭不会立即销毁,非常正常关闭可能会销毁,session会存在我们的硬盘中,也就是当我们点击stop server()会在tomcat目录的work目录中进行对Session的序列化,当服务器再次启动的时候回对这个文件进行一次序列化
浏览器进入Cookie的解决方案(了解)
ps:这个操作建议使用谷歌浏览器使用【在设置中禁用cookie】
此时,服务器可以使用URL重写来完成对 sessionID的发送【cookie中也是存储着JSessionID的】
什么是URL重写?
浏览器在访问服务器上的某个地址时,不在使用原来的哪个地址而是使用经过修改的地址(即,在原地址的后面添加SessionID)
/*
在Servlet中设置一个URL并追加SessionID
//1.获取
HttpSession session = request.getSession()
//2.从写URL//这个路径一般是一个servlet-->"/工程名/servletURL"
//http://localhost:8080/工程名/servletURL;jsessionId=ID值
String newURL = response.encodeRedirectRUL("指向一个跳转路径")
//3.重定向Servlet
response.sendRedirect(newURL)
*/
Session实战保存验证码
1.需要到一个包ValidateCode.jar【验证码的jar包】,并添加到工程中【lib目录需要建在WEB-INF】
package com.qfedu.ValidateCode;
import cn.dsna.util.images.ValidateCode;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet(name = "CreateCodeServlet",value="/createCode")
public class CreateCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ValidateCode vc = new ValidateCode(200,30,4,10);
String code = vc.getCode();
System.out.println("生成的验证码:"+code);
//对验证码进行存储
HttpSession session = request.getSession();
session.setAttribute("code",code);
//直接将验证码响应该客户端
vc.write(response.getOutputStream());
}
}
页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>管理员登录</title>
</head>
<body>
<form action="/cas/loginMgr" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<!--图片的src路径需要是对servlet的路径页面加载的时候会加载对应servlet,然后产生验证码-->
验证码:<input type="text" name="inputVCode"/><img src="/cas/createCode"/><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
登录servlet
package com.qfedu.ValidateCode;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "LoginMgrServlet",value = "/loginMgr")
public class LoginMgrServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.处理乱码
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//2.获取参数
String username = request.getParameter("username");
String password = request.getParameter("password");
String inputVCode = request.getParameter("inputVCode");
//将验证码已经存储在Session域中,需要获取
String code = (String)request.getSession().getAttribute("code");
if (inputVCode.equalsIgnoreCase(code)){
if(username.equals("zhangsan") && password.equals("123456")){
System.out.println("登录成功");
//重定向之后如果需要继续使用某些数据,可以使用session
// response.sendRedirect("");
}else{
request.getRequestDispatcher("log.html").forward(request,response);
}
}else{
request.getRequestDispatcher("log.html").forward(request,response);
}
}
}