• 会话技术中的Cookie与session


    关于会话技术


    1. 会话:一次会话中包含多次请求和响应。
      • 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
    2. 功能:在一次会话的范围内的多次请求间,共享数据
    3. 方式:
      1. 客户端会话技术:Cookie
      2. 服务器端会话技术:Session


    Cookie:

    1. 概念:客户端会话技术,将数据保存到客户端

    2. 使用步骤:

      1. 创建Cookie对象,new Cookie(String name, String value) 绑定数据。
      2. 发送Cookie对象, response.addCookie(Cookie cookie)
      3. 再次请求时,获取Cookie,拿到数据, Cookie[] request.getCookies()
      4. 实现原理其实是基于响应头set-cookie,请求头cookie实现
      • 服务器生成Cookie发送给浏览器
     1    package cn.testRep.web.servlet.cookie;
    2
    3    import javax.servlet.ServletException;
    4    import javax.servlet.annotation.WebServlet;
    5    import javax.servlet.http.Cookie;
    6    import javax.servlet.http.HttpServlet;
    7    import javax.servlet.http.HttpServletRequest;
    8    import javax.servlet.http.HttpServletResponse;
    9    import java.io.IOException;
    10
    11    @WebServlet("/servletCookieDemo1")
    12    public class ServletCookieDemo1 extends HttpServlet {
    13        protected void doPost(HttpServletRequest request, HttpServletResponse   response) throws ServletException, IOException {
    14
    15
    16            //1创建cookie对象
    17            Cookie cookie = new Cookie("msg","hello");
    18            //2发送cookie给浏览器
    19            response.addCookie(cookie);
    20
    21        }
    22
    23        protected void doGet(HttpServletRequest request, HttpServletResponse    response) throws ServletException, IOException {
    24            this.doPost(request,response);
    25
    26        }
    27    }
    • 服务器获取浏览器保存的Cookie
     1    package cn.testRep.web.servlet.cookie;
    2
    3    import javax.servlet.ServletException;
    4    import javax.servlet.annotation.WebServlet;
    5    import javax.servlet.http.Cookie;
    6    import javax.servlet.http.HttpServlet;
    7    import javax.servlet.http.HttpServletRequest;
    8    import javax.servlet.http.HttpServletResponse;
    9    import java.io.IOException;
    10
    11    @WebServlet("/servletCookieDemo2")
    12    public class ServletCookieDemo2 extends HttpServlet {
    13        protected void doPost(HttpServletRequest request, HttpServletResponse   response) throws ServletException, IOException {
    14
    15            //获取客户端的Cookie
    16            Cookie[] cookie = request.getCookies();
    17            //遍历Cookies
    18            if(cookie != null){
    19                for (Cookie c: cookie) {
    20                    String name = c.getName();
    21                    String value = c.getValue();
    22                    System.out.println(name+":"+value);
    23                }
    24            }
    25
    26        }
    27
    28        protected void doGet(HttpServletRequest request, HttpServletResponse    response) throws ServletException, IOException {
    29            this.doPost(request,response);
    30
    31        }
    32    }

    cookie的细节

    1. 一次可不可以发送多个cookie?

      • 可以
      • 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。
    2. cookie在浏览器中保存多长时间?

      1. 默认情况下,当浏览器关闭后,Cookie数据被销毁
      2. 持久化存储:setMaxAge(int seconds)
        正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效。
        负数:为默认值,关闭即销毁。
        0:删除保存的cookie信息。
    3. cookie能不能存中文?

      • 在tomcat 8 之前 cookie中不能直接存储中文数据,需要将中文数据转码---一般采用URL编码(%E3)。
      • 在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
    4. cookie共享问题?
      问: 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
      答: 默认情况下cookie不能共享,但是setPath(String path)可设置cookie的获取范围。默认情况下,设置当前的虚拟目录,如果要共享,则可以将path设置为"/"。即IP地址下的项目都可以共享。

      问: 不同的tomcat服务器间cookie共享问题?
      答: setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享,
      如 setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享

    5. Cookie的特点和作用

      1. cookie存储数据在客户端浏览器
      2. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)
      • 作用1:cookie一般用于存出少量的不太敏感的数据
      • 作用2:在不登录的情况下,完成服务器对客户端的身份识别
        注意:cookie中特殊字符会报错,例如空格

    案例:记住上一次访问时间

    1. 需求:

      1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
      2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
    2. 分析:

      1. 可以采用Cookie来完成
      2. 在服务器中的Servlet判断是否有一个名为lastTime的cookie
        有:不是第一次访问响应数据
        没有:是第一次访问, 响应数据:您好,欢迎您首次访问
    3. 代码实现:

     1package cn.testRep.web.servlet.cookie;
    2
    3import javax.servlet.ServletException;
    4import javax.servlet.annotation.WebServlet;
    5import javax.servlet.http.Cookie;
    6import javax.servlet.http.HttpServlet;
    7import javax.servlet.http.HttpServletRequest;
    8import javax.servlet.http.HttpServletResponse;
    9import java.io.IOException;
    10import java.net.URLDecoder;
    11import java.net.URLEncoder;
    12import java.text.SimpleDateFormat;
    13import java.util.Calendar;
    14import java.util.Date;
    15import java.util.logging.SimpleFormatter;
    16
    17@WebServlet("/servletCookieDemo1")
    18public class ServletCookieDemo1 extends HttpServlet {
    19    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    20
    21        //设置响应的消息体数据格式以及编码
    22        response.setContentType("text/html;charset=utf-8");
    23        //定义一个标记
    24        boolean flag =false;
    25
    26        //获取客户端的Cookie
    27        Cookie[] cookie = request.getCookies();
    28        //遍历Cookies
    29        if(cookie != null && cookie.length > 0){
    30            for (Cookie c: cookie) {
    31                String name = c.getName();
    32                if(name.equals("lastTime")){
    33                    flag = true;
    34                    String value = c.getValue();
    35
    36                    //服务器响应数据
    37                    response.getWriter().write("<h1>欢迎回来,你上次访问时间是<h1>"+URLDecoder.decode(value,"utf-8"));
    38
    39                    //获取时间,更新cookie数据
    40                    Date date = new Date();
    41                    //设置时间格式
    42                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    43                    value = simpleDateFormat.format(date);
    44                    value = URLEncoder.encode(value,"utf-8");
    45                    c.setValue(value);
    46                    //设置存活时间一个月
    47                    c.setMaxAge(60*60*24*30);
    48                    response.addCookie(c);
    49
    50                    break;
    51                }
    52            }
    53        }
    54
    55        //若没有我们查找的cookie
    56        if (!flag ){
    57            //获取时间,更新cookie数据
    58            Date date = new Date();
    59            //设置时间格式
    60            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:MM:SS");
    61            String value = simpleDateFormat.format(date);
    62            //url编码处理特殊字符报错问题
    63            value = URLEncoder.encode(value,"utf-8");
    64            Cookie cookie1 = new Cookie("lastTime",value);
    65            //设置存活时间一个月
    66            cookie1.setMaxAge(60*60*24*30);
    67            response.addCookie(cookie1);
    68
    69            //设置响应内容
    70            response.getWriter().write("<h1>第一次使用,存入时间为:<h1>"+ URLDecoder.decode(value,"utf-8"));
    71
    72        }
    73    }
    74
    75    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    76        this.doPost(request,response);
    77
    78    }
    79}


    JSP:入门

    1. 概念:

      • Java Server Pages: java服务器端页面
      • 可以理解为:一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码,用于简化书写(不在Servlet里进行书写)!!!
    2. 原理

      • JSP本质上就是一个Servlet,浏览器访问服务器时,.jsp会转换为.java(该类继承了tomcat里的HttpJspBase,而HttpJspBase继承了HttpServlet),再进行编译为.class文件进行返回。
    3. JSP的脚本:JSP定义Java代码的方式

      1. <% 代码 %>:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
      2. <%! 代码 %>:定义的java代码,会出现在jsp转换后java类的成员位置。(用的少,线程安全问题)
      3. <%= 代码 %>:对已经定义的java代码,可输出到页面上。实际在转为后的index_jsp.java类中,出现在out.print(xx)中。
    4. JSP的内置对象:

      • 在jsp页面中不需要获取和创建,可以直接使用的对象,如下 request,response等
      • out:字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似
        response.getWriter()和out.write()的区别:
        1.在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。
        2.response.getWriter()数据输出永远在out.write()之前
      • jsp一共有9个内置对象。
    5. 案例:用Jsp改造上述Cookie案例

     1<%@ page import="java.net.URLDecoder" %>
    2
    <%@ page import="java.util.Date" %>
    3
    <%@ page import="java.text.SimpleDateFormat" %>
    4
    <%@ page import="java.net.URLEncoder" %><%--
    5  Created by IntelliJ IDEA.
    6  User: Administrator
    7  Date2020/2/26 0026
    8  Time9:40
    9  To change this template use File | Settings | File Templates.
    10--%>

    11
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    12<html>
    13<head>
    14    <title>显示时间</title>
    15</head>
    16<body>
    17
    18
    <%
    19    //定义一个标记
    20    boolean flag = false;
    21
    22    //获取客户端的Cookie
    23    Cookie[] cookie = request.getCookies();
    24    //遍历Cookies
    25    if (cookie != null && cookie.length > 0) {
    26        for (Cookie c : cookie) {
    27            String name = c.getName();
    28            if (name.equals("lastTime")) {
    29                flag = true;
    30                String value = c.getValue();
    31%>
    //截断
    32
    33<h1> 欢迎回来,你上次访问时间是:
    <%= URLDecoder.decode(value, "utf-8") %></h1>
    34<hr>
    35
    <%
    36                //获取时间,更新cookie数据
    37                Date date = new Date();
    38                //设置时间格式
    39                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    40                value = simpleDateFormat.format(date);
    41                value = URLEncoder.encode(value, "utf-8");
    42                c.setValue(value);
    43                //设置存活时间一个月
    44                c.setMaxAge(60 * 60 * 24 * 30);
    45                response.addCookie(c);
    46
    47                break;
    48            }
    49        }
    50    }
    51
    52    //若没有我们查找的cookie
    53    if (!flag) {
    54        //获取时间,更新cookie数据
    55        Date date = new Date();
    56        //设置时间格式
    57        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:MM:SS");
    58        String value = simpleDateFormat.format(date);
    59        //url编码处理特殊字符报错问题
    60        value = URLEncoder.encode(value, "utf-8");
    61        Cookie cookie1 = new Cookie("lastTime", value);
    62        //设置存活时间一个月
    63        cookie1.setMaxAge(60 * 60 * 24 * 30);
    64        response.addCookie(cookie1);
    65%>

    66//设置响应内容
    67<h1>第一次使用,存入时间为:
    <%= URLDecoder.decode(value, "utf-8") %></h1>
    68<hr>
    69
    <%
    70
    71    }
    72%>

    73
    74</body>
    75</html>
    76


    Session:

    1. 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中HttpSession

    2. 常用对象:

      1. 获取HttpSession对象:
        HttpSession session = request.getSession();
      2. 使用HttpSession对象:
        Object getAttribute(String name)
        void setAttribute(String name, Object value)
        void removeAttribute(String name)
    3. 原理

      • Session的实现是依赖于Cookie的。其实在第一次获取Session对象时,会生成一个JSESSIONID值,并作为响应头set-cookie进行返回。浏览器在第二次请求时,服务器获取Session对象时会再查找内存中是否有这个id。有,则可以得到第一次请求存储在服务器的Session内容。
    4. 一些细节:

      1. 问: 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
        答: 默认情况下。不是。如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
        Cookie c = new Cookie("JSESSIONID",session.getId());
        c.setMaxAge(60*60);
        response.addCookie(c);

      2. 问: 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
        答: 不是同一个,但是要确保数据不丢失。tomcat可自动完成以下工作,但idea只能钝化。
        session的钝化: 在服务器正常关闭之前,将session对象系列化到硬盘上(work目录下)
        session的活化: 在服务器启动后,将session文件转化为内存中的session对象即可。

      3. 问: session什么时候被销毁?
        1. 服务器关闭时
        2. session对象调用invalidate() 。
        3. session默认失效时间 30分钟

      1    选择性配置修改,在tomcat的conf目录下的web.xml里可以配置    
      2    <session-config>
      3        <session-timeout>30</session-timeout>
      4    </session-config>
    5. session的特点

      1. session用于存储一次会话的多次请求的数据,存在服务器端
      2. session可以存储任意类型,任意大小的数据

    session与Cookie的区别:

    1. session存储数据在服务器端,Cookie在客户端
    2. session没有数据大小限制,Cookie有
    3. session数据安全,Cookie相对于不安全

    案例:注册页面验证码登录

    1. 案例需求:
      1. 访问带有验证码的登录页面login.jsp
      2. 用户输入用户名,密码以及验证码。
      • 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
      • 如果验证码输入有误,跳转登录页面,提示:验证码错误
      • 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您

    login.jsp

     1<%--
    2  Created by IntelliJ IDEA.
    3  User: Administrator
    4  Date: 2020/2/26 0026
    5  Time: 21:21
    6  To change this template use File | Settings | File Templates.
    7--%>

    8<%@ page contentType="text/html;charset=UTF-8" language="java" %>
    9<html>
    10<head>
    11    <title>Title</title>
    12</head>
    13<script>
    14    //当窗口加载完之后
    15    window.onload= function ({
    16        //获取验证码ID,当点击过后则更换图片
    17        document.getElementById("img").onclick = function ({
    18            //生成一个时间戳欺骗服务器,避免缓存加载同一张验证码
    19            var date = new Date().getTime();
    20            this.src="/test/checkCodeServlet?time="+date;
    21
    22        }
    23
    24    }
    25
    26
    </script>
    27
    28<%--div样式--%>
    29<style>
    30    div{
    31        color: red;
    32    }
    33
    </style>
    34<body>
    35
    36<form action="/test/loginServlet" method="post">
    37    <table>
    38        <tr>
    39            <td>用户名</td>
    40            <td><input type="text" name="username"></td>
    41        </tr>
    42        <tr>
    43            <td>密码</td>
    44            <td><input type="password" name="password"></td>
    45        </tr>
    46        <tr>
    47            <td>验证码</td>
    48            <td><input type="text" name="checkCode"></td>
    49        </tr>
    50        <tr>
    51            <td colspan="2"><img id="img" src="/test/checkCodeServlet"></td>
    52        </tr>
    53        <tr>
    54            <td colspan="2" ><input type="submit" value="登录"></td>
    55        </tr>
    56    </table>
    57
    58</form>
    59
    60<div> <%= request.getAttribute("cc_error") == null ? "" : request.getAttribute("cc_error") %></div>
    61<div><%= request.getAttribute("login_error")== null ? "" : request.getAttribute("login_error")%></div>
    62
    63</body>
    64</html>

    success.jsp

     1<%--
    2  Created by IntelliJ IDEA.
    3  User: Administrator
    4  Date: 2020/2/26 0026
    5  Time: 22:26
    6  To change this template use File | Settings | File Templates.
    7--%>

    8<%@ page contentType="text/html;charset=UTF-8" language="java" %>
    9<html>
    10<head>
    11    <title>Title</title>
    12</head>
    13<body>
    14<h1> <%= request.getSession().getAttribute("user")  %>欢迎你</h1>
    15</body>
    16</html>

    LoginServlet

     1package cn.testRep.web.servlet;
    2
    3import javax.servlet.ServletException;
    4import javax.servlet.annotation.WebServlet;
    5import javax.servlet.http.HttpServlet;
    6import javax.servlet.http.HttpServletRequest;
    7import javax.servlet.http.HttpServletResponse;
    8import javax.servlet.http.HttpSession;
    9import java.io.IOException;
    10
    11@WebServlet("/loginServlet")
    12public class LoginServlet extends HttpServlet {
    13    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    14        //设置request编码防止中文乱码
    15        request.setCharacterEncoding("utf-8");
    16        //获取参数
    17        String username = request.getParameter("username");
    18        String password = request.getParameter("password");
    19        String checkCode = request.getParameter("checkCode");
    20
    21        //判断验证码是否正确
    22        //先获取生成的验证码,需要强转
    23        String checkCode_upload = (String) request.getSession().getAttribute("checkCode");
    24        //生成session对象,记录会话过程数据
    25        HttpSession session = request.getSession();
    26        //获取后,删除session,防止内存占用
    27        session.removeAttribute("checkCode");
    28        System.out.println(checkCode_upload);
    29
    30        if (checkCode_upload != null && checkCode_upload.equalsIgnoreCase(checkCode)) {
    31            //判断用户名和密码,需要调用UserDao查询数据库,此处省略
    32            if (username.equals("admin") && password.equals("admin")) {
    33                //登录成功,存储用户信息
    34                session.setAttribute("user", username);
    35
    36                //重定向地址,需要获取虚拟目录
    37                response.sendRedirect(request.getContextPath() + "/success.jsp");
    38
    39            } else {
    40                //登录失败
    41                request.setAttribute("login_error""用户名或者密码错误");
    42                //转发到登录页面,不需要加虚拟目录
    43                request.getRequestDispatcher("/login.jsp").forward(request, response);
    44
    45            }
    46
    47        } else {
    48            //验证码不一致,则把提示信息存储到requset域中,用于服务器内部转发
    49            request.setAttribute("cc_error""验证码错误");
    50            //转发到登录页面,不需要加虚拟目录
    51            request.getRequestDispatcher("/login.jsp").forward(request, response);
    52        }
    53
    54    }
    55
    56    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    57        this.doPost(request, response);
    58    }
    59}

    CheckCodeServlet

     1package cn.testRep.web.servlet;
    2
    3import javax.imageio.ImageIO;
    4import javax.servlet.ServletException;
    5import javax.servlet.annotation.WebServlet;
    6import javax.servlet.http.HttpServlet;
    7import javax.servlet.http.HttpServletRequest;
    8import javax.servlet.http.HttpServletResponse;
    9import javax.servlet.http.HttpSession;
    10import java.awt.*;
    11import java.awt.image.BufferedImage;
    12import java.io.IOException;
    13import java.util.Random;
    14
    15@WebServlet("/checkCodeServlet")
    16public class CheckCodeServlet extends HttpServlet {
    17    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    18
    19        int width = 100;
    20        int height = 50;
    21        //1.创建一个对象,在内存中画图
    22        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
    23
    24        //2.美化图片
    25        //填充背景色
    26        Graphics graphics = image.getGraphics();//画笔对象
    27        graphics.setColor(new Color(200,200,169));//设置填充颜色
    28        graphics.fillRect(0,0,width,height);//填充
    29
    30        //画边框
    31        graphics.setColor(Color.darkGray);//设置边框颜色
    32        graphics.drawRect(0,0,width-1,height-1);//画边框
    33
    34        HttpSession session = request.getSession();
    35        //用于存储生成的验证码用于比对
    36        StringBuilder sb = new StringBuilder();
    37
    38        //写验证码
    39        String str = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
    40        for (int i = 0; i < 4 ; i++) {
    41            //生成随机角标
    42            Random ran = new Random();
    43            int index = ran.nextInt(str.length());
    44            char ch = str.charAt(index);
    45            sb.append(ch); //拼接字符串
    46            graphics.drawString(ch+"",width/5*(i+1),ran.nextInt(height-8)+5);
    47
    48        }
    49        //将验证码存进session
    50        String checkCode_session = sb.toString();
    51        session.setAttribute("checkCode",checkCode_session);
    52
    53        //画干扰线
    54        graphics.setColor(new Color(131,175,155));
    55        //随机生成干扰线坐标点
    56        graphics.drawLine(20,30,10,10);
    57
    58        //3.输出到页面展示
    59        ImageIO.write(image,"jpg",response.getOutputStream());
    60
    61
    62    }
    63
    64    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    65        this.doPost(request,response);
    66
    67    }
    68}
  • 相关阅读:
    mplayer编程模式控制命令
    设置开发板启动后自启动Qt
    Linux下制作logo并显示到开发板上 .
    启动开发板,提示:can't access tty,job control turned off
    BellmanFord贝尔曼福特算法
    阿拉伯数字转中文数字
    webService
    http请求全过程
    (转)MongoDB设置访问权限、设置用户
    YTC, YTM, YTW
  • 原文地址:https://www.cnblogs.com/huxiaobai/p/12369935.html
Copyright © 2020-2023  润新知