IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 【后端】Cookie和Session -> 正文阅读

[网络协议]【后端】Cookie和Session

会话的概念:用户打开浏览器,浏览不同的网页(资源),发出多个请求,直到关闭浏览器的过程,称为一次会话(多次请求)。即浏览器从开启到关闭,中间的使用过程。

会话技术:在会话过程(多次请求)中,用户产生的一些数据需要通过会话技术保存起来。会话技术可以保存用户各自(以浏览器为单位)的数据。

一、Cookie

1. 概念

原理:cookie是客户端(浏览器)端的技术,用户浏览的信息以键值对(key-value)的形式保存到浏览器上。若未关闭浏览器,就会将cookie数据带到服务端,服务端可以通过接口来获取cookie数据

image-20211112210513973

作用

  • 在浏览器中存放数据
  • 将浏览器存放的数据带到服务器

使用场景

  • 浏览器记住用户名和密码,下次自动登录
  • 保存电影的播放进度

2. 使用方式

2.1 API

  • 创建Cookie:cookie的数据只能是键值对,且长度有限制;value中不能有空格

    new Cookie(String name,String value);
    
  • 设置cookie生命周期:0代表废除当前cookie,非0即便关掉浏览器依然有效

    cookie.setMaxAge(int expiry);
    
  • 设置cookie路径:用来区别不同服务端的数据,一般为request.getContextPath()

    cookie.setPath(String url);
    
  • 将cookie回复浏览器:将cookie数据返回给客户端,本质上是响应头

    response.addCookie(cookie); 
    
  • 获取所有cookie:所有cookie是以数组的方式呈现,本质上是请求头

    request.getCookies();
    
  • 获取cookie的值

    cookie.getName();
    cookie.getValue();
    

2.2 使用

封装工具类

public class ServletUtils {
    public static Cookie getCookie(String name, String value, int maxAge, String path) {
        Cookie cookie = new Cookie(name, value);	//创建cookie
        if (null != cookie) {
            cookie.setMaxAge(maxAge);	//设置生命周期
            cookie.setPath(path);	//设置路径
            return cookie;
        }
        return null;
    }
    public static String getCookieValue(Cookie[] cookies, String name) {
        if (null != cookies) {
            for (Cookie cookie : cookies) {	//遍历所有cookie
                if (cookie.getName().equals(name)) {
                    return cookie.getValue();	//获取指定cookie
                }
            }
        }
        return null;
    }
}

3. 实例:获取上次访问时间

@WebServlet("/lasttime")
public class GetLastTime extends HttpServlet {
	...
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        //获取上次记录的访问时间
        String lasttime = ServletUtils.getCookieValue(request.getCookies(), "lasttime");
        System.out.println(lasttime);
        //若是第一次访问
        if (lasttime == null) {
            //输出第一次
            response.getWriter().println("第一次访问");
        } else { //若是第n次访问
            response.getWriter().println("上次访问时间:" + lasttime);
        }

        //记录访问时间
        //获取当前时间:值不能有空格
        String date = new SimpleDateFormat("yyyy-MM-dd/HH:mm:ss").format(new Date());
        //记录
        Cookie cookie = ServletUtils.getCookie("lasttime", date, 60*60, request.getContextPath());
        //添加cookie
        response.addCookie(cookie);
    }
}

二、Session

1. 概念

1.1 基本介绍

概述

session是服务器端的技术,服务器为每一个浏览器开辟一块内存空间,即session对象。

  • 每个浏览器在服务器中中都有一个特有的session对象,所以用户记录可以存放在session对象中
  • 每一个session对象都对应一个存放在cookie中的sessionId,服务器通过浏览器带过来的sessionId找到对应的session对象

执行原理

  1. 获取浏览器请求中cookie中的sessionid

  2. 若无sessionid,则创建session对象,并将sessionid通过cookie存入浏览器

  3. 若有sessionid,则通过sessionid找到对应的session对象后使用

    image-20211114200403408

关闭浏览器和服务器

  • 关闭浏览器

    • 关闭浏览器不代表其在服务器对应的session就销毁了,而是浏览器通过cookie保存的sessionid销毁了,无法通过sessionid找到对应的session了。
    • 若要长期使用session,可以通过设置sessionid的cookie(JSESSIONID)声明周期的方式来实现。
  • 关闭服务器

    • 如果是正常关闭服务器,把session钝化到服务器磁盘上,再次启动,把磁盘上的文件活化到内存里
    • Session钝化:把内存中的session序列化保存到硬盘上
    • Session活化:从硬盘上读取序列化的session到内存中形成一个session对象

1.2 对比

cookie和session

  • cookie是保存在浏览器端,大小和个数都有限制;session是保存在服务器端的, 原则上大小是没有限制
  • cookie不支持中文,并且只能存储字符串;session可以存储基本数据类型,集合,对象等

三个域对象比较

域对象创建销毁作用范围应用场景
ServletContext服务器启动服务器正常关闭/项目从服务器移除整个项目记录网站访问次数,聊天室
HttpSession没有JSESSIONID这个cookie的时候,调 用request.getSession()方法session过期(默认闲置30分钟),或者调用session对象的invalidate()方法,或者服务器异常关闭会话(多次请求)验证码校验, 保存用户登录状态
HttpServletRequest来了请求响应这个请求(或者请求已经接收了)一次请求servletA和jsp(servletB)之间数据传递(转发的时候存数据)

域对象的选择

  • 一般情况下, 最小的可以解决就用最小的
  • 根据情况,如重定向, 多次请求, 会话范围, 用session; 如果是转发,一般选择request
  • 若必须要存在浏览器上的数据(如用户名、登录密码等用户信息)用cookie,否则一般都是用session

2. 使用方式

2.1 API

获取session,第一次使用实际上是创建session

request.getSession();

设置session数据

Object getAttribute(String name);

获取session数据

void setAttribute(String name, Object value);

移除当前session

void removeAttribute(String name);

2.2 使用

SessionServletDemo01.class

@WebServlet("/session01")
public class SessionServletDemo01 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 {
        HttpSession session = request.getSession();
        String str = "jay";
        session.setAttribute("str", str);
    }
}

SessionServletDemo02.class

@WebServlet("/session02")
public class SessionServletDemo02 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 {
        HttpSession session = request.getSession();
        String str = (String) session.getAttribute("str");
        System.out.println(str);
    }
}

3. 实例:验证码校验

CheckCodeServlet.class

@WebServlet("/checkCode")
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 {
        //创建验证码
        ValidateCode validateCode = new ValidateCode(120, 40, 5, 100);
        //发送给浏览器
        validateCode.write(response.getOutputStream());
		//将验证码的值发送给提交页面去验证
        HttpSession session = request.getSession();
        String code = validateCode.getCode();
        session.setAttribute("ValidateCode", code);
    }
}

LoginServlet.class

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        //1. 获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String checkCode = request.getParameter("checkCode");

        //判断验证码是否正确
        HttpSession session = request.getSession();
        String code = (String) session.getAttribute("ValidateCode");
        if (code.equalsIgnoreCase(checkCode)) {
 			sout("验证码正确");       
        }
    }
}

三、JSP

1. 概述

JSP(Java Server Page):java服务器页面,JSP本质就是servlet,用于开发动态web资源的技术。包含html(js、css) + java(servlet) + jsp(内置对象、子陵、动作标签等)特有内容

作用

当服务器用servlet通过getWrite().write()方法,向html展示页面输出一个动态的表格等动态资源时,步骤会相当繁琐。为了解决这个问题,定义了JSP,其文件内部可以同时写HTML和JAVA代码

执行原理

JSP会通过默认的JspServlet、JSP引擎翻译成Servlet的.java文件,将Servlet的.java文件编译成.class文件。所以.jsp文件本质上还是servlet文件,最终还是用转换后的servlet文件通过getWrite().write()方式向html输出html文本。

  1. 第一次访问的jsp文件时,服务器会通过JspServlet去查找对应的jsp文件
  2. 找到之后,服务器会将这个jsp文件转换成.java文件(Servlet)
  3. 服务器编译java文件,生成class文件
  4. 服务器运行class文件,生成动态的内容
  5. 服务器收到内容之后,返回给浏览器

image-20211116084431945**

2. 基本语法

2.1 语法

脚本

类型翻译成Servlet对应的部分
<%…%>:Java程序片段翻译成Service()方法里面的内容, 局部的
<%=…%>:输出表达式翻译成Service()方法里面的内容,相当于调用out.print()
<%!..%>:声明成员变量(肯定不用)翻译成Servlet类里面的内容

注释

注释类型
HTML注释
// 或 /* */JAVA注释
<%–注释内容–%>JSP注释

2.2 使用

test.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆页面</title>
</head>
<body>

<%--JAVA代码--%>
<%
    //获取cookie
    String username = "";
    for (int i = 0; i < 10; i++) {
      	sout("i");
    }
%>
<%--HTML文本-%>    
<form action="login" method="post">
    <!--用户名-->
    用户名<input type="text" name="username" value=<%=username%>><br>
    密码<input type="password" name="password"><br>
</form>
</body>
</html>

3. 实例:优化登录案例

login.jsp

  • 根据登录时不同的错误错误,输出不同的错误提醒
  • 根据点击/取消保存用户名,实现用户名输入栏自动出现/消失用户名
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆页面</title>
</head>
<body>

<%--获取错误码--%>
<%
    String errMsg = (String) request.getAttribute("errMsg");
    if (errMsg == null) {
        errMsg = "";
    }

    //获取cookie
    String username = "";
    String remember = "";
    Cookie[] cookies = request.getCookies();
    for (Cookie cookie : cookies) {
        if (cookie.getName().equals("username")) {
            username = cookie.getValue();
            remember = "on";
            System.out.println(username);
        }
    }

%>
<div style="color: red"><%=errMsg%></div><br>

<form action="login" method="post">
    
    用户名<input type="text" name="username" value=<%=username%>><br>
    密码<input type="password" name="password"><br>
    验证码<input type="text" name="checkCode"><br>
    <img src="checkCode" width="200"><br>
    <input type="checkbox" name="remember" value=<%=remember%>记住用户名<br>
    <input type="submit" value="提交">
</form>
</body>
</html>

LoginServlet.java

  • 校验浏览器发送的登录数据不对时,跳转回登录页面
  • 保存当前会话的用户数据
  • 根据浏览器的选择,将用户名发送/取消给浏览器
@WebServlet("/login")
    public class LoginServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }

        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            //1. 获取请求参数
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            String checkCode = request.getParameter("checkCode");

            //判断是否要记住用户名
            String remember = request.getParameter("remember");
            Cookie cookie = new Cookie("username", username);
            cookie.setPath(request.getContextPath());
            if (remember != null) {
                //将用户名通过cookie发送给浏览器
                cookie.setMaxAge(60*60*24);
                System.out.println(username);
            } else {
                //清除用户名cookie
                cookie.setMaxAge(0);
            }
            response.addCookie(cookie);


            //判断验证码是否正确
            HttpSession session = request.getSession();
            String code = (String) session.getAttribute("ValidateCode");
            if (code.equalsIgnoreCase(checkCode)) {
            //2. 连接数据库校验用户名和密码
            String sql = "select * from user where username=? and password=?";
            QueryRunner queryRunner = new QueryRunner(DruidUtil.getDataSource());
            try {
                User user = queryRunner.query(sql, new BeanHandler<>(User.class), username, password);
                if (user != null) {
                    //登录成功
                    response.getWriter().write("登录成功");
                    //保存用户数据
                    session.setAttribute("user", user);
                    //将用户名发送给客户端保存

                    request.getRequestDispatcher("success.jsp").forward(request, response);

                }else {
                    //登录失败
                    //response.getWriter().write("登录失败");
                    String errMsg = "用户名或密码错误";
                    request.setAttribute("errMsg", errMsg);
                    request.getRequestDispatcher("login.jsp").forward(request, response);
                }
            } catch (Exception e) {
                e.printStackTrace();
                //response.getWriter().write("登录失败");
                String errMsg = "用户名或密码错误";
                request.setAttribute("errMsg", errMsg);
                request.getRequestDispatcher("login.jsp").forward(request, response);
            }
        } else {
            //response.getWriter().write("验证码输入错误");
            String errMsg = "验证码错误";
            request.setAttribute("errMsg", errMsg);
            request.getRequestDispatcher("login.jsp").forward(request, response);
        }
    }
}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-11-17 13:06:20  更:2021-11-17 13:08:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/3 20:42:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码