十六、Cookie&Session&JSP

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;,好像有个隐藏的变量在前面。

发布了65 篇原创文章 · 获赞 1 · 访问量 1471

猜你喜欢

转载自blog.csdn.net/weixin_45097731/article/details/104726250