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 void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //【1】需求:向cookie中存储数据,并设置cookie的存活时间为1周;持久化cookie
        //1.创建cookie对象
        Cookie cookie = new Cookie("age", "18");
        //2.设置cookie的最大存活时间  void setMaxAge(int expiry) 参数是秒
        cookie.setMaxAge(60*60*24*7);
        //3.响应cookie给浏览器
        response.addCookie(cookie);
    }
}

7、设置cookie的有效路径【理解】

如果访问的servlet路径是要携带的cookie的路径本身或者子路径,此时会携带该cookie,

否则不会携带cookie

setPath(“有效路径”)

【1】如果系统特别复杂的情况下,我只希望访问系统的用户模块时携带用户的cookie,不需要携带其他模块的cookie。

设置cookie有效路径:/user 即可。

设置cookie的有效路径,使用Cookie类中的方法:

void setPath(String uri)  参数中书写有效路径

【2】需求:

  1. 在PathServlet中创建一个Cookie,设置路径为"/suoge/a/b";
  2. 新建一个PathTwoServlet,设置该servlet的访问路径:"/suoge/a/b/d";
  3. 新建一个PathThrServlet,设置该servlet的访问路径:/suoge/a";
  4. 分别在PathTwoServlet,PathThrServlet中获取cookie;
@WebServlet("/pathServlet")
public class PathServlet 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 {
        //在PathServlet中创建一个Cookie,设置路径为"/suoge/a/b";
        //1.创建cookie对象
        Cookie cookie = new Cookie("name", "柳岩");
        //2.设置有效路径  void setPath(String uri)  参数中书写有效路径
        cookie.setPath("/suoge/a/b");
        //3.响应给浏览器
        response.addCookie(cookie);
    }
}
@WebServlet("/suoge/a/b/d")
public class PathTwoServlet 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 {
        //新建一个PathTwoServlet,设置该servlet的访问路径:"/suoge/a/b/d";
        //1.获取浏览器所有的cookie
        Cookie[] cookies = request.getCookies();
        /*
            通过演示我们发现这里获取的cookie:
                age   路径是  /     只要访问同一个ip地址或者域名都会携带cookie信息
                name  路径是  /suoge/a/b  我们这里访问的servlet路径是:/suoge/a/b/d  因为
                            cookie的name有效路径是/suoge/a/b,而访问的servlet路径属于其子路径。只要访问cookie
                            有效路径的本身以及子路径都会携带cookie
         */
        System.out.println(Arrays.toString(cookies));
    }
}

@WebServlet("/suoge/a")
public class PathThrServlet 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 {
        //新建一个PathTwoServlet,设置该servlet的访问路径:"/suoge/a/b/d";
        //1.获取浏览器所有的cookie
        Cookie[] cookies = request.getCookies();
        /*
            通过演示我们发现这里获取的cookie:
                age   路径是  /     只要访问同一个ip地址或者域名都会携带cookie信息
                name  路径是  /suoge/a/b  我们这里访问的servlet路径是:/suoge/a 因为
                            cookie的name有效路径是/suoge/a/b,而访问的servlet路径不属于其子路径以及本身路径。所以不会携带cookie
         */
//        System.out.println(Arrays.toString(cookies));
    }
}

面试题:

当给cookie设置有效路径"/user/role"后:

访问的servlet路径是:

a:/user 不会携带

b:/user/aaa 不会携带

c:/user/role 会携带

d: /role 不会携带

e:/user/role/aaa 会携带

8、Cookie删除(重要)

1.如果cookie是会话级别的cookie,关闭浏览器会话结束,cookie消失

2.在浏览器手动清除

**3.使用代码进行删除 **【思想是替换。把持久化的cookie变为会话级别的cookie】。

@WebServlet("/deleteCookie01Servlet")
public class DeleteCookie01Servlet 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 {
        //3.使用代码进行删除 
        //思想是替换。把持久化的cookie变为会话级别的cookie。
        //步骤:
//1.创建cookie   new Cookie(name,value), name值就是要删除的cookie的name,value的值是"" 空字符串
        Cookie cookie = new Cookie("age", "");
        //2.设置cookie的存活时间是0
        cookie.setMaxAge(0);
        //3.设置cookie的有效路径和原来的有效路径一致
        cookie.setPath("/");
        //4.响应给浏览器
        response.addCookie(cookie);
    }
}

9、案例【cooki记录浏览商品的历史记录】

需求:做一个商品页面,当我们访问后,在页面上点击查看商品浏览记录后,可以查看到以前浏览过的商品信息

【1】分析

在这里插入图片描述

1.创建两个页面:

goods.html 展示商品信息

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href="/goodsServlet?good=galaxy">三星手机</a> <br>
    <a href="/goodsServlet?good=chuizi">锤子手机</a> <br>
    <a href="/goodsServlet?good=xiaomi">小米手机</a> <br>
</body>
</html>

goods2.html 点击该页面的按钮就可以查看浏览商品的历史记录

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="goods.html">继续浏览</a> <br>
<a href="/historyServlet">查看浏览记录</a> <br>
</body>
</html>

2.创建2个servlet:

goodsServlet:当用户在goods.html页面中点击浏览商品,执行该servlet,将浏览的商品存储到cookie中,然后响应给浏览器。


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

/*
goodsServlet:当用户在goods.html页面中点击浏览商品,执行该servlet,将浏览的商品存储到cookie中,然后响应给浏览器。
 */
@WebServlet("/goodsServlet")
public class GoodsServle 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.获取浏览的商品名
        String good = request.getParameter("good");
        //2.获取页面中的所有cookie
        Cookie cookieHistory = CookieUtils.getCookies(request,"history");
        /*
            3.判断获取的cookie是否是null
                如果是null  说明之前没有浏览过商品,第一次浏览
                如果不是null 说明之前浏览过商品
         */
        if(cookieHistory == null){
            //4.如果是null  说明之前没有浏览过商品,第一次浏览,创建Cookie将商品存储到cookie中
            Cookie cookie = new Cookie("history", good);
            //5.设置cookie最大存活时间
            cookie.setMaxAge(60*60);
            //6.响应给浏览器
            response.addCookie(cookie);
        }else{
             /*
                    7.如果不是null 说明之前浏览过商品
                                        name        value
                    cookie 中的数据:  history   galaxy_chuizi
             */
            //获取cookie中的value  ===》galaxy_chuizi
            String value = cookieHistory.getValue();
            //8.按照_下划线字符进行切割变为数组 {galaxy,chuizi,...}
            String[] arr = value.split("_");
            //9.将数组转换为集合List   static <T> List<T>asList(T... a)
            List<String> list = Arrays.asList(arr);
            //10.使用List集合中的方法  boolean contains(Object o)
            // 判断集合list中是否含有当前浏览的商品
            if(!list.contains(good)){
                //11.不包含 {galaxy,chuizi} 不包含xiaomi 我们要将xiaomi拼接到value值
                //value = galaxy_chuizi_xiaomi===>history====>galaxy_chuizi_xiaomi
                value=value+"_"+good;
                //将新的value覆盖之前的value
                cookieHistory.setValue(value);
                //12.将新的cookie响应给浏览器
                response.addCookie(cookieHistory);
            }
        }

    }
}

工具类:

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
/*
    工具类用来判断浏览器中是否含有name是history的cookie,如果有则返回,没有返回null
 */
public class CookieUtils {
    String cookieNameHistory="history"
    public static Cookie getCookies(HttpServletRequest request, String cookieNameHistory) {
        //1.获取浏览器所有的cookie
        Cookie[] cookies = request.getCookies();
        //防止空指针异常我们这里需要对数组cookies判断
        if(cookies!=null && cookies.length>0){
            //2.遍历数组取出每个cookie
            for (Cookie cookie : cookies) {
                //3.取出cookie的name值
                String name = cookie.getName();
                //4.判断name是否等于cookieNameHistory即history
                if(cookieNameHistory.equals(name)){
                    //5.说明含有name是history的cookie,返回cookie
                    return cookie;
                }
            }
        }
        //能够执行到这里说明浏览器没有name是history的cookie
        return null;
    }
}

​ historyServlet:在 goods2.html页面中点击历史记录按钮,执行该servlet,在该servlet中取出浏览器客户端的历史记录的cookie并将商品历史记录响应给浏览器。

/*
       historyServlet:在  goods2.html页面中点击历史记录按钮,执行该servlet,在该servlet中取出浏览器客户端的历史记录的cookie并将商品历史记录响应给浏览器。
 */
@WebServlet("/historyServlet")
public class HistoryServlet 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 cookieHistory = CookieUtils.getCookies(request, "history");
        //2.判断cookie是否等于null
        if(cookieHistory == null){
            //3.等于null,说明没有历史记录,响应给浏览器一句话
            response.getWriter().print("<a href=\"/goods.html\">您还没有浏览记录,去浏览吧</a>");
        }else{
            //4.不等于null,说明有历史记录,取出cookie的value  galaxy_chuizi_xiaomi
            String value = cookieHistory.getValue();
            //5.按照_下划线切割为数组
            String[] arr = value.split("_");
            //6.响应给浏览器
            response.getWriter().print("您浏览的商品记录是:"+Arrays.toString(arr));
            response.getWriter().print("<br><a href=\"/goods.html\">继续浏览</a>");
        }


    }
}

二、Session技术

1、session介绍

session属于在服务器中创建的,存在服务器中。属于会话过程中的技术,用来存储数据。

在这里插入图片描述

1.Session会话技术属于HttpSession接口类型

2.属于在服务器中创建的,存在服务器中,并且可以保留一段时间(默认30min)

2、Session原理【掌握】

1.用户第一次访问的时候,tomcat会创建对应的session容器,每个容器具有唯一的标识JSESSIONID,然后tomcat底层创建会话级别的cookie存储唯一标识JSESSIONID存储到浏览器端。

2.用户再次访问,tomcat中取出session并从cookie中取出之前保存的唯一标识JSESSIONID进行比较查找自己的session容器

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

3、Session常用API【掌握】

创建和销毁的API

【1】request.getSession() 【记住】

// 创建session 如果session不存在,创建session,存在,获取当前session
request.getSession(); // 第一次创建 ,后续获取

【2】HttpSession session1 = request.getSession(true);

//两个API效果相同 request.getSession(true); 等于 request.getSession();
// 创建session 如果session不存在,创建session,存在,获取当前session
HttpSession session1 = request.getSession(true);

【3】request.getSession(false); 了解

// 如果当前存在session 获取当前session, 不存在,不获取session,返回null
request.getSession(false);

【4】session.invalidate() ;

//使当前session失效,即销毁当前session
session.invalidate() 

【5】补充:String sessionId = session.getId();

// 获取session的唯一标识JSESSIONID
String sessionId = session.getId();  

代码演示:

@WebServlet("/sessionDemo01Servlet")
public class SessionDemo01Servlet 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 {
        /*
            session创建和销毁的api演示:
         */
        //1.创建session
        HttpSession session = request.getSession();
        //2.获取唯一标识并输出
        System.out.println(session.getId());
        //3.创建session  有则获取,没有则创建
        HttpSession session2 = request.getSession(true);
        //4.获取唯一标识并输出
        System.out.println(session2.getId());

        //销毁session  session.invalidate()使当前session失效,即销毁当前session
        session.invalidate();
        //5.创建session  有则获取,没有则不获取返回null
        HttpSession session3 = request.getSession(false);
        System.out.println("session3 = " + session3);
        if(session3!=null){
            //6.获取唯一标识并输出
            System.out.println(session3.getId());
        }
    }
}

HttpSession接口方法作用
long getCreationTime()表示会话创建的时间,返回long类型。 表示1970-1-1到这个时间之间相差的毫秒数
boolean isNew()判断当前是否是一个新的会话,是的返回true,否则就是false
@WebServlet("/sessionDemo02Servlet")
public class SessionDemo02Servlet 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.long getCreationTime()**表示会话创建的时间**,返回long类型。  表示1970-1-1到这个时间之间相差的毫秒数
            2.boolean isNew()判断当前是否是一个新的会话,是的返回true
         */
        //创建session
        HttpSession session = request.getSession();
        //long getCreationTime()**表示会话创建的时间**,返回long类型。  表示1970-1-1到这个时间之间相差的毫秒数
        /*long creationTime = session.getCreationTime();
        System.out.println("creationTime = " + creationTime);
        //将creationTime毫秒转换为日期时间
        Date date = new Date(creationTime);
        System.out.println(date.toString());
        //2020-11-20 14:52:46
        System.out.println(date.toLocaleString());

        //Timestamp(long time) 2020-11-20 14:54:30
        System.out.println(new Timestamp(creationTime).toLocaleString());*/


        //2.boolean isNew()判断当前是否是一个新的会话,是的返回true
        System.out.println(session.isNew());
    }
}

5、Session的域对象操作【掌握】

1.session作为域对象可以在多次请求中共享session容器中的数据

2.三个域对象的范围:request < Session < ServletContext

【1】session属于域对象,具有三个方法:

void setAttribute(String name, Object value) 
Object getAttribute(String name)  
void removeAttribute(String name) 

【2】在一次会话过程中都可以使用,代码实现:

@WebServlet("/sessionScope01Servlet")
public class SessionScope01Servlet 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.创建session
        HttpSession session = request.getSession();
        //2.向session中存储数据
        session.setAttribute("username","小明");
        System.out.println(session.getId());

        //重定向到sessionScope02Servlet
        response.sendRedirect("/sessionScope02Servlet");
    }
}

@WebServlet("/sessionScope02Servlet")
public class SessionScope02Servlet 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.获取session
        HttpSession session = request.getSession();
        //2.从session中获取数据
        String username = (String) session.getAttribute("username");
        System.out.println(session.getId());
    }
}

6.Session的生命周期【了解】

1.session的创建时间:第一次访问执行代码request.getSession();

2.销毁session:

​ 1)默认是30min,时间到自动销毁

​ 2)执行方法:invalidate()

​ 3) 服务器非正常关闭

​ 4)手动设置过期时间

在这里插入图片描述

手动设置过期时间

HttpSession的方法功能描述
void setMaxInactiveInterval(int 秒)设置会话最大非活动时间时隔,单位是秒
session中的方法说明
int getMaxInactiveInterval()得到服务器上会话最大的非活动时间间隔,默认是1800秒(30分钟)
@WebServlet("/sessionDestroy01Servlet")
public class SessionDestroy01Servlet 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 {

        //创建session
        HttpSession session = request.getSession();
        System.out.println("更改session的存活时间前="+session.getId());
        //1.int getMaxInactiveInterval()得到服务器上会话最大的非活动时间间隔,默认是1800秒(30分钟)
        int time = session.getMaxInactiveInterval();
        System.out.println("time = " + time);

        //2.void  setMaxInactiveInterval(int 秒)设置会话最大非活动时间时隔,单位是秒
//        session.setMaxInactiveInterval(5);
        //负数时间指示会话永远不会超时。 
        session.setMaxInactiveInterval(-1);
        System.out.println("更改session的存活时间后="+session.getId());
        int time2 = session.getMaxInactiveInterval();
        System.out.println("time = " + time2);

    }
}

7、session持久化方案(重要)

【1】问题引入:

tomcat在创建cookie的时候属于会话级别的cookie,关闭浏览器,cookie消失,

下次打开浏览器不会携带之前的cookie即cookie中的JSESSIONID到tomcat服务器中了,

那么这样会造成tomcat服务器中会有很多个不能使用的session容器(session依然还在,只是找不到了)。

严重的话会造成服务器宕机。

@WebServlet("/sessionPersis01Servlet")
public class SessionPersis01Servlet 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.获取session
        HttpSession session = request.getSession();
        System.out.println(session.getId());
    }
}

【2】解决方案

持久化session解决问题

主要问题是cookie是会话级别的,我们只需要将会话级别的cookie变为持久化级别的即可。

持久化session就是持久化cookie

步骤:

1.创建session

2.获取session的JSESSIOID的值

3.创建Cookie ,Cookie(“JSESSIOID”,值)

4.使用cookie对象调用方法setMaxAge()进行cookie的持久化,存活时间建议30min

5.将cookie响应给浏览器

@WebServlet("/sessionPersis01Servlet")
public class SessionPersis01Servlet 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.创建session
        HttpSession session = request.getSession();
        //2.获取session的JSESSIOID的值
        String sessionId = session.getId();
        System.out.println(sessionId);
        //3.创建Cookie ,Cookie("JSESSIOID",值)
        Cookie cookie = new Cookie("JSESSIONID", sessionId);
        //4.使用cookie对象调用方法setMaxAge()进行cookie的持久化,存活时间建议30min
        cookie.setMaxAge(60*30);
        //5.将cookie响应给浏览器
        response.addCookie(cookie);
    }
}

8、Session的钝化与活化技术(了解) 面试

钝化:就是正常关闭tomcat服务器,会将session容器中的数据长久保存到硬盘上。底层原理是序列化。

活化:就是启动tomcat服务器,将之前钝化的session容器读取到内存中。底层原理是反序列化。

注意:

1.由于钝化和活化的原理是序列化和反序列,所以要求存储在session容器中的对象所属类必须实现序列化接口Serializable。

2.演示钝化和活化效果不能在idea中演示,我们需要将当前项目打成war包放到tomcat服务器中的webapps目录下进行演示。

3.钝化:就是正常关闭tomcat服务器,将session中的的数据长久保存到硬盘上,会在work\Catalina\localhost\项目名下生成一个钝化文件。该文件中保存的就是session中的数据。实现原理是序列化。

4.活化:启动tomcat服务器将之前钝化的文件读取内存中,文件会自动消失。原理是反序列化。

钝化和活化的演示

【1】代码:

@WebServlet("/setSessionServlet")
public class SetSessionServlet 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.创建session
        HttpSession session = request.getSession();
        //2.获取session的id
        String sessionId = session.getId();
        //3.创建商品对象
        Product p = new Product("笔记本", 9999);
        //4.将商品对象存储到session中
        session.setAttribute("p",p);
        //5.响应数据
        response.getWriter().print("setSessionServlet.....当前JSESSIONID="+sessionId);
    }
}

@WebServlet("/getSessionServlet")
public class GetSessionServlet 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.获取session
        HttpSession session = request.getSession();
        //2.获取session的id
        String sessionId = session.getId();
        //3.从session中取出商品
        Product p = (Product) session.getAttribute("p");
        //4.响应数据
        response.getWriter().print("getSessionServlet.....当前JSESSIONID="+sessionId+",p="+p.toString());
    }
}

【2】打war包

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

6.构建完成之后:

在这里插入图片描述

7.将上述生成的war包复制到tomcat的webapps目录下:

在这里插入图片描述

8.到tomcat的bin目录下启动tomcat
在这里插入图片描述

注意:这里启动一定将idea中的tomcat关闭。

9.在浏览器中访问servlet
在这里插入图片描述在这里插入图片描述

10.正常关闭tomcat:bin目录下面的shutdown.bat

11.在如下目录生成session的钝化文件:

在这里插入图片描述
12.正常启动tomcat

钝化文件就会被加载到内存,文件自动消失

9、Cookie禁用后Session的处理【了解】

1.如果cookie被禁用,如何找到对应的session?

重写url,有2种方式:

​ 1)重定向重写url:

String url = response.encodeRedirectURL(path);

​ 2)超链接重写url

String url = response.encodeURL(path);

核心思想都是在url后面拼接当前session的JSESSIONID.

/demo02;jsessionid=0073C2468966D58AF52BBC728A688577

2.注意两种方式区别:

​ 超链接重写url:如果url是空字符串,那么也会在url后面拼接JSESSIONID.

​ 重定向重写url: 如果url是空字符串,不做拼接

1.问题

cookie禁用后,浏览器中不能保存cookie了,那么没有cookie,就没有JSESSIONID,

那么这样就找不到tomcat服务器中的session容器了,

这样会造成tomcat服务器中的存在过多的不能使用的session容器。

2.解决问题

重写url即在url后面拼接当前session的唯一标识JSESSIONID.

3.两种方法

重定向重写URL
方法说明
response.encodeRedirectURL(path)将重定向跳转的地址进行重写,添加一个会话ID在后面。
@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 {
        /*
            重定向重写URL 方式解决禁用cookie访问session的问题:
            response.encodeRedirectURL(path)将重定向跳转的地址进行重写,添加一个会话ID在后面。
         */
        //1.创建session
        HttpSession session = request.getSession();
        //2.输出id
        System.out.println(session.getId());
        //3.重定向到  /demo02
        String path = "/demo02";
        // response.encodeRedirectURL(path)将重定向跳转的地址进行重写,添加一个会话ID在后面。
        ///demo02;jsessionid=0073C2468966D58AF52BBC728A688577
        String url = response.encodeRedirectURL(path);
        response.sendRedirect(url);
    }
}

@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.创建session
        HttpSession session = request.getSession();
        //2.输出id
        System.out.println(session.getId());
    }
}

超连接重写URL
方法说明
response.encodeURL(path)对要跳转到的地址使用URL重写
@WebServlet("/demo03")
public class Demo03Servlet 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");
        /*
            超连接重写URL 方式解决禁用cookie访问session的问题:
            response.encodeURL(path)对要跳转到的地址使用URL重写
         */
        //1.创建session
        HttpSession session = request.getSession();
        //2.输出id
        System.out.println(session.getId());
        //3.超连接重写URL  /demo04
        String path = "/demo04";
        //4.响应给浏览器一个超链接
        String url = response.encodeURL(path);
        //<a href='/demo04'>超连接重写URL</a>
//        response.getWriter().print("<a href='"+url+"'>超连接重写URL</a>");
        response.getWriter().print("<a href=\""+url+"\">超连接重写URL</a>");
    }
}

@WebServlet("/demo04")
public class Demo04Servlet 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.创建session
        HttpSession session = request.getSession();
        //2.输出id
        System.out.println(session.getId();
    }
}

10、servlet的三大域对象(重要)

  • 掌握servlet的三大域对象特点和区别以及应用场景

【1】

域对象名描述
session—HttpSession接口比request大,属于一次会话过程中使用的,可以实现多次请求来共享session域对象中的数据。应用场景:验证码 购物车 只有登录才可以操作一些需求等
request—HttpServletRequest接口最小的域对象,只能在一次请求中使用,应用场景:请求转发携带request域对象数据。
servletContext—ServletContext接口最大的域对象,表示当前项目的上下文对象,即当前项目。tomcat服务器一启动就会创建,当tomcat服务器关闭才会销毁。存活时间最长的。多次请求。应用场景:统计网站访问次数,读取当前项目的配置文件等

【2】

request  < session  < servletContext

【3】

【API操作】操作三个作用域对象的API

  • 存储数据:setAttribute(name,value);

  • 获得数据:getAttribute(name);

  • 删除数据:removeAttribute(name);

11、案例【Session验证码登陆】【重要】

1.需求

验证码是由服务器给浏览器端生成的一张图片,这张图片上有扭曲变形的数字或文字。主要是用来防止恶意注册或者登陆的。

在这里插入图片描述

2.流程

在这里插入图片描述

3.实现步骤

1.创建登录页面login.html

2.定义一个CheckCodeServlet用来生成验证码图片

验证码校验整体思路:

​ 1)页面一加载就向CheckCodeServlet发送请求获取验证码图片上的验证码

​ 2)每次点击验证码图片重新向CheckCodeServlet发送请求获取验证码图片上的验证码

​ 3)点击登录按钮将输入框输入的验证码和后台存储到session中的验证码进行比较

通过验证码案例我们知道session的应用场景,可以在多次请求中共享session中的数据

3.定义一个LoginServlet用来登录时校验验证码是否正确

4.代码实现
login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<h2>登录页面</h2>
<form action="/loginServlet" method="post">
    账号<input type="text" name="username"><br>
    密码<input type="password" name="password"><br>
    验证码<input type="text" name="code">
    <!--页面一加载就向checkCodeServlet发送请求-->
    <img src="/checkCodeServlet" alt="验证码" style="cursor: pointer" onclick="changeCheckCode(this);"><br>
    <input type="submit" value="登录">
</form>
<script type="text/javascript">
    //定义函数更改验证码图片
    //obj 表示img标签对象
    function changeCheckCode(obj) {//obj=this
        /*
            每次点击验证码图片重新向后台checkCodeServlet发送新的请求
            问题:当我们点击验证码图片,发现浏览器并没有向后台发送请求,因为浏览器认为当前发送的请求的路径是同一个,那么浏览器直接将当前浏览器的图片
            显示了
            解决问题:
            我们可以在请求的路径后面增加一个时间戳,告知浏览器这是一个新的请求,和原来的请求不一样
         */
        // obj.src = "/checkCodeServlet";//同一个请求,不会发送新的请求
        obj.src = "/checkCodeServlet?t="+new Date().getTime();//每次请求都不一样
    }
</script>
</body>
</html>
CheckCodeServlet类

用来生成验证码图片

package com.itheima.sh.a_session_checkcode_01;

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;

/*
     说明:验证码是一张图片,而这个图片中的内容是使用代码生成的。
        分析和步骤:
        1)创建一个可以存放图片的缓冲区BufferedImage作为画布;
        2)通过画布获取到针对这个画布的画笔;
        3)修改画布的背景颜色为白色;
        4)设置画布的边框,画边框的时候需要注意下,如果这里写画布的宽width和高height ,就会超出画布就会看不见,所以width和height 分别-1;
        5)创建一个获取随机数的对象;
        6)给画布上写数据;
        7)给画布上画干扰线;
        8)需要把画布中的内容响应给浏览器;ImageIO.write(bi,"JPG",response.getOutputStream());
 */
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet 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 {
        //定义画布的宽和高
        int width = 120;
        int height = 30;
        //创建一个可以存放图片的缓冲区,作为画布
        //BufferedImage.TYPE_INT_RGB 表示生成图片的类型
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //通过画布获取到针对这个画布的画笔
        Graphics g = bi.getGraphics();
        //修改画布的背景颜色  每次使用画笔的时候都得给画笔指定颜色
        g.setColor(Color.WHITE);
        //填充画布
        g.fillRect(0, 0, width, height);
        //设置画布的边框
        //给画笔指定颜色
        g.setColor(Color.RED);
        //给画布画边框 如果这里写width height 就会超过画布,因为边框也会占一个像素,所以这里宽和高都需要-1
        g.drawRect(0, 0, width - 1, height - 1);
        //创建一个获取随机数的对象
        Random r = new Random();
        //给画布上画干扰线
        //循环控制画多条线
        for (int i = 1; i <= 3; i++) {
            //设置画笔的颜色
            g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
            //向画布上画干扰线
            //drawLine(x1, y1, x2, y2) 这里四个参数是因为两个点画成一条线
            g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
        }
        //定义数据准备向画布中写数据
        String data = "abcdefghigklmnpqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ123456789";
        //创建字符串缓冲区
        StringBuilder sb = new StringBuilder();

        //循环控制画四个字符
        for (int i = 1; i <= 4; i++) {
            //设置画笔的颜色 Color.BLUE这里的颜色固定了,只能是蓝色,我们可以让颜色随机变化
//			g.setColor(Color.BLUE);
            g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
            //设置字体  Font.ITALIC表示斜体
            g.setFont(new Font("宋体", Font.ITALIC, 20));
            //给画布上写内容 20表示从x轴的位置开始书写 25表示y轴位置开始书写
//			g.drawString("哈哈哈哈", 20, 25);
            /*
             * data.charAt()表示根据函数的参数进行查找字符
             * data.length()表示字符串的长度
             * r.nextInt()表示生成随机数,但是随机数的范围在0~data字符串的长度
             */
            String str = data.charAt(r.nextInt(data.length())) + "";
            g.drawString(str, 20 * i, 25);
            //将验证码内容拼接到字符串缓冲区中
            sb.append(str);
        }
        //  验证码保存到session中
        request.getSession().setAttribute("checkcode", sb.toString());
        //将生成的验证码图片响应给浏览器
        ImageIO.write(bi, "JPG", response.getOutputStream());
    }
}

LoginServlet类

登录时校验验证码是否正确

package com.itheima.sh.a_session_checkcode_01;

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.io.IOException;

@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");
        //页面的输入框的验证码
        String input_code = request.getParameter("code");
        //3.从session中获取验证码图片
        // request.getSession().setAttribute("checkcode", sb.toString());
        String session_checkcode = (String) request.getSession().getAttribute("checkcode");
        //4.比较从session中获取的验证码和从页面获取的验证码是否相等:
        if(input_code!=null && input_code.equalsIgnoreCase(session_checkcode)){
            //相等:将用户名和密码传递到dao层向数据库查询
            System.out.println("验证码校验通过");
        }else{
            //不相等:响应给浏览器客户端提示验证码输入有误
            System.out.println("验证码校验没有通过");
        }
    }
}
  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程小栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值