zoukankan      html  css  js  c++  java
  • 会话技术中的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}
  • 相关阅读:
    Python动态展示遗传算法求解TSP旅行商问题
    MOEAD算法中均匀权向量的实现---Python
    HDU 5294 多校第一场1007题 最短路+最小割
    POJ 3261 Milk Patterns sa+二分
    HDU 4292 FOOD 2012 ACM/ICPC Asia Regional Chengdu Online
    CodeForces 201A Clear Symmetry
    POJ 1679 The Unique MST 确定MST是否唯一
    POJ 3268 Silver Cow Party 最短路 基础题
    POJ 2139 SIx Degrees of Cowvin Bacon 最短路 水題
    POJ2229 Sumsets 基礎DP
  • 原文地址:https://www.cnblogs.com/huxiaobai/p/12369935.html
Copyright © 2011-2022 走看看