一、案例一:记录用户的上次访问时间
运用场景:QQ异地登录
1.1、流程及技术分析
会话技术(相当于打电话)
会话的生命周期:
会话开启:打开浏览器(相当于拨通电话)
会话结束:关闭浏览器(相当于挂断电话)
会话有什么作用:
存储数据
会话范围:
会话开启 ————》 会话结束 (会话一旦开启,只要不关闭会话,中间的通话都是会话数据)
会话的数据存储在什么位置?
会话的分类:
Cookie: 会话数据存储在浏览器端
Session: 会话数据存储在服务器端
会话是针对浏览器的某次请求开启,只要不关闭浏览器就是一次会话。
1.2、cookie
1.2.1、cookie简述
Cookie: 直译 小饼干、 小甜点
Cookie说白了就是浏览器向服务器传递一张小纸条
服务器负责:
1.写纸条
2.解析数据(小纸条)
浏览器负责:
1.存储小纸条
2.将小纸条发送给服务器
1.2.2、cookie入门案例
1.2.2.1、入门案例1:服务器给浏览器写cookie
package com.zql.servlet;
import java.io.IOException;
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;
@WebServlet("/demo1")
public class DemoServlet1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//服务器给浏览器写cookie
//1.创建小纸条(cookie)
Cookie cookie1 = new Cookie("name", "Daniel");
Cookie cookie2 = new Cookie("name", "Wendy");
Cookie cookie3 = new Cookie("name", "Kendra");
Cookie cookie4 = new Cookie("name", "Jenny");
//将cookie发送给浏览器
response.addCookie(cookie1);
response.addCookie(cookie2);
response.addCookie(cookie3);
response.addCookie(cookie4);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Cookie什么情况下销毁?
结论1:服务器关闭不影响cookie数据的销毁
结论2:浏览器关闭,cookie销毁
1.2.2.2、入门案例2:浏览器把cookie传递给服务器,服务器解析
package com.zql.servlet;
import java.io.IOException;
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;
@WebServlet("/demo2")
public class DemoServlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解析Cookie
//1.获取Cookie
Cookie[] cookies = request.getCookies();
//遍历 遍历之前先进行判断,判断是否为空
if(cookies != null) {
for (Cookie cookie : cookies) {
//获取Cookie的名称 和 值
String name = cookie.getName();
String value = cookie.getValue();
System.out.println("获得cookie的名称为"+name+",对应的值为"+value);
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
可以再次证明: 浏览器关闭,cookie销毁
1.2.3、cookie原理
1.2.4、cookie使用注意
Cookie是由http协议制定的,不仅仅javaee能用cookie,移动端,平板电脑也可以使用。
Cookie的使用是有上限的
一个网站只能在某一个浏览器中,最多保存20~30个cookie。
一个浏览器保存的cookie数量也是有上限,最多保存100~300个cookie。
如果超出了保存上限,会导致新的cookie无法保存。
应用场景:
七天自动登录(将用户名和密码保存在cookie中)
浏览历史记录(将商品id保存在cookie中)
1.2.5、cookie种类
Cookie分类:
会话级别cookie:cookie保存在浏览器端,会随着浏览器的关闭,cookie销毁。
持久化级别cookie:cookie保存在浏览器端,指定在磁盘上。可以去设置cookie的生存时间
方法名 | 描述 |
---|---|
setMaxAge(int expiry) | 设置cookie的生存时间。 单位:秒。 在这里int的取值可以是:-1 默认是会话级别的cookie 0 但是cookie立即被销毁 1 持久化级别的cookie 存活时间是1秒 如果没有设置,cookie只缓存浏览器缓存中,浏览器关闭,cookie删除。 如果设置有效时间,在时间范围内,cookie被写入到浏览器端,关闭浏览器下次访问仍可获得,直到过期。 |
如果是七天自动登录setMaxAge(72460*60)
1.3、实现案例(用户的上次访问时间)
(1)结构如下:
(2)代码实现:
VisitServlet.java
package com.zql.servlet;
import java.io.IOException;
import java.util.Date;
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;
@WebServlet("/visit")
public class VisitServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取当前的时间
Date date = new Date();
//获取毫秒值
long time = date.getTime();
//创建Cookie,把当前时间存储到Cookie中
Cookie cookie = new Cookie("lastTime", time+"");
//添加Cookie,然后写给浏览器
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
ShowServlet.java
package com.zql.servlet;
import java.io.IOException;
import java.util.Date;
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;
@WebServlet("/show")
public class ShowServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理乱码问题
response.setContentType("text/html;charset=utf-8");
Cookie lastTime = null;
//获取Cookie
Cookie[] cookies = request.getCookies();
//判断Cookie是否为空
if(cookies != null) {
for (Cookie cookie : cookies) {
//要获取自己想要的Cookie名称
if("lastTime".equals(cookie.getName())) {
lastTime = cookie;
}
}
}
//判断Cookie是否为空
if(lastTime != null) {
String time = lastTime.getValue();
//time是一个毫米值
//sout.out.println(time);
Date date = new Date(Long.parseLong(time));
System.out.println(date);
response.getWriter().write("您上次访问的时间是"+date.toLocaleString());
}else {
response.getWriter().write("兄台,您是第一次访问");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
先访问: http://localhost:8080/servlet4/visit
再次访问: http://localhost:8080/servlet4/show
显示:
二、案例二:一次性验证码的校验
2.1、讲解:session
2.1.1、session的简述
会话技术:把数据保存在服务器端的会话技术。
区别:
Cookie保存在浏览器端:不会占用服务器内存,不安全,数据量/保存数量有上限
Session保存在服务器端:占用服务器内存,安全,数据量/保存数量无上限。
数据共享范围:
会话范围。
特点:
针对某个浏览器的N次请求
2.1.2、session入门案例
2.1.2.1、入门-获取session查看执行现象
package com.zql.servlet;
import java.io.IOException;
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;
@WebServlet("/demo")
public class DemoServlet0 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
System.out.println(session);
}
}
是因为第一次调用request.getSession();方法时,在响应头创建了一个cookie,他的名字叫JSESSIONID的cookie
(cookie是会话级别的cookie,浏览器关闭,cookie销毁。)
第二次去访问时,JSESSIONID消失
2.1.2.2、入门案例-使用session进行数据共享
Session就是一个域对象
(1)创建DemoServlet1.java
package com.zql.servlet;
import java.io.IOException;
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;
@WebServlet("/demo1")
public class DemoServlet1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取session
HttpSession session = request.getSession();
//存数据
session.setAttribute("name", "Daniel");
}
}
(2)创建DemoServlet2 .java
package com.zql.servlet;
import java.io.IOException;
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;
@WebServlet("/demo2")
public class DemoServlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取session
HttpSession session = request.getSession();
//取存的数据
Object name = session.getAttribute("name");
System.out.println(name);
}
}
(3)打开F12开发者模式 浏览器访问:http://localhost:8080/servlet5/demo1
(4)打开F12开发者模式 浏览器访问:http://localhost:8080/servlet5/demo2
2.1.3、session的原理
2.1.4、session的生命周期
Session生命周期:
创建: 第一次调用request.getSession();
销毁:
1.服务器非正常关闭时销毁session(服务器正常关闭不会销毁,因为session数据是存在服务器端的,和浏览器无关)
D:\develop\apache-tomcat-8.5.29\work\Catalina\localhost\servlet5(序列化session的位置)
2.手动销毁
//销毁session
session.invalidate();
3.默认不操作,超过30分钟自动销毁(文件位置在Tomcat配置文件web.xml中)
ServletContext域对象(作用范围最大的域对象)
创建: 服务器启动
销毁: 服务器关闭
Request域对象(一次请求,一次响应)
创建: 请求过来时
销毁: 响应结束
2.1.5、session常用API
方法声明 | 功能描述 |
---|---|
String getId() | 用于返回与当前HttpSession对象关联的会话标识号 |
long getCreationTime() | 返回Session创建的时间,这个时间是创建Session的时间与1970年1月1日00:00:00之间时间差的毫秒表示形式 |
long getLastAccessedTime() | 返回客户端最后一次发送与Session相关请求的时间,这个时间是发送请求的时间与1970年1月1日00:00:00之间时间差的毫秒表示形式 |
void setMaxInactiveInterval(int interval) | 用于设置当前HttpSession对象可空闲的以秒为单位的最长时间,也就是修改当前会话的默认超时间隔 |
boolean isNew() | 判断当前HttpSession对象是否是新创建的 |
void invalidate() | 用于强制使Session对象无效 |
ServletContext getServletContext() | 用于返回当前HttpSession对象所属于的WEB应用程序对象,即代表当前WEB应用程序的ServletContext对象 |
void setAttribite(String name,Object value) | 用于将一个对象与一个名称关联后存储到当前的HttpSession对象中 |
String getAttribute(String name) | 用于从当前HttpSession对象中返回指定名称的属性对象 |
void removeAttribute(String name) | 用于从当前HttpSession对象中删除指定名称的属性 |
2.2、案例流程分析
2.3、案例代码实现
(1)导入素材
(2)代码实现:
完整:
package com.zql.servlet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/vs")
public class VerifyCodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//生成图片
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1 高和宽
int height = 30;
int width = 60;
String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
Random random = new Random();
//2 创建一个图片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//3 获得画板
Graphics g = image.getGraphics();
//4 填充一个矩形
// * 设置颜色
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
g.setColor(Color.WHITE);
g.fillRect(1, 1, width-2, height-2);
// * 设置字体
g.setFont(new Font("宋体", Font.BOLD|Font.ITALIC, 25));
//让它拼接我们的验证码
String msg = "";
//5 写随机字
for(int i = 0 ; i < 4 ; i ++){
// 设置颜色--随机数
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
// 获得随机字
int index = random.nextInt(data.length());
String str = data.substring(index, index + 1);
msg+=str;
// 写入
g.drawString(str, width/6 * (i + 1), 20);
}
//将验证码存储到session域对象中
request.getSession().setAttribute("msg", msg);
//6 干扰线
for(int i = 0 ; i < 3 ; i ++){
// 设置颜色--随机数
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
// 随机绘制先
g.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width),random.nextInt(height));
// 随机点
g.drawOval(random.nextInt(width), random.nextInt(height), 2, 2);
}
//end 将图片响应给浏览器
ImageIO.write(image, "jpg", response.getOutputStream());
}
}
(3)
(4)创建servlet
package com.zql.servlet;
import java.io.IOException;
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;
@WebServlet("/check")
public class CheckServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取输入框中的验证码
String code = request.getParameter("code");
//获取session域中的验证码
String msg = (String) request.getSession().getAttribute("msg");
//清除验证码
request.getSession().removeAttribute("msg");
//判断是否一致
if(code != null && msg != null && code.equalsIgnoreCase(msg)) {
System.out.println("兄呆,您输入的验证码正确");
}else {
System.out.println("兄呆,您是个猪吧,请重新输入!!!");
}
}
}
最终显示: