会话的概念
用户打开浏览器,浏览不同的网页,发出多个请求,直到关闭浏览器的过程,称为一次会话(多次请求)。
3.3常用的会话技术
3.3.1 cookie
cookie是客户端(浏览器)端的技术,用户浏览的信息以键值对(key=value)的形式保存在浏览器上。如果没有关闭浏览器,再次访问服务器,会把cookie带到服务端,服务端就可以做响应的处理。
3.3.2 session
session是服务器端的技术。 服务器为每一个浏览器开辟一块内存空间,即session。由于内存空间是每一个浏览器独享的,所有用户在访问的时候,可以把信息保存在session对象中。同时,每一个session对象都对应一个sessionId,服务器把sessionId写到cookie中,再次访问的时候,浏览器会把cookie(sessionId)带过来,找到对应的session对象。
1.Cookie
Cookie是一种客户端的会话技术,它是服务器存放在浏览器的一小份数据,浏览器以后每次访问该服务器的时候都会将这小份数据携带到服务器去。
1.1.Cookie的主要作用
- 在浏览器中存放数据
- 将浏览器中存放的数据携带到服务器
1.2.我们应该学到的Cookie部分
1.我们主要是写服务器端的,主要是写向浏览器中设置cookie。
2.接收客户端的cookie。
1.3.Cookie的作用在哪?
- 记住用户名
当我们在用户名的输入框中输入完用户名后,浏览器记录用户名,下一次再访问登录页面时,用户名自动填充到用户名的输入框. - 自动登录(记住用户名和密码)
当用户在淘宝网站登录成功后,浏览器会记录登录成功的用户名和密码,下次再访问该网站时,自动完成登录功能.
以上这些场景都是使用会话cookie实现的,将上次的信息保存到了cookie中,下次直接从cookie中获取数据信息 - 保存电影的播放进度
在网页上播放电影的时候,如果中途退出浏览器了,下载再打开浏览器播放同一部电影的时候,会自动跳转到上次退出时候的进度,因为在播放的时候会将播放进度保存到cookie中
Cookie就是将一些少量的配置信息保存在"浏览器"
1.4.Cookie相关的API
- new Cookie(String name,String value); 创建Cookie
- response.addCookie(cookie); 把Cookie写给浏览器
- request.getCookies(); 获得所有的Cookie对象
- cookie.getName() 获得Cookie的key
- cookie.getValue() 获得Cookie的value
Cookie本质是请求头,响应头
cookie的其他方法
**cookie默认有效期:一次会话**
setMaxAge()方法可以设置cookie的有效期
setPath()方法可以设置cookie的路径:表示这个cookie可以在哪些路径下使用,一般会设置cookie的路径为当前项目
request.getContextPath():设置当前项目的名字,一般在setPath里面路径就是这个。important!
以下是使用cookie的一个demo
服务器端:
@WebServlet("/demo01")
public class Demo01Servlet 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 {
String name="testing";
//1.将name存储到cookie里面
//服务器是通过response里面的Set-Cookie: name=xxx将数据发送给客户端
//客户端是通过request里面的Cookie: JSESSIONID=20AC1F37C6F2DC155371CB1C5A7B63D6; name=xxx将数据携带给服务器
Cookie name1 = new Cookie("name", name);
//设置有效期
name1.setMaxAge(60*60*24*7);//单位是秒,目前表示设置七天
//设置路径
name1.setPath(request.getContextPath());//设置cookie可以使用的项目路径
//2.将cookie发送到浏览器
response.addCookie(name1);
}
}
客户端:
@WebServlet("/demo02")
public class Demo02Servlet 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[] cookies = request.getCookies();
//2.遍历cookies
if (cookies != null) {
for (Cookie c1 :
cookies) {
if (c1.getName().equals("name")) {
System.out.println(c1.getValue());
}
}
}
}
}
浏览器清除cookie:清除浏览器中的某一个cookie,只需要往浏览器存放一个同名,同path的cookie,设置他们的maxAge为0即可。
name1.setMaxAge(0);//单位是秒,设置为0表示清除某个cookie
CookieUtils工具类
public class CookieUtils {
public static Cookie createAndSetCookie(String name,String value,int time,String url){
//1.新建cookie
Cookie name1 = new Cookie(name, value);
//2.设置cookie存活时间
name1.setMaxAge(time);
//3.设置路径
name1.setPath(url);
//4.将cookie发送到浏览器
return name1;
}
public static String getCookieValue(Cookie[] cookies,String name){
//遍历cookie
if (cookies != null) {
for (Cookie c1 :
cookies) {
if (c1.getName().equals(name)){
return c1.getValue();
}
}
}
return null;//服务器端没有存储cookie
}
}
Cookie的上一次访问时间案例
@WebServlet("/cookieTest")
public class CookieTest 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();
String lastTime = CookieUtils.getCookieValue(cookies, "lastTime");
if (lastTime == null) {
//说明我是第一次访问
response.getWriter().write("你是第一次访问!!!");
}else {
//说明我不是第一次访问
response.getWriter().write("您的上次访问时间是:"+lastTime);
}
//2. 将当前时间存储到cookie中
lastTime = new SimpleDateFormat("yyyy-MM-dd/HH:mm:ss").format(new Date());
//cookie的value中不能存储空格
Cookie cookie = CookieUtils.createAndSetCookie("lastTime", lastTime, 7 * 24 * 60 * 60, request.getContextPath());
response.addCookie(cookie);
}
}
2.Session
2.1session概述
session是服务器端的技术。服务器为每一个浏览器开辟一块内存空间,即session对象。由于session对象是每一个浏览器特有的,所以用户的记录可以存放在session对象中。同时,每一个session对象都对应一个sessionId,服务器把sessionId写到cookie中,再次访问的时候,浏览器把sessionId带过来,找到对应的session对象
2.2 cookie和Session的不同
- cookie是保存在浏览器端的,大小和个数都有限制。session是保存在服务器端的, 原则上大小是没有限制(实际开发里面也不会存很大大小), 安全一些。
- cookie不支持中文,并且只能存储字符串;session可以存储基本数据类型,集合,对象等
-
2.3 Session的执行原理
1、获得cookie中传递过来的SessionId(cookie)
2、如果Cookie中没有sessionid,则创建session对象
3、如果Cookie中有sessionid,找指定的session对象
如果有sessionid并且session对象存在,则直接使用
如果有sessionid,但session对象销毁了,则执行第二步
2.3.Session的常用方法
-
Session基本使用: 作为域对象存取数据 范围: 一次会话(多次请求, 用户各自的) 不同的浏览器session不一样
-
Object getAttribute(String name) ;获取值
-
void setAttribute(String name, Object value) ;存储值
-
void removeAttribute(String name) ;移除
2.4.Session的销毁方式1.闲置三十分钟自动销毁。
2.服务器关闭。
2.1如果是正常关闭服务器,
把session钝化到服务器磁盘上,再次启动,把磁盘上的文件活化到内存里面
Session钝化:把内存中的session序列化保存到硬盘上
Session活化:从硬盘上读取序列化的session到内存中形成一个session对象
3.手动调用invalidate()方法。
2.5.Session如何在浏览器关闭的时候仍能使用?
可以手动设置JSESSIONID的cookie的存活时间
cookie的name是"JSESSIONID" ,path是“项目路径”request.getContextPath().
2.6.Session会在浏览器关闭之后销毁吗?
session没有销毁.
session基于cookie, sessionId保存到cookie里面的, 默认情况下cookie是会话级别,浏览器关闭了cookie就是消失了,也就是说sessionId消失了, 从而找不到对应的session对象了, 就不能使用了.
4.小结
-
session是服务器端的技术, 数据保存在服务器端的
-
只有在服务器端调用了requet.getSession()的时候, 才有session产生
-
session基于cookie的
- 创建session的同时 生成sessionId, 服务器自动通过Cookie的方式写给浏览器, 浏览器自己保存
- 下次的话 浏览器携带cookie(SessionId)找到对应的session使用了
解决: 自己获得sessionId, 自己写给浏览器 设置Cookie的有效时长, 这个Cookie的key必须:
JSESSIONID
验证码登陆案例
1.导入ValidateCode.jar,链接如下:
链接:https://pan.baidu.com/s/1i9TYYaOLB_Aeuo4DnUn04w
提取码:q1yg
2.在WebServlet("/yzm")中得到项目路径,并在doGet()里面编写验证码servlet代码。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.利用验证码创建验证码图片
ValidateCode validateCode = new ValidateCode(200,80,4,18);
//2.获取服务器生成的验证码
String code = validateCode.getCode();
//3.使用字节输出流将validateCode输出到浏览器
validateCode.write(response.getOutputStream());
//4.使用域对象进行数据共享,将验证码传入到LoginServlet进行验证码校验
HttpSession session = request.getSession();
session.setAttribute("value",code);
System.out.println(code);
}
3.在登录界面的servlet共享域数据,进行校验。下面是登陆界面的servlet
@WebServlet("/login")
public class LoginServlet 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.setHeader("Content-Type", "text/html;charset=UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
//获取前台传入到的验证码
String checkCode = request.getParameter("checkCode");
//进行域对象共享获取checkCodeServlet对象的验证码数据
HttpSession session = request.getSession();
String realValue = (String) session.getAttribute("value");
//下面代码是校验复选框是否选中的记住用户名
String c1 = request.getParameter("c1");
Cookie cookie = new Cookie("username", username);
cookie.setPath(request.getContextPath());
if (c1 != null) {//记住用户名,将用户名存储到cookie中
cookie.setMaxAge(7 * 24 * 60 * 60);
} else {
cookie.setMaxAge(0);
}
response.addCookie(cookie);
//校验验证码: 使用用户输入的验证码和服务器生成的验证码进行校验
if (realValue.equalsIgnoreCase(checkCode)) {
//验证码正确: 才会去校验用户名和密码
//2. 连接数据库校验用户名和密码
String sql = "select * from user where username=? and password=?";
QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
try {
User user = queryRunner.query(sql, new BeanHandler<>(User.class), username, password);
System.out.println(user);
if (user != null) {
//登录成功
//将当前用户的信息存起来:session
session.setAttribute("user", user);
//登录成功之后,要跳转到success.jsp页面,并且显示"欢迎XXX登录"
request.getRequestDispatcher("success.jsp").forward(request, response);
} else {
//登录失败
String errorMsg = "用户名或密码错误";
//将errorMsg存储到域对象中
request.setAttribute("error", errorMsg);
//跳转回到登录页面
request.getRequestDispatcher("login.jsp").forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
String errorMsg = "用户名或密码错误";
request.setAttribute("error", errorMsg);
request.getRequestDispatcher("login.jsp").forward(request, response);
//response.getWriter().write("用户名或密码错误");
}
} else {
//验证码错误
String errorMsg = "验证码错误";
request.setAttribute("error", errorMsg);
request.getRequestDispatcher("login.jsp").forward(request, response);
//response.getWriter().write("验证码错误");
}
}
}
三个域对象比较
域对象 | 创建 | 销毁 | 作用范围 | 应用场景 |
---|---|---|---|---|
ServletContext | 服务器启动 | 服务器正常关闭/项目从服务器移除 | 整个项目 | 记录网站访问次数,聊天室 |
HttpSession | 没有JSESSIONID这个cookie的时候,调 用request.getSession()方法 | session过期(默认闲置30分钟),或者调用session对象的invalidate()方法,或者服务器异常关闭 | 会话(多次请求) | 验证码校验, 保存用户登录状态等 |
HttpServletRequest | 来了请求 | 响应这个请求(或者请求已经接收了) | 一次请求 | servletA和jsp(servletB)之间数据传递(转发的时候存数据) |
Jsp里面编写Java代码三种方式
我们可以通过JSP脚本在JSP页面上编写Java代码. 一共有三种方式:
类型 | 翻译成Servlet对应的部分 | 注意 |
---|---|---|
<%…%>:Java程序片段 | 翻译成Service()方法里面的内容, 局部的 | |
<%=…%>:输出表达式 | 翻译成Service()方法里面的内容,相当于调用out.print() | 输出表达式不能以;结尾 |
<%!..%>:声明成员变量(肯定不用) | 翻译成Servlet类里面的内容 |
第一种和第二种通过查看是在jsp.service里面,是局部变量,第三种是成员变量层次。
cookie,session,jsp思维导图链接如下
链接:https://pan.baidu.com/s/1fC3vhPKgGgAJZ2NcIgbT3Q
提取码:i923