02_会话技术_概述
Cookie:是数据于存在客户端
(键,值)
Session:是存在于浏览器
直到有一方断开为止是指:要么浏览器断开,要么服务器关闭
03_会话技术_快速入门
在服务器【响应】的时候,服务器的【资源A】会创建一个Cookie对象并绑定数据发送给【浏览器】,浏览器收到Cookie对象之后携带这个Cookie对象请求服务器【资源B】,服务器【获取Cookie对象】拿到数据。
响应:
responst
请求:
request
原理:
资源A
资源B
04_Cookie_原理分析
3. 实现原理
* 基于响应头set-cookie和请求头cookie实现
服务器先把数据存在Cookie上,发送给客户端;客户端收到并保存缓存Cookie数据,然后又向另一个服务器资源发出请求,这个请求是携带Cookie的
Cookie细节
05_细节1_发送多个Cookie
4. cookie的细节
1. 一次可不可以发送多个cookie?
* 可以
* 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。
addCookie方法
:发送Cookie给浏览器
06_细节2_Cookie存活时间
2. cookie在浏览器中保存多长时间?
1. 默认情况下,当浏览器关闭后,Cookie数据被销毁
2. 持久化存储:
* setMaxAge(int seconds)
1. 正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
2. 负数:默认值
3. 零:删除cookie信息
07_细节3_Cookie存储中文
3. cookie能不能存中文?
* 在tomcat 8 之前 cookie中不能直接存储中文数据。
* 需要将中文数据转码---一般采用URL编码(%E3)
* 在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
【重要】特殊字符还是不支持,建议使用URL编码存储,URL解码解析
08_细节4_Cookie共享
1、不同Web项目,虚拟目录不同。不同web项目Cookie可以共享嘛?
- 默认情况下Cookie不能共享:
创建发送Cookie对象,不设置setPath相当于setPath设置了当前虚拟目录,即,http://localhost:80/day16
- 共享Cookie:
设置setPath为”/“,即,http://localhost:80/
不管你什么虚拟目录都会
2、不同tomcat服务器间的Cookie怎么共享?
setDomain(String path):path设置二级域名
09_特点&作用
5. Cookie的特点和作用
1. cookie存储数据在客户端浏览器
2. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)
* 作用:
1. cookie一般用于存出少量的不太敏感的数据
2. 在不登录的情况下,完成服务器对客户端的身份识别
不太敏感:Cookie存储到客户端本地不安全
“在不登录的情况下,完成服务器对客户端的身份识别” 是什么意思?
首先,网站的页面如果仅仅是写前端显示是没有功能的(有点绝对)。那么,如果你想在没有登陆的百度页面下设置什么什么功能,比如:什么搜索设置啊等等,这些数据其实是后台发送Cookie给浏览器保存的,服务器知道获取Cookie什么键值对,就照着干什么事情。这个身份识别意思是:浏览器一请求服务器某个资源,某个资源专门发送Cookie的,然后它发送Cookie给你,你不用登陆,但是服务器也知道你是谁。
10、案例:记住上一次访问时间
原来消息体就是写给客户端html文档内容。
一般啊,读取方面一般用request,写出方面用response
package cn.itcast.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 javax.xml.crypto.Data;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
@WebServlet("/ServletCookie")
public class ServletCookie extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置消息体的数据格式和编码格式
response.setContentType("text/html;charset=utf-8");
boolean flag = false;
//1、获取所有的Cookie对象
Cookie[] cookies = request.getCookies();
//2、遍历Cookie,判断是否存在lastTime名称
for (Cookie cookie : cookies) {
if (cookie != null && cookies.length > 0) {
String name = cookie.getName();//获取cookie键名
if ("lastTime".equals(name)) {//判断名称是否为lastTime
//有,上一次访问过了,标记一下
flag = true;
//3、更新Cookie的值
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");//设置时间格式
String str_date = sdf.format(date);//把Date格式换成字符串
//把Cookie值转换url编码值
str_date = URLEncoder.encode(str_date, "utf-8");
//设置cookie值
cookie.setValue(str_date);
//4、设置cookie存活时间
cookie.setMaxAge(60 * 60 * 24 * 30);//1个月
//5、发送Cookie给客户端
response.addCookie(cookie);
//6、响应客户端信息
//6.1 获取Cookie值(url编码的)
String value = cookie.getValue();
//6.2 URL解码value
value = URLDecoder.decode(value, "utf-8");
//6.3 响应信息
response.getWriter().write("<h1>欢迎回来,您上次访问的时间为:" + value + "</h1>");
break;//找到lastTime名称就没必要遍历了
}
}
}
//没有Cookie,第一次访问
if (cookies == null || cookies.length == 0 || flag == false) {
//1、设置cookie值
//1.1 获取时间
String strs_date = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date());
//2、给cookie值url编码
strs_date = URLEncoder.encode(strs_date, "utf-8");
//3、创建Cookie对象,并赋键对值
Cookie cookie = new Cookie("lastTime", strs_date);
//4、设置Cookie存活时间
cookie.setMaxAge(60 * 60 * 24 * 30);//1个月
//5、发送Cookie
response.addCookie(cookie);
//6、响应消息给浏览器
response.getWriter().write("<h1>您好,欢迎您首次访问XXX</h1>");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
总结一下:
- 1、request读取表单请求参数的中文乱码
(表单提交中文信息,request读取乱码)
解决:
resquest.setCharsetEncoding(“utf-8”);
- 2、response输出流写到浏览器页面
(response直接输出中文,浏览器显示乱码)
解决:
response.setContentType(“test/html;charset=utf-8”);
- 3、response发送Cookie对象的value中特殊字符乱码
(servlet发送有特殊字符的Cookie值给浏览器,当servlet获取时,是乱码)
解决:
URL编码:URLEncoder.encode(需要编码的cookie值,“utf-8”)
URL解码:URLDecoder.decode(需要解码的cookie值,“utf-8”)
然后,我发现这个URLEncoder.encode跟之前那个工具类源码出现过。
使用场景:
表单请求发送地址,服务器截取”九尾.jpg“并读取本地的”九尾.jpg“文件,写出给浏览器的”九尾.jpg“中的”九尾“进行了url编码给浏览器自动解析。
12_JSP_概念
1. 概念:
* Java Server Pages: java服务器端页面
* 可以理解为:一个特殊的页面,其中既可以直接定义html标签,又可以定义java代码
* 用于简化书写!!!
13_JSP_原理
2. 原理
* JSP本质上就是一个Servlet
JSP本质上就是一个Servlet?
因为他、它继承了HttpServlet
怎么个简化法?
以前sevrlet类响应信息到浏览器页面,要自己动手调用write。你在jsp直接写HTML代码,就可以实现显示在浏览器页面了。Jsp底层使用wirte自动转换了html代码。
14_JSP_脚本
3. JSP的脚本:JSP定义Java代码的方式
1. <% 代码 %>:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
2. <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置。[成员变量和成员方法]
3. <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。【很像print输出打印一样,而页面是控制台】
15_JSP_入门学习_内置对象
1. JSP的内置对象:
* 在jsp页面中不需要获取和创建,可以直接使用的对象
* jsp一共有9个内置对象。
* 今天学习3个:
* request
* response
* out:字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似
* response.getWriter()和out.write()的区别:
* 在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。
* response.getWriter()数据输出永远在out.write()之前
原理:
一般我们不用response.getWrite()在JSP使用,会打乱布局。
16_JSP_案例_改造Cookie案例
改了哪里?
- 删除:response.setContentType(“text/html;charset=utf-8”);
- response.getWrite()改out
- 使用<% %>截取,把out.XXX变成html元素。
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.net.URLEncoder" %>
<%@ page import="java.net.URLDecoder" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
boolean flag = false;
//1、获取所有的Cookie
Cookie[] cookies = request.getCookies();
//2、遍历Cookie,判断是否存在lastTime名称
for (Cookie cookie : cookies) {
if (cookie != null && cookies.length > 0) {
String name = cookie.getName();
if ("lastTime".equals(name)) {//判断名称是否为lastTime
//有,上一次访问过了,标记一下
flag = true;
//3、更新Cookie的值
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");//设置时间格式
String str_date = sdf.format(date);//把Date格式换成字符串
//把Cookie值转换url编码值
str_date = URLEncoder.encode(str_date, "utf-8");
//设置cookie值
cookie.setValue(str_date);
//4、设置cookie存活时间
cookie.setMaxAge(60 * 60 * 24 * 30);//1个月
//5、发送Cookie给客户端
response.addCookie(cookie);
//6、响应客户端信息
//6.1 获取Cookie值(url编码的)
String value = cookie.getValue();
//6.2 URL解码value
value = URLDecoder.decode(value, "utf-8");
%>
<%--//6.3 响应信息--%>
<h1>欢迎回来,您上次访问的时间为:<%= value %></h1>
<%
break;//找到lastTime名称就没必要遍历了
}
}
}
//没有Cookie,第一次访问
if (cookies == null || cookies.length == 0 || flag == false) {
//1、设置cookie值
//1.1 获取时间
String strs_date = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date());
//2、给cookie值url编码
strs_date = URLEncoder.encode(strs_date, "utf-8");
//3、创建Cookie对象,并赋键对值
Cookie cookie = new Cookie("lastTime", strs_date);
//4、设置Cookie存活时间
cookie.setMaxAge(60 * 60 * 24 * 30);//1个月
//5、发送Cookie
response.addCookie(cookie);
%>
<%-- //6、响应消息给浏览器--%>
<h1>您好,欢迎您首次访问XXX</h1>
<%
}
%>
</body>
</html>
17_会话技术_Session_快速入门
1. 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession
2. 快速入门:
1. 获取HttpSession对象:
HttpSession session = request.getSession();
2. 使用HttpSession对象:
Object getAttribute(String name) //获取值
void setAttribute(String name, Object value) //设置键对值
void removeAttribute(String name) //移除键
18_会话技术_Session_原理分析
3. 原理
* Session的实现是依赖于Cookie的。
原理图:
浏览器:请求
SessionDemo1:
第1次request.getSession()获取Session对象----->服务器没有获取Cookie(Cookie不存在)—>在内存中创建Session对象(假设id:742948a4289)—>响应给浏览器:服务器会创建Cookie对象携带着Session对象的id
浏览器:
把Cookie数据存储下来---->再下次请求中传递Cookie并携带Session对象的id
SessionDemo2:
SessionDemo2获取对象的时候会根据浏览器传过来的Session对象的id去内存中寻找有没有这个Session对象的id,有则直接引用。
所以,Session的实现是依赖于Cookie的。而且,一次会话中的session对象是同一个。
Session细节
19_会话技术_Session_细节1
1. 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
* 默认情况下。不是。
* 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。【Cookie保存在浏览器本地,所有打开的时候,还是一样】
Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);
response.addCookie(c);
20、细节2
2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
* 不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作
* session的钝化:
* 在服务器正常关闭之前,将session对象序列化到硬盘上
* session的活化:
* 在服务器启动后,将session文件转化为内存中的session对象即可。
但是,如果在IDEA里面部署项目session的活化就不会实现,因为IDEA重启服务器后,它是把work目录删除掉再创建新的work目录,所有即使有序列化session对象在本地,最终都被删除掉。
work目录:
tomcat部署和IDEA部署都有,它是服务器运行是生成并保存的动态数据。
不过大可放心,以后做项目一般不会在IDEA本地上部署,都是放在tomcat本地的wepapps里面。
21、Session_细节3_session销毁
3. session什么时候被销毁?
1. 服务器关闭
2. session对象调用invalidate() 。【自杀】
3. session默认失效时间 30分钟
选择性配置修改
<session-config>
<session-timeout>30</session-timeout>
</session-config>
选择性失效时间一般我们要设置长一点,如果在30分钟内用户没有操作而导致页面失效,这个样子用户体验很不好。
设置在哪里找到?
tomcat本地文件—>config—>web.xml
22、session特点
5. session的特点
1. session用于存储一次会话的多次请求的数据,存在服务器端
2. session可以存储任意类型,任意大小的数据
* session与Cookie的区别:
1. session存储数据在服务器端,Cookie在客户端
2. session没有数据大小限制,Cookie有
3. session数据安全,Cookie相对于不安全
session翻译做”主菜“,Cookie翻译做”小饼干“,因为大量的数据都会以session存放在服务器端。
验证码案例分析
问:
- 为什么要使用session存储验证码?
因为我们要在2次请求中共享数据,而session是适用于一次会话中多次请求存储数据;request是一次请求。使用session存储验证码,我们把session存储的值给取出来跟用户输入的验证码进行对比
- 哪2次请求?
jsp页面加载的一次请求,生成验证码的一次请求
- 为什么使用”重定向“跳转到sucess.jsp?
一般登陆都会使用重定向,但是使用重定向之后,共享数据就不能用request了,要使用session,因为重定向是2次请求,即,原始页面一次,跳转到另一个servlet一次。
- 【重要】为什么用户输入错误要使用request转发到登陆页面?
因为登陆页面和LoginServlet有数据的传输关系,即,你提交了表单,用户输入错误我就提示在登陆页面上。提示信息就是request对象域数据。如果用户输入错误,那么request的对象域数据就会在登陆页面上操作并显示,而且刚好也是一次请求一次跳转,即,提交表单请求一次。重点是,使用request跳转的登陆页面它是不会因为跳转而导致原有的页面数据丢失,好比你账号密码输入错了,浏览器就资源跳转到本页面并获取request对象域数据提示你输入错,但是你原本在页面输入的账号密码数据还在。而如果使用重定向就不一样了,它会是重新打开页面。
这是很重要的区别。这样有什么好处?
1、请求转发比重定向速度快
2、用户不小心输入1-2个字就导致全部输入,用户体验差
在案列我发现:<%= %>有点像【变量=xxx】这种赋值一样。
<%=request.getAttribute("login_error")==null?"":request.getAttribute("login_error")%>
这里并没有 int a = b>c?d:f;的样子,而是b>c?d:f;,好像有个隐藏的变量在前面。