“从来不跌倒不算光彩,每次跌倒后能再站起来,才是最大的荣耀。”你好,我是梦阳辰,快和我一起学习起来吧!
01.概述
会话技术
Web应用中的会话过程类似于生活中的打电话过程,它指的是一个客户端(浏览器)于web服务器之间连续发生的一系列请求和响应的过程。
会话:一次会话中包含多次请求和响应。
—次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止。
功能:在一次会话的范围内的多次请求间,共享数据。
方式:
客户端会话技术:Cookie
服务器端会话技术: Session
02.Cookie快速入门
1.概念:客户端会话技术,将数据保留在客户端。
快速入门
使用步骤:
1.创建Cookie对象,绑定数据。
new Cookie(String name, String value)
2.发送Cookie(发给浏览器)
reponse.addCookie(Cookie cookie);
3.获取Cookie,拿到数据(浏览器将cookie包装在请求中,服务器就可以拿到cookie)
Cookie[] request.getCookies();
测试:
@WebServlet("/ServletCookieTest1")
public class ServletCookieTest1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie对象
Cookie c =new Cookie("name","meng");
//发送Cookie
response.addCookie(c);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
@WebServlet("/ServletCookieTest2")
public class ServletCookieTest2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//3.获取Cookie
Cookie[] cs = request.getCookies();
if(cs!=null){
for (Cookie c :cs){
String name = c.getName();
String value = c.getValue();
System.out.println(name+":"+value);
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
结果:访问1,再访问2后。
03.Cookie原理分析与应用
1.原理图解:
2.cookie能否发送多个cookie?
可以!
可以创建多个Cookie对象,使用response调用多次addCookie方法发送Cookie即可。
@WebServlet("/ServletCookieTest3")
public class ServletCookieTest3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie对象
Cookie c1 =new Cookie("name","meng");
Cookie c2 =new Cookie("firstName","YangChen");
//发送Cookie
response.addCookie(c1);
response.addCookie(c2);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
3.cookie在浏览器中保存多长的时间?
1.默认情况下,当浏览器关闭后,Cookie数据被销毁(在浏览器内存中)。
2.在浏览器关闭后,仍然保存下来。
持久化存储:
setMaxAge(int seconds);
1.正数:将Cookie数据写到硬盘文件中,持久化存储,cookie存活时间。
2.负数:默认值。
3.零:删除cookie信息。
@WebServlet("/ServletCookieTest4")
public class ServletCookieTest4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie对象
Cookie c =new Cookie("msg","setMaxAge");
//2.设置存活时间
c.setMaxAge(60);
//发送Cookie
response.addCookie(c);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
4.cookie能不能存储中文数据?
Tomcat8之前cookie中不能支持中文数据。
需要将中文数据转码------------------一般用url编码。
value = URLEncoder.encode(value,"utf-8");
cookie.setValue(value);
//输出时还需要解码
value =URLDecoder.decode(value,"utf-8");
Tomcat8之后完全没得问题(但对特殊字符还是不行)。
5.cookie数据共享范围有多大?
假设在一个tomcat服务器中,部署了多个web项目,那么在这些项目中cookie能不能共享?
默认情况下cookie不能共享。
setPath(String path):设置cookie的获取范围。
默认情况下,设置当前的虚拟目录(项目)。
如果要共享,则可以将path设置为“/”。(根路径)
不同的tomcat服务器间Cookie共享问题?
setDomain(String path):
如果设置以及域名相同,那么多个服务器之间cookie可以共享
setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie
可以共享
Cookie的特定和作用
1.cookie存储数据在客户端浏览器(不安全)。
2.浏览器对于单个cookie的大小有限制(4kb)以及同一个域名下的总cookie数量也有限制。
3.cookie一般用于存储少量的不太敏感数据。
4.在不登录的情况下,完成对服务器的身份识别。
04.Cookie案例
1.记录上一次访问网站的时间。
需求:
1.访问一个servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。2.如果不是第一次访问,则提示∶欢迎回来,您上次访问时间为:显示时间字符串
分析
1.可以采用cookie来完成
2.在服务器中的servlet判断是否有一个名为lastTime的cookie
有:不是第一次访问.
响应数据:欢迎回来,您上次访问时间为:2018年6月10日11:50:202.写cookie
2.没有:是第一次访问。
1.响应数据:您好,欢迎您首次访问
2.写回cookie : lastTime=2020年11月13
@WebServlet("/ServletCookieTest5")
public class ServletCookieTest5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
//1.获取所有的Cookie
Cookie[] cookies = request.getCookies();
//2.遍历Cookie数组
boolean flag= false;//没有Cookie为lastTime
if(cookies!=null&&cookies.length>0){
for(Cookie cookie :cookies){
//3.获取Cookie的名字
String name = cookie.getName();
//4.判断Cookie名称是否是:lastTime
if("lastTime".equals(name)){
flag = true;
//5.有该Cookie,则不是第一次访问
//获取当前时间的字符串,重新设置Cookie的值,重新发送Cookie
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str_date = sdf.format(date);
str_date = URLEncoder.encode(str_date,"utf-8");
cookie.setValue(str_date);
//设置Cookie的存活时间
cookie.setMaxAge(60*60*24*30);//一个月
response.addCookie(cookie);
//响应数据
//获取Cookie的value,时间
String value = cookie.getValue();
value = URLDecoder.decode(value,"utf-8");
out.print("欢迎回来,你上次访问的时间是:"+value);
break;
}
}
}
if(cookies==null||cookies.length==0||flag==false){
//没有,则是第一次访问
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str_date = sdf.format(date);
str_date = URLEncoder.encode(str_date,"utf-8");
Cookie cookie = new Cookie("lastTime",str_date);
//设置Cookie的存活时间
cookie.setMaxAge(60*60*24*30);//一个月
response.addCookie(cookie);
out.print("你好,欢迎你首次访问!");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
05.Session
1.概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。(HttpSession)
当浏览器访问web服务器时,Servlet容器就会创建一个Session对象和ID属性,其中Session对象就相当于病历档案,ID就相当于就诊卡号。当客户端后续访问服务器时,只要将标识号传递给服务器,服务器就能判断出该请求是那个客户端发送的,从而选择与之对应的session对象为其服务。
由于客户端需要接收,记录和回送Sesssion对象的ID属性,因此,Session需要借助Cookie技术来传递ID属性。
在一次会话中:cookie保存了用户的浏览数据,session对象同样也保存了用户浏览数据,通过ID属性确认用户的身份。
2.快速入门:
2.1获取HttpSession对象:
HttpSession session = request.getSession();
2.2使用HttpSession对象:
Object getAttribute(String name);
void setAttrebute(String name,Object value);
void removeAttribute(String name);
@WebServlet("/ServletSessionTest1")
public class ServletSessionTest1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
//存储数据
session.setAttribute("user","MengYangChen");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
@WebServlet("/ServletSessionTest2")
public class ServletSessionTest2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取session对象
HttpSession session = request.getSession();
//取数据
String user = (String)session.getAttribute("user");
System.out.println(user);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
06.Session原理分析与应用
session是依赖于cookie的。
1.当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
默认认情况下不是。(因为服务器依靠ID属性确认客户端为哪个session对象,而ID属性保存在客户端的cookie中,当浏览器关闭时,cookie也就默认删除)
如果需要相同,则可以创建cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
Cookie c = new Cookie( "SESSIONID" ,session.getId());
c.setMaxAge(60*60) ;
response.addcookie(c);
测试:
@WebServlet("/ServletSessionTest3")
public class ServletSessionTest3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取session
HttpSession session = request.getSession();
//期望客户端关闭后,session也能相同
Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);//1小时
response.addCookie(c);
System.out.println(session);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
2.客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
不是同一个,但是要确保数据不丢失。
session的钝化:在服务器正常关闭之前,将session对象序列化到硬盘上。
session的活化:在服务器启动后,将session文件转化为内存中的session对象即可。
Tomcat已经为我们实现了钝化和活化的过程。
3. session的失效时间?
服务器关闭。
sesion对象调用invalidate()方法。
Tomcat服务器session默认失效时间30分钟(可以在配置文件中配置)。
4.Seesion的特点
用于存储一次会话的多次请求数据,存在于服务器端。
session可以存储任意类型,任意大小的数据。
5.session与cookie的区别:
session存储数据在服务器端,Cookie在客户端。
session没有数据大小限制,Cookie有。
sesion数据安全,Cookie相对于不安全。
07.Session验证码案例
案例需求:
1.访问带有验证码的登录页面login.jsp。
2.用户输入用户名,密码以及验证码。
如果用户名和密码输人有误,跳转登录页面,提示:用户名或密码错误。
如果验证码输入有误,跳转登录页面,提示:验证码错误。
如果全部输人正确,则跳转到主页success.jsp,显示∶用户名,欢迎您。
分析:
登录:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户登录</title>
<script src="../tool/jquery-3.5.1.min.js"></script>
</head>
<body>
<form class="fm">
<div>
<label>用户:</label>
<input type="text" name="userName" id="userName"/>
</div>
<div>
<label>密码:</label>
<input type="password" name="passWord" id="passWord"/>
</div>
<div>
<label>验证码:</label>
<input type="text" name="checkCode" id="checkCode"/><br>
<img src="/First/IdentifyingCodeServlet" id="img"></img>
</div>
<input type="button" id="btn" value="确认">
</form>
<p style="color: red" ></p>
<script>
$(function () {
$("img").click(function () {
this.src="/First/IdentifyingCodeServlet?time="+new Date().getTime();//加上时间戳欺骗浏览器缓存
});
$("#btn").click(function () {
var fmData = $(".fm").serialize();
$.get(
"/First/LoginServlet",
fmData,
function (data) {//使用ajax需要在前端实现跳转页面
$("p").html(data);
}
);
});
});
</script>
</body>
</html>
成功页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功页面</title>
</head>
<body>
<h1><%=request.getSession().getAttribute("userName") %>,欢迎你!</h1>
</body>
</html>
后端:
package IdentifyingCode;
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;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet("/IdentifyingCodeServlet")
public class IdentifyingCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 100;
int height = 50;
//1.创建一对象,在内存中的图片(验证码图片对象)
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//2.美化图片
//2.1填充背景色
Graphics g = image.getGraphics();
g.setColor(Color.pink);
g.fillRect(0,0,100,50);//填充矩形
//2.2画边框
g.setColor(Color.yellow);
g.drawRect(0,0,width-1,height-1);
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
//生成随机角标
Random ran = new Random();
StringBuilder sb = new StringBuilder();//存储验证码的值
for(int i=1;i<=4;i++){
int index = ran.nextInt(str.length());
char ch = str.charAt(index);//随机字符
sb.append(ch);
//2.3写验证码
g.setColor(Color.blue);
g.drawString(""+ch,width/5*i,height/2);
}
String checkCode_session = sb.toString();
//将验证码存入session
request.getSession().setAttribute("checkCode_session",checkCode_session);
//2.4画干扰线,防识别
//随机生成坐标点
for(int i=0;i<8;i++){
int x1 =ran.nextInt(width);
int x2 =ran.nextInt(width);
int y1 =ran.nextInt(height);
int y2 =ran.nextInt(height);
g.setColor(Color.green);
g.drawLine(x1,y1,x2,y2);
}
//3.将图片输出到页面展示
ImageIO.write(image,"jpg",response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
package IdentifyingCode;
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;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置request编码
request.setCharacterEncoding("utf-8");
//2.获取参数Map(简化获取参数)
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
String userName = request.getParameter("userName");
String passWord = request.getParameter("passWord");
String checkCode = request.getParameter("checkCode");
//先判断验证码是否正确
//先获取生成的验证码
HttpSession session = request.getSession();
String checkCode_session =(String)session.getAttribute("checkCode_session");
//用完就删除验证码
session.removeAttribute("checkCode_session");
if(checkCode_session!=null&&checkCode_session.equalsIgnoreCase(checkCode)) {//忽略大小写的比较
//判断用户名和密码是否一致
if("MengYangChen".equals(userName)&&"123456".equals(passWord)){//简单书写,原则需要查询数据库
//登录成功
//存储信息,用户信息
session.setAttribute("userName",userName);
//重定向到sussess.jsp
response.sendRedirect(request.getContextPath()+"/html/success.jsp");
}else{//登录失败
//存储提示信息到request
//request.setAttribute("login_error","用户名或密码错误!");
out.print("用户名或密码错误!");
//转发到登录页面
//request.getRequestDispatcher("html/login.jsp").forward(request,response);
}
}else{
//验证码不一致
//存储提示信息到request
//request.setAttribute("cc_error","验证码错误");
out.print("验证码错误!");
//转发到登录页面
//request.getRequestDispatcher("/html/login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
结果: