03-JavaWeb开发最详细的Cookie&Session分析

Posted ahcfl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了03-JavaWeb开发最详细的Cookie&Session分析相关的知识,希望对你有一定的参考价值。

typora-copy-images-to: img
typora-root-url: img

知识回顾

request&http&response&ServletContext

1.request域对象:一次请求和响应使用。
用来存储数据setAttribute(name,value) 获取数据getAttribute(name) 删除数据

2.http响应报文协议:
响应行:状态码 200 OK  302 重定向  404找不到资源 500 服务器异常 304 浏览器缓存
响应头:key:value    
refresh ---- 秒数;url=服务器地址
content-type---告知浏览器文件的MIME类型(文件在服务器中的文件类型 text/plain  text/html)
			location:结合302重定向
			content-disposition:告知浏览器以附件下载:“attachment;filename=文件名”
响应体:
		getWriter()响应字符数据
		getOutputStream()响应字节数据
		
3.response对象:服务器响应给浏览器数据的对象
	1)setStatus(状态码)
	2)setHeader(key,value);  setContentType("text/html;charset=utf-8"); 
	   sendRedirect()重定向
	   
4.ServletContext:域对象,表示整个web项目,并且每个web项目只有一个ServletContext对象,
tomcat启动创建对象,关闭tomcat对象消失。多次请求和响应

Arrays的asList方法【掌握】

注意一:

1.使用数组工具类Arrays中的asList方法将数组转换为集合,因为集合的数据是来自于数组,数组长度固定不变,所以这里要求集合的长度不能改变
2.如果将基本数据类型的数组转换为集合,那么数组类型不能是基本数据类型,必须是包装类类型

注意二:

包装类缓冲池 byte 常量池 :
针对byte范围的数据,jvm专门单独开辟一个byte常量池。其实就是一个数组。
查阅源码,针对-128到127之间的数据做了一个数据缓冲池,
如果数据是该范围内的,每次并不创建新的空间。直接从数组中拿数据。反之,需要创建新的空间。

例如:Integer的数据直接赋值,如果在-128到127之间,会直接从缓冲池里获取数据

package com.itheima.sh.demo_02;

public class Demo01 {
    public static void main(String[] args) {
        //包装类面试题
        Integer i1 = new Integer(50);
        Integer i2 = new Integer(50);
        System.out.println(i1 == i2); //false  凡是new的,都走堆内存中创建一块新的空间

        Integer i3 = new Integer(500);
        Integer i4 = new Integer(500);
        System.out.println(i3 == i4); //false
--------------------------------------------------------------------------------
// 发生了自动装箱 ,实现原理:Integer static Integer valueOf(int i)
// 返回一个表示指定的 int 值的 Integer 实例
/*
            源码:
 class Integer{
	//Integer类中的成员内部类
	private static class IntegerCache{
		static final int low = -128;
		static final int high;
		static final Integer cache[];
		//静态代码块
		static {
			    // high value may be configured by property
			    int h = 127;
			    String integerCacheHighPropValue =
				sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
			    if (integerCacheHighPropValue != null) {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
			    }
			    high = h;

			    cache = new Integer[(high - low) + 1];
			    int j = low;
			    for(int k = 0; k < cache.length; k++)
				cache[k] = new Integer(j++);
			}
			
	    //上述代码调用这个函数创建
        public static Integer valueOf(int i) {
           assert IntegerCache.high >= 127;
           //i的值在-128和127之间
           if (i >= IntegerCache.low && i <= IntegerCache.high){	   
                    /*如果i在-128和127之间,则执行这个return语句,将i的值存在
                    某个数组空间中,下次i的值相同情况下,继续返回相同空间的值*/
   			 return IntegerCache.cache[i + (-IntegerCache.low)];
       	   return new Integer(i);
   		   }		
		}

}
*/            
        解析:
           public static Integer valueOf(int i) {
                if (i >= -128 && i <= 127)
                    //传递的值在-128到127直接直接到数组cache中获取内容
                    return IntegerCache.cache[i + (-IntegerCache.low)];
                return new Integer(i);
            }
       
-------------------------------------------------------------------------------- 
        Integer i5 = 50;  //Integer.valueOf(50); -128-127自动装箱
        Integer i6 = 50;  
        System.out.println(i5 == i6); //true 因为i5和i6的值都是50,到静态数组cache获取同一个空间数据
--------------------------------------------------------------------------------     
        // 针对-128到127之间的数据做了一个数据缓冲池,
// 如果数据是该范围内的,每次并不创建新的空间。直接从数组中拿数据。反之,需要创建新的空间。
        //new Integer(i) ---> new Integer(500)
        Integer i7 = 500;
        //new Integer(i) ---> new Integer(500)
        Integer i8 = 500;
        System.out.println(i7 == i8);//false
    }
}
package com.itheima.sh.c_cookie_test_03;

import java.util.Arrays;
import java.util.List;

/*
注意:
1.使用数组工具类Arrays中的asList方法将数组转换为集合,因为集合的数据是来自于数组,数组长度固定不变,
所以这里要求集合的长度不能改变
2.如果将基本数据类型的数组转换为集合,那么数组类型不能是基本数据类型,必须是包装类类型
 */
public class Demo02 {
    public static void main(String[] args) {
        method_3();
        method_2();
        method_1();
    }

    private static void method_3() {
        //1.定义整数数组
//        Integer[] arr = {10,20,30}; //自动装箱Integer.valueOf(10) -128-127byte常量池  new  Integer();
        Integer[] arr = {Integer.valueOf(10),Integer.valueOf(20),Integer.valueOf(30)};
        //2.转化为集合
        // public static <T> List<T> asList(T... a) {}
        List<Integer> list = Arrays.asList(arr);
        System.out.println(list.size()); //3
        System.out.println(list);   //{10,20,30}
    }

    private static void method_2() {
        //1.定义整数数组
        int[] arr = {10,20,30};
        //2.转化为集合
        // public static <T> List<T> asList(T... a) {}
        List<int[]> list = Arrays.asList(arr);
        System.out.println(list.size()); //1
        System.out.println(list);       //[[I@1540e19d]
    }

    private static void method_1() {
        //1.创建数组
        String[] arr = {"abc","def","abc"};
        //2.将上述数组转换为List集合
        List<String> list = Arrays.asList(arr);
        //给list集合添加数据
//        list.add("哈哈"); //Exception in thread "main" java.lang.UnsupportedOperationException
//        list.remove("def"); //Exception in thread "main" java.lang.UnsupportedOperationException
        //获取
//        System.out.println(list.get(0));
        //修改元素内容不是集合长度
        list.set(0, "呵呵");

        //3.输出集合数据
        System.out.println("list = " + list);
    }
}

一、Cookie技术

1、什么是会话【掌握】

用户打开浏览器访问网站开始直到关闭浏览器的过程就是一次会话。

在这里插入图片描述

2、Cookie介绍

Cookie属于一个类,可以直接创建对象

Cookie是在服务器端创建保存在浏览器端

tomcat服务器将创建的cookie以及cookie中的数据响应给浏览器,

当使用HttpServletResponse中的对象调用方法addCookie将服务器创建的cookie直接保存到浏览器端

当我们下次访问同一个服务器会携带相同的cookie信息,在服务器中我们可以使用HttpServletRequest对象调用方法getCookies获取随着请求携带过来的所有的cookie。

在这里插入图片描述在这里插入图片描述

好处:减轻服务器压力

弊端:不安全

在这里插入图片描述

3、Cookie的应用场景

【1】购物车 : 例如现在的苏宁易购,不登录账户也可浏览商品,并添加购物车。

【2】记住用户名和密码:例如 b站 用户登陆页面,勾选框,浏览器可记住用户名和密码。

说明:目前还不能完成第二次访问登录页面,在页面中取出cookie中的用户名和密码。

4、Cookie的常用API(重要)

【1】需求:上述应用场景中我们目前还不能完成第二次访问登录页面,在页面中取出cookie中的用户名和密码。我们可以实现第二次访问服务器取出cookie中的数据。

【2】图解
在这里插入图片描述

方法使用示例说明
创建Cookie对象Cookie(String name,String value)name表示指定 cookie 名称 ,value 表示指定 cookie 值Cookie c1 = new Cookie(“username”,“suoge”)
获取cookie的name值String getName()c1.getName()
获取cookie的value值String getValue()c1.getValue()
设置cookie的值void setValue(String value)c1.setValue(“李四”)

【3】构造方法

Cookie(String name, String value) 

【4】操作Cookie类中的name和value方法

1.String getName() 		// 获取cookie类中的name值
2.String getValue()  	// 获取cookie类中的value值
3.void setValue(String newValue)  // 修改value值

【5】使用HttpServletResponse中的对象调用方法addCookie将服务器创建的cookie直接保存到浏览器端

void addCookie(Cookie cookie)   参数需要一个cookie类的对象

【6】使用HttpServletRequest对象调用方法getCookies获取随着请求携带过来的所有的cookie。

Cookie[] getCookies()  获取随着请求的所有cookie放到数组中

【7】案例实现

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/loginServlet" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        记住用户名和密码:<input type="checkbox" name="check"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

loginServlet:

@WebServlet("/loginServlet")
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 {
        //1.处理post请求乱码
        request.setCharacterEncoding("utf-8");
        //2.获取用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //3.获取复选框的value属性值
        String check = request.getParameter("check");
        //4.判断用户是否希望记住用户名和密码
        if("on".equals(check)){
            //5.假设用户希望记住,我们创建cookie对象将用户名和密码存储到cookie中
            //Cookie(String name, String value)
            Cookie cookie1 = new Cookie("username", username);
            Cookie cookie2 = new Cookie("password", password);
            //6.响应给浏览器 void addCookie(Cookie cookie)   参数需要一个cookie类的对象
            response.addCookie(cookie1);
            response.addCookie(cookie2);
        }
    }
}

login02Servlet:

@WebServlet("/login02Servlet")
public class Login2Servlet 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 使用HttpServletRequest对象调用方法getCookies获取随着请求携带过来的所有的cookie。
        //Cookie[] getCookies()  获取随着请求的所有cookie放到数组中
        Cookie[] cookies = request.getCookies();
        //2.遍历数组取出用户名和密码的cookie
        for (Cookie cookie : cookies) {
            //3.输出用户名和密码的cookie中的value值和name值
            String cookieName = cookie.getName();
            //判断是否是用户名
            if("username".equals(cookieName)){
                System.out.println(cookieName+"----"+cookie.getValue());
            }else if("password".equals(cookieName)){
                //判断是否是密码
                System.out.println(cookieName+"----"+cookie.getValue());
            }

        }
    }
}

5、关于cookie中存储特殊字符问题 (理解原理)

如果直接向cookie中存储特殊字符,例如空格,分号(😉,逗号(,),等号(=)等特殊字符。那么就会出现问题。

在向cookie中存储特殊字符之前必须要先进行编码处理,然后从cookie中取出之后在进行解码处理。

1、cookie中不能直接存储特殊字符:空格 分号等,如果存储必须先编码在存储:

 String encode = URLEncoder.encode(str, "utf-8");

2、在获取的时候需要解码:

 String decode = URLDecoder.decode(value, "utf-8");

【1】向cookie中存储特殊字符问题演示

@WebServlet("/specialCookie01Servlet")
public class SpecialCookie01Servlet 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 {
        /*
            向cookie中存储特殊字符问题演示
         */
        //1.创建Cookie类的对象
        Cookie cookie = new Cookie("msg", "12 34");
        //2.将cookie存储到浏览器端
        response.addCookie(cookie);
    }
}

在这里插入图片描述

【2】解决向cookie中存储特殊字符的问题

方案:在向cookie中存储特殊字符前进行编码,然后取出之后需要解码。

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
            向cookie中存储特殊字符问题演示
         */
        //1.创建Cookie类的对象
//        Cookie cookie = new Cookie("msg", "12 34");报错
        String str = "12 34";
        //编码
        String encode = URLEncoder.encode(str, "utf-8");
        Cookie cookie = new Cookie("msg", encode);
        //2.将cookie存储到浏览器端
        response.addCookie(cookie);
    }
}
@WebServlet("/specialCookie02Servlet")
public class SpecialCookie02Servlet 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
        Cookie[] cookies = request.getCookies();
        //2.遍历cookie数组
        for (Cookie cookie : cookies) {
            //3.取出cookie的name
            String cookieName = cookie.getName();
            //4.判断cookieName的值是否是msg
            if("msg".equals(cookieName)){
                //5.取出value
                String value = cookie.getValue();
                //6.解码并输出
                String decode = URLDecoder.decode(value, "utf-8");
                System.out.println(decode);
            }
        }
    }
}

6、Cookie的存活时间setMaxAge() 【重要】

【1】需求:向cookie中存储数据,并设置cookie的存活时间为1周;

cookie默认的存活时间是会话结束即关闭浏览器。

我们平常开发中对于某些cookie中存储的数据希望保存的时间更长一些,而不是浏览器关闭就不存在。

如果想让cookie长久保存我们可以使用Cookie类的方法即可

cookie分为两种

>1)会话级别的cookie:关闭浏览器cookie自动销毁
>
>2)**持久化级别的cookie**:**通过Cookie类的方法setMaxAge设置cookie的存活时间**
 void setMaxAge(int expiry) 参数是秒
@WebServlet("/cookiePersis01Servlet")
public class CookiePersis01Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected 史上最详细解释接口自动化测试中cookiesession和token的区别多测师

如何在Android中启动JAVA程序

PHP通过伪造和模拟客户端COOKIE登陆来采集抓取远程网址

如何进行基于am335的boa移植?

史上postgres元数据表最详细信息!

史上postgres元数据表最详细信息!