JavaWeb-03-Servlet-10-多个Servlet之间的数据共享

1.多个Servlet之间的数据共享实现方案

数据共享:OneServlet工作完毕后,将产生的数据交给TwoServlet来使用。

在Servlet规范中提供四种数据共享方案:

  1. ServletContext接口
  2. Cookie类
  3. HttpSession接口
  4. HttpServletRequest接口

2.ServletContext接口

2.1ServletContext接口介绍

  1. 是来自于Servlet规范中的一个接口。
  • 存在于Tomcat中的servlet-api.jar。
  • 由Tomcat负责提供这个接口的实现类。
  1. 如果两个Servlet来自于同一个网站,那么彼此之间可以通过网站的ServletContext实例对象来实现数据共享。
  2. 开发人员习惯将其ServletContext对象称为【全局作用域对象】。

2.2原理

Java 屏幕共享功能 javaweb共享数据_作用域

  1. 每一个网站中都存在一个全局作用域对象。
  2. 这个全局作用域对象相当于是一个【Map】,以键值对形式存储数据。
  3. 在这个网站中,OneServlet可以将一个数据存入到全局作用域对象。
  4. 在存入数据后,当前网站中的其他Servlet都可以从全局作用域对象获取这个数据。

2.3全局作用域对象的生命周期

  1. 创建:在服务器启动过程中,服务器会自动为当前网站创建一个全局作用域对象。
  2. 数量:在服务器运行期间,只有一个全局作用域对象【一个网站只有一个】
  3. 运行:在服务器运行期间,全局作用域对象一直处于存活状态。
  4. 销毁:在服务器准备关闭时,服务器会自动将当前网站中的全局作用域对象销毁。

注意:全局作用域对象的生命周期贯穿网站整个运行期间

2.4命令实现

在同一个网站中,将OneServlet中的数据共享给TwoServlet。

OneServlet:

public class OneServlet extends HttpServlet {
    @Overrite
    protected void doGet(HttpServletRequest request,HttpResponse response) throws IOException {
        //1.通过【请求对象】向Tomcat服务器索要【全局作用域对象】
        ServletContext application = request.getServletContext();//全局作用域对象名默认都写作application
        //2.将数据添加到全局作用域对象中作为【共享数据】
        application.setAttribute("key1",数据【任意类型】);
    }
}

TwoServlet:

public class TwoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.通过【请求对象】向服务器索要当前网站中的【全局作用域】对象
        ServletContext application = request.getServletContext();
        //2.通过指定关键字从【全局作用域对象】中得到对应数据
        Object 存储数据的变量 = application.getAttribute("关键字key");
    }
}

2.5演示

流程:

  1. 在web目录下创建一个html页面,命名为login.html。
  1. 通过表单将用户名和用户密码发送给服务器。
  1. 新建一个网站MyWeb,定义两个Servlet接口实现类:
  1. OneServlet
  2. TwoServlet
  1. OneServlet负责从请求协议包中获取用户名和用户密码,然后把数据共享给TwoServlet
2.5.1html页面

Java 屏幕共享功能 javaweb共享数据_servlet_02

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <style type="text/css">
        * {
            font-size: 20px;
        }
    </style>
</head>
<body>
    <form action="/MyWeb/one">
        <table>
            <tr>
                <td>用户名:</td>
                <td><input type="text" name="userName"></td>
            </tr>
            <tr>
                <td>密    码:</td>
                <td><input type="password" name="passWord"></td>
            </tr>
            <tr>
                <td><input type="submit" value="登录"></td>
                <td><input type="reset" value="重置"></td>
            </tr>
        </table>

    </form>
</body>
</html>
2.5.2OneServlet
package com.tsccg.controller;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Author: TSCCG
 * @Date: 2021/08/17 16:29
 */
public class OneServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.通过【请求对象】获取请求头中的【请求参数】
        String userName = request.getParameter("userName");
        String passWord = request.getParameter("passWord");
        //2.通过【请求对象】向服务器索要【全局作用域对象】
        ServletContext application = request.getServletContext();
        //3.将【请求参数】添加到【全局作用域对象】中
        application.setAttribute("key1",userName);
        application.setAttribute("key2",passWord);
        //4.处理完当前请求后,需要访问TwoServlet
        //4.1通过当前【请求对象】生成资源文件申请报告对象,将TwoServlet地址传进去
        RequestDispatcher report = request.getRequestDispatcher("/two");
        //4.2将报告对象发送给服务器
        report.forward(request,response);
        
    }
}
2.5.3TwoServlet
package com.tsccg.controller;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Author: TSCCG
 * @Date: 2021/08/17 16:52
 */
public class TwoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.通过【请求对象】获取【全局作用域对象】
        ServletContext application = request.getServletContext();
        //2.通过指定关键字【key】获取【全局作用域对象】中的值
        String userName = (String)application.getAttribute("key1");
        String passWord = (String)application.getAttribute("key2");
        //3.将获取到的数据打印在控制台
        System.out.println("userName=" + userName);
        System.out.println("passWord=" + passWord);
        //4.通过响应对象向服务器索要输出流
        PrintWriter out = response.getWriter();
        //5.将一个字符串返回给浏览器作为结束标识
        out.print("Hello");
    }
}
2.5.4开始演示

Java 屏幕共享功能 javaweb共享数据_servlet_03

3.Cookie

3.1Cookie介绍

  1. Cookie来自于Servlet规范中的一个工具类,存放在Tomcat提供的servlet-api.jar包中。
  2. 如果两个Servlet来自于同一个网站,并且为同一个浏览器/用户提供服务,那么此时,可以借助Cookie对象进行数据共享。
  3. Cookie存放着当前用户的私人数据,在共享数据过程中来提高我们的服务质量。
  4. 在现实生活中,Cookie相当于用户在服务端得到了一张【会员卡】。

Java 屏幕共享功能 javaweb共享数据_java_04

3.2Cookie原理

  1. 用户通过浏览器第一次向MyWeb网站发送请求,申请OneServlet。
  2. OneServlet在运行期间,创建一个Cookie,存储了当前用户的相关数据。
  3. 在OneServlet运行结束时,会将Cookie写入请求头中,发送给浏览器。
  4. 浏览器在接收到Cookie后,会将Cookie放进浏览器的缓存中。
  5. 一段时间后,当用户通过【同一浏览器】,向【MyWeb】网站再次发送请求,申请TwoServlet时,浏览器将无条件地将第一次【MyWeb】网站发送过来的Cookie从浏览器缓存中取出,写入到请求头中,发送给服务器。
  6. 此时TwoServlet运行时,就能通过请求头中Cookie的信息,读取到OneServlet提供的共享数据。

3.3命令实现

在同一个网站中,OneServlet与TwoServlet借助Cookie实现数据共享。

OneServlet

public class OneServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.创建Cookie对象,保存共享数据(当前用户数据)
        //Cookie对象相当于一个Map,以键值对方式存放数据
        //键值对中的key和value都只能是String类型,且key不能为中文
        //一个Cookie只能存放一个键值对
        Cookie card1 = new Cookie("key1","abc");
        Cookie card2 = new Cookie("key2","def");
        //2.将Cookie对象写入响应头中,发送给浏览器
        response.addCookie(card1);
        response.addCookie(card2);
    }
}

浏览器/用户接收到响应包:

状态栏

200

响应头

Cookie:key1=“abc”;key2=“def”

空白行

响应体

处理结果

浏览器再次向同一网站发送请求访问TwoServlet,发送的请求包:

请求行

url:/MyWeb/two; method:get;

请求头

请求参数:***; Cookie: key1=“abc”;key2=“def”;

空白行

请求体

TwoServlet:

public class TwoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.调用请求对象从请求头中获取浏览器返回的Cookie
        Cookie[] cookieArray = request.getCookies();
        //2.循环遍历数据得到每一个Cookie的key和value
        for(Cookie card : cookieArray) {
            String key = card.getName();//读取key值--->"key1"
            String value = card.getValue();//读取value值--->"abc"
        }
    }
}

3.4Cookie应用实例_订餐会员卡

3.4.1流程图

Java 屏幕共享功能 javaweb共享数据_Java 屏幕共享功能_05

3.4.2搭建申请页面

Java 屏幕共享功能 javaweb共享数据_servlet_06

在web目录下新建index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>申请会员卡</title>
    <style type="text/css">
        * {
            font-size: 20px;
        }
    </style>
</head>
<body>
    <center>
        <h2 style="color: red">申请会员卡</h2>
        <form action="/MyWeb/one" method="get">
            <table>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name="userName" /></td>
                </tr>
                <tr>
                    <td>预存金额:</td>
                    <td><input type="text" name="money" /></td>
                </tr>
                <tr>
                    <td><input type="submit" value="提交" /></td>
                    <td><input type="reset" value="重置" /></td>
                </tr>
            </table>
        </form>
    </center>
</body>
</html>
3.4.3实现开卡(OneServlet)
package com.tsccg.controller;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Author: TSCCG
 * @Date: 2021/08/18 13:30
 */
public class OneServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.通过请求对象获取请求头中的请求参数【userName;money】
        String userName = request.getParameter("userName");
        String money = request.getParameter("money");
        //2.创建两个Cookie对象,把两个参数传进去。【开卡】
        Cookie card1 = new Cookie("userName",userName);
        Cookie card2 = new Cookie("money",money);
        //3.通过响应对象将两个Cookie对象写入响应头中,发送给浏览器【发卡】
        response.addCookie(card1);
        response.addCookie(card2);
        //4.将点餐页面地址写入响应头的location中
        response.sendRedirect("/MyWeb/order.html");//【重定向】
//        request.getRequestDispatcher("/order.html").forward(request,response);//【请求转发】
    }

}
3.4.4搭建点餐页面

Java 屏幕共享功能 javaweb共享数据_服务器_07

在web目录下新建order.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>点餐页面</title>
    <style type="text/css">
        * {
            font-size: 20px;
        }
        h1 {
            color: red;
            font-size: 30px;
        }

    </style>
</head>
<body>
    <center>
        <h1>点餐</h1>
        <form action="/MyWeb/two" method="get">
            <table border="2" cellspacing="0" cellpadding="0" width="300px" height="150px">
                <tr>
                    <td>
                        <label>捞面:   
                            <input type="radio" name="food" value="noodle"/>
                        </label>
                    </td>
                    <td>10元</td>
                </tr>
                <tr>
                    <td>
                        <label>盖浇饭:
                        <input type="radio" name="food" value="rice"/>
                        </label>
                    </td>
                    <td>15元</td>
                </tr>
                <tr>
                    <td>
                        <label>饺子:   
                            <input type="radio" name="food" value="dumplings"/>
                        </label>
                    </td>
                    <td>20元</td>
                </tr>
                <tr>
                    <td colspan="2"><input type="submit" value="下单"/></td>
                </tr>
            </table>

        </form>
    </center>
</body>
</html>
3.4.5实现消费(TwoServlet)
package com.tsccg.controller;

import javax.naming.Name;
import javax.servlet.ServletException;
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;

/**
 * @Author: TSCCG
 * @Date: 2021/08/18 13:31
 */
public class TwoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.定义变量
        final int noodlePrice = 10;//捞面
        final int ricePrice = 15;//盖浇饭
        final int dumplingsPrice = 20;//饺子
        String food = null;//食物类型
        Cookie[] cookies = null;//Cookie数组
        String userName = null;//用户名
        int money = 0;//账户余额
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();//获取输出流
        Cookie newCard = null;
        int cost = 0;//总共消费


        //2.通过请求对象获取请求头中的请求参数,取得食物类型
        food = request.getParameter("food");
        //3.通过请求对象获取请求头中所有的Cookie,返回一个Cookie数组
        cookies = request.getCookies();
        //4.遍历Cookie数组
        for (Cookie cookie : cookies) {
            String key = cookie.getName();
            String value = cookie.getValue();
            if("userName".equals(key)) {
                userName = value;//获取用户名
            } else if("money".equals(key)) {
                money = Integer.parseInt(value);//获取余额
                if ("noodle".equals(food)) {
                    if(money < noodlePrice) {
                        out.print("<center><font style='color:red'>账户余额不足!</font><br></center>");
                    } else {
                        //消费
                        cost = noodlePrice;
                        money -= cost;
                    }
                } else if ("rice".equals(food)) {
                    if(money < ricePrice) {
                        out.print("<center><font style='color:red'>账户余额不足!</font><br></center>");
                    } else {
                        //消费
                        cost = ricePrice;
                        money -= cost;
                    }
                } else if ("dumplings".equals(food)) {
                    if(money < dumplingsPrice) {
                        out.print("<center><font style='color:red'>账户余额不足!</font><br></center>");
                    } else {
                        //消费
                        cost = dumplingsPrice;
                        money -= cost;
                    }
                }
                newCard = new Cookie("money",(money + ""));
            }
        }
        //5.将会员卡归还给客户
        response.addCookie(newCard);
        out.print("<center><font style='color:green;font-size:20px'>用户:" + userName + "</font><br>");
        out.print("<font style='color:green;font-size:20px'>本次消费:" + cost + "元</font><br>");
        out.print("<font style='color:green;font-size:20px'>剩余金额:" + money + "元</font><br>");
        out.print("<input type=\"button\" value=\"再来一单\" οnclick=\"window.open('/MyWeb/order.html','_self')\"></center>");

    }
}
3.4.6开始演示

Java 屏幕共享功能 javaweb共享数据_servlet_08

3.5Cookie生命周期

在默认情况下,Cookie对象存放在浏览器内的缓存中。因此只要关闭浏览器,Cookie对象就会被销毁。

Java 屏幕共享功能 javaweb共享数据_Java 屏幕共享功能_09

在手动设置的情况下,可以要求浏览器将接收的Cookie存放到客户端计算机硬盘上,同时需要指定Cookie在硬盘上的存活时间。

在存活时间范围内,无论是关闭浏览器还是关闭客户端计算机,或者关闭服务器,都不会导致Cookie被销毁。

存活时间到达时,Cookie会被自动从硬盘上删除。

命令:

Cookie card = new Cookie("userName","Tom");
card.setMaxAge(60);//card在硬盘上存活1分钟

设置money在客户端硬盘中存活1分钟:

public class OneServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.通过请求对象获取请求头中的请求参数【userName;money】
        String userName = request.getParameter("userName");
        String money = request.getParameter("money");
        //2.创建两个Cookie对象,把两个参数传进去。【开卡】
        Cookie card1 = new Cookie("userName",userName);
        Cookie card2 = new Cookie("money",money);
        //3.设置card2在客户端硬盘上存活1分钟
        card2.setMaxAge(60);
        //4.通过响应对象将两个Cookie对象写入响应头中,发送给浏览器【发卡】
        response.addCookie(card1);
        response.addCookie(card2);
        //5.将点餐页面地址写入响应头的location中
        response.sendRedirect("/MyWeb/order.html");//【重定向
    }

}

Java 屏幕共享功能 javaweb共享数据_java_10

一分钟后:

Java 屏幕共享功能 javaweb共享数据_Java 屏幕共享功能_11