当前位置:   article > 正文

WEB阶段4:Cookie增删查和HttpSession增删查&自动登入案例&验证码登入与注销案例_web后端使用session会话跟踪技术,实现用户登录、注销

web后端使用session会话跟踪技术,实现用户登录、注销

Cookie增删查和HttpSession增删查&自动登入案例&验证码登入与注销案例

回顾

上次课学习了两个对象:

  1. 响应HttpServletResponse
  2. 上下文对象ServletContext

获取当前工程的资源文件

ServletContext的方法功能
InputStream getResourceAsStream(String path)获取web目录下资源,转成一个输入流
String getRealPath(String path)获取真实的路径
String getInitParameter(String name)获取web.xml中全局的配置参数
<context-param>

获取作用域对象的值

ServeltContext的方法作用
Object getAttribute(String name)获取上下文域中值
void setAttribute(String name, Object value)向上下文域中添加键和值
void removeAttribute(String name)通过键删除上下文域中键和值

response设置响应行的方法

状态码的方法描述
setStatus(int status)作用: 设置状态码
常见状态码:
404:找不到资源
500:服务器代码异常
304:静态资源使用了缓存
302:页面进行了跳转
405:没有重写doGet或doPost方法
200:服务器正常响应

response设置响应头的方法

响应头的方法描述
void setHeader(String name, String value)设置响应头的键和值
void setContentType(String type)专门设置content-type响应头
1. 告诉浏览器,服务器使用的编码
2. 设置响应的编码,相当于setCharacterEncoding()
3. 设置响应的内容类型,如:text/html

输出响应的两种方式

响应体的方法描述
OutputStream getOutputStream() 处理字节响应的字节输出流
PrintWriter getWriter() 处理字符响应的字符输出流

学习目标

  1. Cookie
    1. 能够说出会话的概念
    2. 能够说出cookie的概念
    3. 能够创建、发送、接收、删除cookie
    4. 能够说出cookie执行原理
  2. HttpSession
    1. 能够说出session的概念
    2. 能够获取session对象、添加、删除、获取session中的数据

学习内容

1. 两种会话的技术

目标:

  1. 什么是会话

  2. 会话有哪两种技术

会话的概念

  1. 生活中的会话

    概念:两个人一次交流的活动

    1. 会话的创建:有任何一方接通的电话
    2. 会话过程:两个人多次互相的向对话发送语音信息
    3. 会话结束:有任何一方挂了电话
    1552693743916
  2. BS结构的会话

    概念:浏览器与服务器的多次请求和响应的过程。一个会话包含了多次请求和响应

    1. 会话的创建:浏览器第一次发送请求给服务器,由服务器创建会话。
    2. 会话的过程:浏览器多次发送请求,服务器多次做出响应
    3. 会话结束:浏览器关闭或服务器会话过期
    1552693761999
  3. 为什么有会话技术:

    因为HTTP协议(超文本传输协议,传输HTML),是一个无状态的协议,不会记录用户的状态。服务器不能通过HTTP协议来知道用户是同一个用户还是不同的用户发送的请求。通过会话技术来识别不同的用户。

  4. 会话的两种技术:

    1. 浏览器端使用的技术:Cookie
    2. 服务器端使用的技术:HttpSession

    HttpSession需要使用到Cookie才能实现会话的跟踪技术

小结:

  1. 什么是会话?

    一个用户的多次请求和响应的过程

  2. 会话有哪两种技术?

    1. Cookie
    2. HttpSession

2. 如何查看Cookie的数据

目标

​ 如何在不同的浏览器中查看Cookie的信息

应用场景

如何实现自动登录?

把用户名和密码保存在本地,可以被浏览器读取,再发送给服务器实现自动登录。
使用Cookie技术将数据保存在本地。
Cookie就是用来保存数据,格式是:键值对,键和值都是文本内容
  • 1
  • 2
  • 3

如何查看Cookie信息

在Chrome中
  1. 点地址栏的左边按钮

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ugX6zlp9-1598876513901)(assets/image-20200831091304334.png)]

  1. 点Cookie查看本地信息

    image-20200831091501076
在Firefox中
  1. 按F12打开开发者模式

  2. 点下面的存储

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0zxvoIJk-1598876513963)(assets/image-20200831091723940.png)]

  3. 扩展:可以安装浏览器的插件,让浏览器的功能更加强大

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ThzhnHEB-1598876513975)(assets/image-20200831091946001.png)]

小结

问:不同浏览器之间的Cookie数据能不能共享?

因为不同的浏览器之间Cookie的数据不能共享,所以在服务器看来是不同的用户。
  • 1

3. Cookie的执行原理

目标

  1. 什么是Cookie

  2. Cookie的执行原理

什么是Cookie

特点:本质上就是一个键值对,每个Cookie只能保存一个键和值

大小:最大不能超过4K,内容就是文本的内容

Cookie运行的原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkRCT5fH-1598876514027)(assets/image-20200831094141910.png)]

小结

服务器代码要做的事情

  1. 创建Cookie
  2. 发送Cookie
  3. 接收Cookie

4. Cookie的创建和发送【重点】

目标

  1. 如何创建Cookie

  2. 如何将创建的Cookie写入到浏览器端

创建和发送的方法

Cookie类的方法作用
Cookie(String name,String value)指定键和值,创建一个Cookie对象,注:它没有无参的构造方法
HttpServletResponse对象的方法作用
addCookie(Cookie cookie)响应对象的方法,将服务器端创建好的Cookie对象发送给浏览器

创建Cookie的案例演示

需求:

Servlet中创建一个Cookie(“user”,“NewBoy”),并且写到浏览器端去。

运行效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xVPZPKSN-1598876514031)(assets/image-20200831094943676.png)]

代码
package com.itheima.servlet;

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

/**
 * 在Servlet中创建一个user=NewBoy,并且写到浏览器端去。
 */
@WebServlet("/demo1")
public class Demo1CreateCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.创建一个Cookie对象
        Cookie man = new Cookie("user", "NewBoy");
        //2.使用响应对象发送给浏览器
        response.addCookie(man);
        //3.输出提示信息
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("向浏览器发送了一个Cookie信息");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
查询响应头

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-brCtgsC9-1598876514037)(assets/image-20200831094931257.png)]

小结

  1. 如何创建Cookie:

    new Cookie("键","值") 键和值都是String类型
    
    • 1
  2. 如何写入Cookie:

    response.addCookie(Cookie对象)
    
    • 1

5. 设置Cookie过期的时间

目标

如何设置Cookie的过期时间

设置Cookie过期时间的方法

在默认的情况下,只要浏览器关闭,Cookie会失效,不会永久保存下来

Cookie的方法说明
void setMaxAge(int expiry)设置Cookie保存的时间,单位是秒。
正整数:以秒为单位设置Cookie过期的时间
零:表示删除Cookie
负整数:无效,与没有设置的效果一样,浏览器关闭就失效

案例:设置Cookie的过期时间

需求:

在写入Cookie之前先设置Cookie过期的时间,设置为10分钟以后过期

效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BhGnjn4E-1598876514041)(assets/image-20200831095741950.png)]

代码
package com.itheima.servlet;

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

/**
 * 在Servlet中创建一个user=NewBoy,并且写到浏览器端去。
 */
@WebServlet("/demo1")
public class Demo1CreateCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.创建一个Cookie对象
        Cookie man = new Cookie("user", "NewBoy");
        //1.5 在要发送给浏览器之前设置过期时间
        man.setMaxAge(60 * 10);  //设置为10分钟
        //2.使用响应对象发送给浏览器
        response.addCookie(man);
        //3.输出提示信息
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("向浏览器发送了一个Cookie信息");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
查询响应头

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KwzbBsqf-1598876514045)(assets/image-20200831095822549.png)]

小结

  1. 如何设置Cookie过期的时间?

    setMaxAge()

  2. 参数是正,负,0分别表示什么意思?

    1. 正:以秒为单位
    2. 负数:无效
    3. 零:删除

6. 读取Cookie的信息【重点】

目标

如何从浏览器读取Cookie的信息到服务器

读取Cookie的方法

HttpServletRequest对象作用
Cookie[] getCookies()获取浏览器发送过来的所有的Cookie对象,返回Cookie数组
Cookie的方法作用
String getName()获取Cookie的键
String getValue()获取Cookie的值

演示案例

需求
  1. 修改写入的Servlet,创建两个Cookie
  2. 创建Servlet读取所有Cookie信息,显示在浏览器上。
代码

写入

package com.itheima.servlet;

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

/**
 * 在Servlet中创建一个user=NewBoy,并且写到浏览器端去。
 */
@WebServlet("/demo1")
public class Demo1CreateCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.创建一个Cookie对象
        Cookie man = new Cookie("user", "NewBoy");
        //1.5 在要发送给浏览器之前设置过期时间
        man.setMaxAge(60 * 10);  //设置为10分钟
        //2.使用响应对象发送给浏览器
        response.addCookie(man);

        //再创建一个Cookie对象
        Cookie age = new Cookie("age", "22");
        age.setMaxAge(60 * 5);  //设置为5分钟
        response.addCookie(age);

        //3.输出提示信息
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("向浏览器发送了两个Cookie信息");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

读取

package com.itheima.servlet;

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

/**
 * 读取所有的Cookie信息并且显示
 */
@WebServlet("/demo2")
public class Demo2ReadCookiesServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        //1.通过请求对象的方法读取所有的Cookie数组
        Cookie[] cookies = request.getCookies();
        //2.要判断一个数组是否为空,如果浏览器端没有Cookie,会返回空
        if (cookies == null) {
            out.print("浏览器端没有Cookie信息");
        } else {
            //遍历每个Cookie对象
            for (Cookie cookie : cookies) {
                //获取cookie的键和值
                String name = cookie.getName();
                String value = cookie.getValue();
                out.print("Cookie的名字:" + name + ",值:" + value + "<hr/>");
            }
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
执行效果

响应头

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QJvMElZe-1598876514049)(assets/image-20200831100817748.png)]

浏览器查看请求头

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7SqlBWQk-1598876514052)(assets/image-20200831101439608.png)]

小结

HttpServletRequest对象作用
Cookie[ ] getCookies()获取浏览器端所有的Cookie对象,返回Cookie的数组
Cookie类的方法作用
String getName()获取Cookie的名字
String getValue()获取Cookie的值

7. 设置Cookie的访问路径

目标

  1. 如何设置Cookie的访问路径?
  2. 设置访问路径

设置访问路径的作用

  1. 在不同的路径下可以设置相同的键,避免键被覆盖
  2. 在访问特定路径的时候,才将Cookie的信息发送给服务器

设置路径的方法

Cookie设置路径的方法功能
void setPath(路径)只有访问这个路径或它的子路径,浏览器才会发送Cookie的信息给服务器。
如果没有设置,默认是当前项目的访问地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-39XMJ6Zj-1598876514053)(assets/image-20200831102133255.png)]

设置路径的案例

需求

创建一个Cookie,设置过期时间,设置Cookie的访问路径

效果

响应头

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8oQOJHxl-1598876514055)(assets/image-20200831102603105.png)]

代码
package com.itheima.servlet;

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

@WebServlet("/demo3")
public class Demo3PathServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("保存了用户名在Cookie中");

        Cookie username = new Cookie("username", "Rose");
        username.setMaxAge(60 * 60 * 24 * 7);  //设置过期的时间是一周
        //设置它的访问路径, getContextPath()当前项目的访问地址
        username.setPath(request.getContextPath() + "/login.html");
        response.addCookie(username);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
效果

只在访问login.html浏览器才会将Cookie的数据发送给服务器

小结

如果访问路径是setPath("/day-cookie"),以下路径浏览器会发送Cookie给服务器?

访问地址会不会发送Cookie给服务器
http://localhost:8080/day-cookie/会,因为路径匹配
http://localhost:8080/day-cookie/aa/bb会,因为访问的是子路径
http://localhost:8080/day/不会,路径不匹配
http://localhost:8080/不会,访问父路径

8. 删除Cookie

目标

​ 学习删除Cookie的方法

方法

Cookie的删除说明
setMaxAge(0)删除一个Cookie

案例:删除指定的Cookie

需求

删除指定的Cookie信息,注意Cookie的访问路径要相同

代码
package com.itheima.servlet;

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

@WebServlet("/demo4")
public class Demo4DeleteServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.创建一个同名的Cookie
        Cookie cookie = new Cookie("user", null);
        //2.设置过期的时间为0,表示删除Cookie
        cookie.setMaxAge(0);  
        //注:访问地址也要一样
        cookie.setPath(request.getContextPath());  //默认是这个
        //3.发送到浏览器端
        response.addCookie(cookie);

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("Cookie被删除");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

小结

删除Cookie使用哪个方法?setMaxAge(0)

9. 创建Cookie的工具类

目标

编写一个工具类,用于读取Cookie指定键的值。如果键不存在,则返回null。如果存在就返回值

代码

工具类

package com.itheima.utils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
 * 工具类
 * 用于读取Cookie指定键的值
 * 如果键不存在,则返回null
 * 如果存在就返回值
 */
public class CookieUtils {

    /**
     * 通过Cookie的键,获取值
     * @param request 请求对象
     * @param name cookie的键
     * @return cookie的值,如果没有返回null
     */
    public static String getCookieValue(HttpServletRequest request, String name) {
        //1.通过请求对象的方法读取所有的Cookie数组
        Cookie[] cookies = request.getCookies();
        //2.要判断一个数组是否为空,如果浏览器端没有Cookie,会返回空
        if (cookies != null) {
            //遍历每个Cookie对象
            for (Cookie cookie : cookies) {
                //获取cookie的键和值
                String key = cookie.getName();
                String value = cookie.getValue();
                //比较name和key是否相等
                if (key.equals(name)) {
                    return value;
                }
            }
        }
        //没有找到返回null
        return null;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

工具类的使用

package com.itheima.servlet;

import com.itheima.utils.CookieUtils;

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;
import java.io.PrintWriter;

@WebServlet("/demo5")
public class Demo5UseUtilsServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //使用工具类获取一个Cookie的值
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //调用工具类
        String age = CookieUtils.getCookieValue(request, "age");
        out.print("Cookie中age的值是:" + age);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

10. 案例part1:Cookie实现自动登录Servlet【作业】

目标

能够使用Cookie保存用户名和密码

结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fIvwRd41-1598876514057)(assets/1568899204362.png)]

分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jcu6CpCX-1598876514059)(assets/image-20200831112951460.png)]

Servlet步骤

  1. 得到表单提交的数据:用户名和密码
  2. 判断用户名和密码实现登录
  3. 如果登录成功,则判断是否勾选了记住我。
  4. 如果勾选了,则将用户名和密码写入Cookie中,保存一周的时间,并跳转到成功页面。
  5. 否则跳转到登录失败页面

代码

LoginServlet

package com.itheima.servlet;

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

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 得到用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //2. 判断是否登录成功
        if ("admin".equals(username) && "123".equals(password)) {
            //3. 如果登录成功,判断是否勾了记住我
            String remember = request.getParameter("remember");
            //4. 如果勾了
            if (remember != null) {
                //创建Cookie保存用户名和密码
                Cookie cname = new Cookie("username", username);
                cname.setMaxAge(60 * 60 * 24 * 30);  //保存1个月
                cname.setPath(request.getContextPath() + "/login.html");  //设置访问路径
                //5. 发送Cookie到浏览器端
                response.addCookie(cname);

                Cookie cpass = new Cookie("password", password);
                cpass.setMaxAge(60 * 60 * 24 * 30);  //保存1个月
                cpass.setPath(request.getContextPath() + "/login.html");  //设置访问路径
                response.addCookie(cpass);
            }
            //跳转到登录成功的页面
            response.sendRedirect("success.html");
        }
        else {
            //登录失败
            response.sendRedirect("failure.html");
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

11. 案例part2:Cookie实现自动登录浏览器端

目标

浏览器端代码的实现

JS代码

读取指定键的值commons.js
  1. 得到当前路径下所有的cookie信息
  2. 如果不为空字符串,则按分号进行拆分成数组,数组中有2个元素
  3. 每个元素再按等于号来拆分,0是名字,1是值
  4. 如果name与key相等,就返回value
  5. 没找到返回空字符串
页面加载完毕的代码
  1. 页面加载完成,调用工具类读取cookie的信息
  2. 如果有username不为空串,并且password也不为空串
  3. 则将用户名和密码赋值给文件框,并且提交表单
commons.js
/**
 工具方法,通过名字得到值,如果没有这个键就返回null
 */
function getCookieValue(name) {
    //这个属性可以读取浏览器端所有的cookies
    let cookies = document.cookie;  //username=admin; password=123   密码前面有空格
    //按;和空格拆分
    let strings = cookies.split("; ");
    //遍历数组
    for (let string of strings) {  //username=admin
        //按等号进行拆分
        let arr = string.split("=");  //arr[0]=username键  arr[1]=admin值
        let key = arr[0];  //键
        let value = arr[1];  //值
        //如果key与name相等表示找到
        if (key == name) {
            return value;
        }
    }
    //最后返回null
    return null;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

代码

login.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
    <!--导入js文件-->
    <script src="js/commons.js"></script>
</head>
<body>
<h2>用户登录</h2>
<form action="login" method="post" id="loginForm">
    <table>
        <tr>
            <td width="60">用户名</td>
            <td><input type="text" name="username" id="username"/></td>
        </tr>
        <tr>
            <td>密码</td>
            <td><input type="password" name="password" id="password"/></td>
        </tr>
        <tr>
            <td>记住我</td>
            <!--没有value属性的前提下,点中它的值是on,如果没有选中是没有值的 -->
            <td><input type="checkbox" name="remember"/></td>
        </tr>
        <tr>
            <td colspan="2" align="center"><input type="submit" value="登录"/></td>
        </tr>
    </table>
</form>

<script type="text/javascript">
    //当前页面加载完毕,从cookie中读取用户名和密码的信息
    window.onload = function () {
        let username = getCookieValue("username");
        let password = getCookieValue("password");
        //用户名和密码都不能为空才提交数据给服务器
        if (username!=null && password!=null) {
            //把用户名和密码赋值给两个文本框
            document.getElementById("username").value = username;
            document.getElementById("password").value = password;
            //提交表单
            document.getElementById("loginForm").submit();
        }
    }
</script>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

小结

实现自动登录的思路

  1. 在浏览器端通过JS读取本地用户名和密码
  2. 自动提交给服务器
  3. 服务器端获取用户名和密码进行判断

上午的回顾

创建Cookie对象: new Cookie("键","值")
发送给浏览器:response.addCookie(Cookie对象)
获取浏览器发送回来的cookie: Cookie[] request.getCookies()

设置Cookie的过期时间:setMaxAge(秒),如果设置为0,表示删除
设置Cookie的访问路径:setPath(/路径)
获取Cookie的名字和值:getName() getValue()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

12. HttpSession对象的方法

目标

  1. 如何得到会话对象

  2. 学习HttpSession接口中常用的方法

Session存储数据的特点

在服务器端用的最多的就是会话域对象

  1. 在服务器的内存中保存用户的数据
  2. 每个用户有自己的存储空间,数据不能共享
  3. 每个用户有自己的ID,会话ID用来识别不同的用户
类似于超市的储物柜
1552711348283
Session和Cookie的主要区别
  1. Cookie:
    1. 存储在浏览器的硬盘中
    2. 每个Cookie只能保存一个键和值
    3. 键和值都是字符串类型
  2. Session
    1. 存储在服务器的内存中
    2. 每个Session可以保存多个键和值
    3. 键是字符串,值是Object类型

HttpSession接口的方法(重点)

得到会话的方法
HttpServletRequest创建会话的方法描述
HttpSession request.getSession()通过请求对象获取一个会话对象
创建会话的时机

用户第一次访问,并且调用上面的getSession()方法就创建一个会话对象,并且会分配会话ID给这个用户。

如果第二次以后访问,就会返回第一次创建的同一个会话。每个用户只对应一个会话对象。

org.apache.catalina.session.StandardSessionFacade@4105c137

public class StandardSessionFacade implements HttpSession
会话对象由Tomcat实现,并且由Tomcat实例化
  • 1
  • 2
  • 3
  • 4

案例:会话接口中方法的演示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FtsDZwz2-1598876514125)(assets/image-20200831145040455.png)]

步骤
  1. 得到会话对象
  2. 使用会话对象使用上面的各个方法
效果
image-20200831145425349
代码
package com.itheima.servlet;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Timestamp;

@WebServlet("/demo1")
public class Demo1SessionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        //创建一个会话对象
        HttpSession session = request.getSession();
        out.print("会话对象是:" + session + "<br/>");
        //每个用户都有一个唯一的会话ID,格式是:32位的十六进制数
        out.print("会话的ID是:" + session.getId() + "<hr/>");
        //时间戳:java.sql.Timestamp(毫秒数) 构造方法传递的参数就是一个毫秒数
        //获取会话创建的时间,返回的是一个long类型,1970年1月1日到这个时间之间相差的毫秒数
        out.print("会话创建的时间:" + new Timestamp(session.getCreationTime()) + "<br/>");
        //判断当前会话是否是新的会话
        out.print("是否新的会话:" + session.isNew() + "<hr/>");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

小结

如何创建或获取一个会话对象? request.getSession(),第一次访问是创建会话,以后是获取会话。

HttpSession接口方法作用
String getId()获取会话的ID
long getCreationTime()获取会话创建的时间,返回毫秒数
boolean isNew()判断是否是一个新的会话,第一次返回true,以后返回false

13. 会话域的操作方法【重点】

目标

与会话域有关的操作方法

讲解

三个作用域
  1. 请求域:一个用户的一次请求
  2. 会话域:一个用户的所有请求
  3. 上下文域:所有用户的所有请求

请求域 < 会话域 < 上下文域

会话域用于:购物车,用户的权限验证

会话域中的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IHmNxF7d-1598876514126)(assets/1552450034543.png)]

演示案例

需求

​ 通过1个案例学习上面方法的使用

执行效果
  1. 先执行向会话域中添加值的Servlet

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B8abt2Xv-1598876514128)(assets/1552450585063.png)]

  1. 再执行从会话域中取值的Servlet

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q8sjqvow-1598876514130)(assets/1552450653128.png)]

  1. 另一个浏览器执行的效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-91xXAgIU-1598876514131)(assets/1552450684828.png)]

代码
SetServlet.java
package com.itheima.servlet;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/demo2")
public class Demo2SetServlet extends HttpServlet {
    //向会话域中添加键和值
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取会话对象
        HttpSession session = request.getSession();
        //2.调用方法向会话域中添加键和值
        session.setAttribute("product", "娃娃");

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("向会话域中添加了键和值");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
GetServlet.java
package com.itheima.servlet;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/demo3")
public class Demo3GetServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //1.获取会话对象,取的与demo2中是同一个会话对象
        HttpSession session = request.getSession();
        //2.从会话域中取出值
        String product = (String) session.getAttribute("product");
        //3.输出到页面
        out.print("商品名字:" + product);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

小结:课堂提问

为什么另一个浏览器得不到放在会话域中的值?

关键点是他们的会话ID不同
  • 1

14. 会话访问的原理【重点】

目标

  1. 学习Session的会话原理
  2. 保存会话ID到Cookie中

原理分析

查看SetServlet中响应头

会话ID通过Cookie发送给浏览器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-khsapLLN-1598876514133)(assets/image-20200831151050787.png)]

查看GetServlet的请求头

浏览器将会话ID通过Cookie发送给服务器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pHqjUcsl-1598876514134)(assets/image-20200831151134300.png)]

原理图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w4nxfjhf-1598876514136)(assets/image-20200831150901798.png)]

疑问

  1. 如果浏览器关闭,服务器上的会话信息是否还存在?

    还在,直到服务器上会话过期,默认是30分钟。
    
    • 1
  2. 浏览器关闭以后,还能不能得到之前会话域中的信息?

    正常是不能的
    
    • 1
  3. 有没有可能让浏览器关闭还可以再访问服务器上没有过期的信息?

    可以,手动将会话ID保存,并且设置过期时间
    
    • 1

演示案例

步骤
  1. 创建会话对象
  2. 得到会话的ID
  3. 创建一个Cookie,将它的名字设置为JSESSIONID,值为上面的会话ID
  4. 设置过期时间为30分钟
  5. 写入到浏览器
代码
package com.itheima.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/demo2")
public class Demo2SetServlet extends HttpServlet {
    //向会话域中添加键和值
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取会话对象
        HttpSession session = request.getSession();
        //2.调用方法向会话域中添加键和值
        session.setAttribute("product", "娃娃");

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("向会话域中添加了键和值");

        //手动创建一个Cookie的数据,键是JSESSIONID,值是会话的ID,并且设置过期的时间
        Cookie cookie = new Cookie("JSESSIONID", session.getId());
        //设置过期的时间
        cookie.setMaxAge(60 * 30);
        //添加到浏览器端
        response.addCookie(cookie);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-59yginKr-1598876514138)(assets/image-20200831152155424.png)]

小结

服务器与浏览器之间是如何将会话ID发送给对方的

通过Cookie发送
  • 1

15. 修改会话过期时间的三种方式

目标

​ 学习设置会话过期的三种方式

查看会话过期的时间

  • 疑问:Session在服务器上默认的销毁时间是多久?如何查看?

修改会话过期时间的三种方式

方式一:通过代码
session.setMaxInactiveInterval();
  • 1
示例:设置会话过期的时间为10秒,输出过期的时间,输出会话ID
代码
package com.itheima.servlet;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 获取会话过期的时间间隔
 */
@WebServlet("/demo4")
public class Demo4IntervalServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        //1.获取会话对象
        HttpSession session = request.getSession();

        //设置过期的时间是10秒
        //session.setMaxInactiveInterval(10);

        //2.获取会话过期的时间间隔,单位是秒。非活动:没有新的请求
        //如果设置为10秒,第9秒的时候有一次请求,服务器就会重新计时10秒
        int interval = session.getMaxInactiveInterval();
        out.print("会话过期的时间是:" + interval + "<hr/>");
        out.print("会话ID是:" + session.getId() + "<br/>");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
方式二:可以通过web.xml的配置来实现
<!--会话的配置-->
<session-config>
    <!--过期的时间: 单位是分-->
    <session-timeout>5</session-timeout>
</session-config>
  • 1
  • 2
  • 3
  • 4
  • 5

疑问:如果同时使用代码和配置的方式以哪个为准?

以代码为准,后面的代码会覆盖前面的配置
  • 1
方式三:立刻失效

应用场景:用于用户退出或注销,让会话马上过期。会释放当前用户会话域中所有资源

session.invalidate();
  • 1

小结

修改会话过期的时间有哪三种方式?

  1. session.setMaxInactiveInterval(秒)

  2. 在web.xml中配置

    <session-config>
       <session-timeout>分钟</session-timeout>
    </session-config>   
    
    • 1
    • 2
    • 3
  3. 马上失效:session.invalidate()

16. URL重写:禁用Cookie的处理【了解】

目标

  1. Cookie禁用后重写向的处理
  2. Cookie禁用后超连接的处理

禁用Cookie后会话中共享数据导致的问题

  1. 把浏览器的Cookie禁用
  2. 在一个Servlet1中向session中添加一个数据,重定向到Servlet2。
  3. 在另一个Servlet2中的session中读取数据并显示出来
  4. 无法得到原来会话中的信息
效果

浏览器不会把会话ID再发送给服务器,导致服务器上会话数据读取不出来。

解决方法

不能通过Cookie来发送会话ID,在地址栏上发送会话id

  1. 分隔符是;
  2. jsessionid是小写

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hWCcSKPM-1598876514141)(assets/image-20200831155832231.png)]

重定向的解决方法

什么是URL重写:

响应对象的方法说明
response.encodeRedirectURL(path)在要跳转过去的地址栏后面加上会话id

重写前的URL:

demo3
  • 1

重写后的URL:

demo3;jsessionid=5933A9F542C0938DDE196E3DF80C0C82
  • 1
代码
//URL重写:在地址后面加上会话的ID,使用分号隔开
String url = response.encodeRedirectURL("demo3");
//输出到浏览器上
out.println("<a href='" + url + "'>跳转到demo3</a>");
  • 1
  • 2
  • 3
  • 4

思考

使用URL重写以后,不同的浏览器可不可以访问其它浏览器的会话数据?

理论上是可以访问的
  • 1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OkrSf0Lo-1598876514145)(assets/image-20200831160506165.png)]

小结

方法说明
response.encodeRedirectURL(path)将会话ID添加到URL的后面,使用分号隔开

17. 案例part1:登录验证码的准备【作业】

目标

登录验证码环境的搭建

流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2OGzsFOe-1598876514148)(assets/image-20200831161318298.png)]

需求:用户登录的时候使用验证码进行验证

​ 登录成功后将用户信息保存到会话域中,并且跳转到WelcomeServlet,然后在WeclcomeServlet中读取用户信息,显示欢迎信息。在WelcomeServlet上显示退出的链接,点退出,注销会话信息。

步骤

  1. 复制登录的原型login.html,添加name属性
  2. 复制昨天已经写好的验证码,修改验证码代码。将字符串保存在会话域中
  3. 搭建整个项目,今天不访问数据库。

登录页面

<div class="col-sm-3">
	<!--指定为servlet,鼠标移上去变成手-->
	<img src="code" style="cursor: pointer" title="看不清换一张" id="picCode"/>

	<script type="text/javascript">
		//编写图片的点击事件
		document.getElementById("picCode").onclick = function () {
			//修改图片的src,并且指定一个变化的参数
			this.src = "code?n=" + new Date().getTime();
		};
	</script>
</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

验证码的Servlet

package com.itheima.servlet;

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 javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

@WebServlet("/code")
public class PicCodeServlet extends HttpServlet {

    //随机类
    private Random random = new Random();

    /**
     * 随机获取一种颜色
     */
    private Color getRandomColor() {
        //随机得到r,g,b的取值,范围是0~255
        int r = random.nextInt(256);
        int g = random.nextInt(256);
        int b = random.nextInt(256);
        return new Color(r, g, b);  //red红 green绿 blue蓝
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置MIME类型
        response.setContentType("image/jpeg");
        //定义宽和高的值
        int width = 90;
        int height = 30;
        //1. 创建一张图片,参数:宽,高,图片模式
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //获取画笔对象
        Graphics graphics = image.getGraphics();
        //整个图片填充白色
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0,0,width,height);

        //2. 随机绘制4个验证码
        char[] arr = { 'A', 'B', 'C', 'D', 'N', 'E', 'W', 'b', 'o', 'y', '1', '2', '3', '4','5','6','7','8' };

        //设置字体,字体对象有三个参数:字体名字,字体样式(加粗,斜体), 大小
        graphics.setFont(new Font(Font.DIALOG_INPUT, Font.BOLD + Font.ITALIC, 19));

        //创建一个StringBuilder
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < 4; i++) {
            //随机获取1个索引号
            int index = random.nextInt(arr.length);
            //随机获取字符数组的一个字符
            char c = arr[index];
            sb.append(c);
            //每个字符的颜色不同
            graphics.setColor(getRandomColor());
            //写字符,参数:文字内容,x,y坐标  (把字符转成字符串)
            graphics.drawString(String.valueOf(c),10+(i*20), 20);
        }

        //把验证码放在会话域中
        HttpSession session = request.getSession();
        //转成字符串以后放到会话域中
        session.setAttribute("code", sb.toString());
        System.out.println("生成的验证码是:" + sb);

        //3. 绘制8条干扰线
        for (int i = 0; i < 8; i++) {
            //指定颜色
            graphics.setColor(getRandomColor());
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            int x2 = random.nextInt(width);
            int y2 = random.nextInt(height);
            //画线,起点和终点
            graphics.drawLine(x1,y1,x2,y2);
        }

        //4. 把图片输出到浏览器,参数:输出的图片对象,图片格式,响应输出流
        ImageIO.write(image,"jpg", response.getOutputStream());
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

18. 案例part2:登录的Servlet

目标

​ 实现登录的Servlet

步骤

  1. 使用昨天的代码实现验证码的绘制
  2. 将随机产生的字符串放在会话域中
  3. 用户登录的时候提交验证码的字符串
  4. 比较表单提交的字符串是否与会话域中的字符串相等,如果相等则验证成功
  5. 登录一次以后删除会话域中的验证码字符串
  6. 登录成功以后保存用户的信息到会话域中,并且跳转到WelcomeServlet

代码

package com.itheima.servlet;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

       //1.判断验证码,验证码放在会话域中
        HttpSession session = request.getSession();  //获取会话对象
        String code = (String) session.getAttribute("code");  //从会话域中取出验证码
        //获取用户提交的验证码
        String vcode = request.getParameter("vcode");
        //判断验证码是否正确,忽略大小写比较
        if (vcode.equalsIgnoreCase(code)) {
            //2.判断用户名和密码
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            if ("admin".equals(username) && "123".equals(password)) {
                //把用户的信息保存在会话域中,这是一个标记,表示用户已经登录成功
                session.setAttribute("username", username);
                //3.如果成功跳转到welcome
                response.sendRedirect("welcome");
            }
            //用户名密码错误
            else {
                out.print("<script>");
                out.print("alert('用户名或密码错误');");
                out.print("location.href='login.html';");
                out.print("</script>");
            }
        }
        //验证码错误
        else {
            //使用脚本跳转,可以看到错误信息
            out.print("<script>");
            out.print("alert('验证码错误');");
            out.print("location.href='login.html';");
            out.print("</script>");
            //4.如果失败跳转到login.html
            //response.sendRedirect("login.html");
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

19. 案例part3:欢迎Servlet和注销的Servlet

目标

  1. 在欢迎的Servlet上显示用户的信息
  2. 点退出链接,用户注销
  3. 如果没有正确登录的用户,不能访问WelcomeServlet

步骤

  1. 从会话域中取出用户信息并且显示
  2. 判断用户是否正常登录,如果是非法用户则跳转到登录页面
  3. 在页面上输出一个注销的连接,点注销跳转到LogoutServlet
  4. 注销:调用invalidate(),重定向到login.html

代码

WelcomeServlet
package com.itheima.servlet;

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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

/*
这个页面必须进行权限验证
原理:只要登录成功的用户,会话域中是有数据的,没有登录的用户,会话域中用户信息是空的
 */
@WebServlet("/welcome")
public class WelcomeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        //获取会话域
        HttpSession session = request.getSession();
        //从会话域中取出用户的信息
        String username = (String) session.getAttribute("username");

        //表示没有登录
        if (username == null) {
            //getRemoteAddr() 获取客户端的IP地址
            System.out.println("拦截到了非法的用户:" + request.getRemoteAddr());
            response.sendRedirect("login.html");
            //后面的代码还会继续运行的
            return;
        }

        //输出用户的信息
        out.print("<h1>登录成功,欢迎您!" + username + "</h1>");
        out.print("<a href='logout'>退出</a>");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
LogoutServlet
package com.itheima.servlet;

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("/logout")
public class LogoutServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.销毁会话
        request.getSession().invalidate();
        //2.重定向到登录页面
        response.sendRedirect("login.html");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

小结

  1. 验证码放在会话域中
  2. 登录的时候先从会话域中取出验证码,再判断用户名和密码
  3. 如果登录成功跳转到欢迎页面,并从会话域中取出用户信息显示
  4. 登录失败跳转到登录页面
  5. 点退出注销会话,跳转到登录页面

学习总结

  1. 能够说出会话的概念

    创建:浏览器第一次访问,由服务器创建会话。

    过程:浏览器与服务器之间的多次请求和响应

    结束:浏览器关闭或服务器会话过期

  2. 能够说出cookie的概念

    1. 保存在: 浏览器端的硬盘中

    2. 键和值都是: 字符串类型,每个Cookie保存一个键值对

    3. 默认浏览器关闭: Cookie失效

  3. 能够创建、发送、接收、删除cookie

    方法名作用
    new Cookie(名字,值)创建一个Cookie对象
    response.addCookie(Cookie cookie)把Cookie发送到浏览器写入
    Cookie[] request.getCookies()获取浏览器端所有的Cookie对象数组
    setMaxAge(0)删除Cookie
  4. 能够说出cookie执行原理

    1544243690839
  5. 能够说出session的概念

    1. 保存在: 服务器的内存中

    2. 键和值:键是字符串类型,值是Object类型

    3. 默认过期:30分钟

    修改过期的时间:

    1. setMaxInactiveInterval(秒)
    2. web.xml中配置session-config session-timeout 分钟
    3. invalidate() 马上过期
  6. 能够获取session对象、添加、删除、获取session中的数据

    方法名作用
    request.getSession()第一次访问创建会话,以后是获取会话对象
    session.setAttribute(“键”, 值)向会话域中添加键和值
    session.getAttribute(“键”)从会话域中取出值
    session.removeAttribute(“键”)删除键和值
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/104381?site
推荐阅读
相关标签
  

闽ICP备14008679号