Web基础:Servlet规范(二)

本文介绍了Servlet间调用的两种主要方式:重定向与请求转发,并详细讲解了如何通过ServletContext、Cookie和HttpSession实现数据共享,以及它们各自的特点和适用场景。涵盖了多个Servlet协作的关键概念和技术细节。
摘要由CSDN通过智能技术生成

目录

8.多个Servlet之间的调用规则

8.1 概述

8.2 重定向解决方案

8.3 请求转发解决方案

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

9.1 概述

9.2 ServletContext接口

9.3 Cookie

9.4 HttpSession接口

9.5 HttpServletRequest接口


8.多个Servlet之间的调用规则

8.1 概述

   某些来自于浏览器发送的请求,往往需要服务端中多个Servlet协调处理,但是浏览器一次只能访问一个Servlet,导致用户需要手动通过浏览器发起多次请求才能得到服务,这样会增加用户获得服务的难度,导致用户放弃访问当前网站。

   为了提高用户的使用感受,需要做到无论本次请求涉及多少哥Servlet,用户只需要手动通知浏览器一次请求即可。

   多个Servlet之间的调用规则:

        ①重定向解决方案

        ②请求转发解决方案

8.2 重定向解决方案

   工作原理:用户第一次通过手动方式通知浏览器访问OneServlet,OneServlet工作完毕后,将TwoServlet的地址写入到响应头location属性中,导致Tomcat服务器将状态码302写入到状态行。在浏览器接收到响应包之后,会读取到302状态,此时浏览器自动根据响应头中location属性中的地址发起第二次请求,访问TwoServlet去完成请求中的剩余任务。

   实现命令

        response.sendRedirect("请求地址");

public class OneServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("OneServlet 负责洗韭菜");
        //重定向结局方案
        response.sendRedirect("/myWeb/two");//[地址格式:/网站名/资源文件名]
    }
}
public class TwoServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("TwoServlet 负责韭菜炒鸡蛋");
    }
}

   特征

        ①既可以把当前网站内部的资源文件地址发送给浏览器,也可以把其他网站资源文件地址发

          送给浏览器。

                如果是当前网站的,地址填写:/网站名/资源文件名

                如果是其他网站的,地址填写:http://IP地址:端口号/网站名/资源文件名

        ②浏览器至少发送两次请求,但是只有第一次请求是用户手动发送的,后续请求都是浏览器

          自动发送的。

        ③重定向解决方案中,通过地址栏通知浏览器发起下一次请求,因此通过重定向解决方案调

          用的资源文件接收的请求方式一定是Get

   缺点:重定向解决方案需要在浏览器与服务器之间进行多次往返,大量时间消耗在往返次数上,增加用户等待服务的时间。        

8.3 请求转发解决方案

   工作原理:用户第一次通过手动方式要求浏览器访问OneServlet,OneServlet工作完毕后,通过当前的请求对象代替浏览器向Tomcat发送请求,申请调用TwoServlet,Tomcat在接收到这个请求之后,自动调用TwoServlet来完成剩余任务。 

   实现命令:请求对象代替浏览器向Tomcat发送请求 

        //1.通过当前请求对象生成资源文件申请报告对象

        RequestDispatcher report = request.getRequestDispatcher("/资源文件名");//一定以"/"开头

        //2.将报告对象发送给Tomcat

        report.forward(当前请求对象,当前响应对象);

public class OneServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("OneServlet ");
        //请求转发方案:
        //1.通过当前请求对象生成资源文件申请报告对象
        RequestDispatcher report = request.getRequestDispatcher("/two");
        //2.将报告对象发送给Tomcat
        report.forward(request,response);
    }
}
public class TwoServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("TwoServlet ");
    }
}

   特征

        ①在请求转发过程中,浏览器只发送一次请求

        ②只能向Tomcat服务器申请调用当前网站下的资源文件。

                request.getRequestDispatcher("/资源文件名");//不要写网站名

        ③在请求转发过程中,浏览器只发送了一个Http请求协议包。参与本次请求的所有Servlet共

          享同一个请求协议包,因此这些Servlet接收的请求方式与浏览器发送的请求方式保持一致。

   优点:

        ①无论本次请求涉及到多少个Servlet,用户只需要手动通过浏览器发送一次请求

        ②Servlet之间的调用发生在服务端计算机上,节省服务端与浏览器之间往返次数,增加处理

          服务速度。

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

9.1 概述

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

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

        ①ServletContext接口

        ②Cookie

        ③HttpSession接口

        ④HttpServletRequest接口

9.2 ServletContext接口

   来自于Servlet规范中的一个接口。在Tomcat中存在于servlet-api.jar中,在Tomcat中负责提供这个接口实现类

   如果两个Servlet来自于同一个网站,彼此之间通过网站的ServletContext实例对象来实现数据共享。

   开发人员习惯将ServletContext对象称为全局作用域对象

   工作原理每一个网站都存在一个全局作用域对象。这个全局作用域对象相当于一个Map,里面的数据以键值对的形式存储。在这个网站中OneServlet可以将一个数据存入到全局作用域对象中,当前网站中其他Servlet此时都可以从全局作用域对象得到这个数据进行使用。

   全局作用域对象的生命周期:在Http服务器启动过程中,自动为当前网站在内存中创建一个全局作用域对象;在Http服务器运行期间时,一个网站只有一个全局作用域对象;在Http服务器运行期间,全局作用域对象一直处于存活状态;在Http服务器准备关闭时,负责将当前网站中全局作用域对象进行销毁处理。总之,全局作用域对象生命周期贯穿网站整个的运行期间

   命令实现: 【同一个网站】OneServlet将数据共享给TwoServlet

        OneServlet{

                 public void doGet(HttpServletRequest request,HttpServletResponse response){

                         //1.通过【请求对象】向Tomcat索要当前网站中【全局作用域对象】

                        ServletContext application = request.getServletContext();

                         //2.将数据添加到全局作用域对象作为【共享数据】

                        application.setAttribute("key1",数据)

                }

        }

        TwoServlet{

                public void doGet(HttpServletRequest request,HttpServletResponse response){

                        //1.通过【请求对象】向Tomcat索要当前网站中【全局作用域对象】

                        ServletContext application = request.getServletContext();

                        //2.从全局作用域对象得到指定关键字对应数据

                        Object 数据 =  application.getAttribute("key1");

                }

        }

public class OneServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.通过请求对象向Tomcat索要当前全局作用域对象
        ServletContext application = request.getServletContext();
        //2.将数据添加到全局作用域对象,作为共享数据
        application.setAttribute("key1",100);
    }
}
public class TwoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.通过请求对象向Tomcat索要当前网站全局作用域对象
        ServletContext application = request.getServletContext();
        //2.从全局作用域对象得到指定关键字对应的值
        Integer money = (Integer) application.getAttribute("key1");//写成Integer防止空指针异常,int类型不能赋值null
    }
}

9.3 Cookie

   Cookie来自于Servlet规范中的一个工具类,存在于Tomcat提供的servlet-api.jar包中

   如果两个Servlet来自于同一个网站,并且为同一个浏览器/用户提供服务,此时借助于Cookie对象进行数据共享。

   Cookie存放当前用户的私有数据,在共享数据过程中提高服务质量。在现实生活场景中,Cookie相当于用户在服务端得到会员卡。

   工作原理:用户通过浏览器第一次向MyWeb网站发送请求申请OneServlet,OneServlet在运行期间创建一个Cookie存储与当前用户相关数据;OneServlet工作完毕后,将Cookie写入到响应头交还给浏览器。浏览器收到响应包之后,将Cookie存储在浏览器的缓存中,一段时间之后,用户通过同一个浏览器再次向MyWeb网站发送请求申请TwoServlet时,浏览器需要无条件地将MyWeb网站之间推送过来的Cookie写入到请求头发送过去,此时TwoServlet在运行时,就可以通过读取请求头中的Cookie信息,得到OneServlet提供的共享数据。

   实现命令:  同一个网站 OneServlet 与  TwoServlet 借助于Cookie实现数据共享

        OneServlet{

                public void doGet(HttpServletRequest request,HttpServletResponse response){

                        //1.创建一个cookie对象,保存共享数据(当前用户数据)

                        Cookie card = new Cookie("key1","abc");

                        Cookie card1= new Cookie("key2","efg");

                        ****cookie相当于一个map

                        ****一个cookie中只能存放一个键值对

                        ****这个键值对的key与value只能是String

                        ****键值对中key不能是中文

                        //2.【发卡】将cookie写入到响应头,交给浏览器

                        response.addCookie(card);

                        response.addCookie(card1)

                }

        }

         浏览器/用户<---------响应包 【200】【cookie: key1=abc; key2=eft】【处理结果】

        浏览器向myWeb网站发送请求访问TwoServlet---->请求包 【url:/myWeb/two method:get】【请求参数:xxxx  Cookie   key1=abc;key2=efg】【】【】

        TwoServlet{

                public void doGet(HttpServletRequest request,HttpServletResponse resp){

                         //1.调用请求对象从请求头得到浏览器返回的Cookie

                        Cookie[]  cookieArray = request.getCookies();

                        //2.循环遍历数据得到每一个cookie的key 与 value

                        for(Cookie card:cookieArray){

                                String key = card.getName(); 读取key  "key1"

                                Strign value = card.getValue();读取value "abc"

                                //提供较好的服务。。。。。。。。

                        }

                }

        }

   一个代码实例:通过会员卡点餐。

public class OneServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userName,money;
        //1.调用请求对象读取请求头参数信息
        userName = request.getParameter("userName");
        money = request.getParameter("money");
        //2.开卡,设置cookie
        Cookie card1 = new Cookie("userName",userName);
        Cookie card2 = new Cookie("money",money);
        //3.指定card2在客户端硬盘上存活一分钟
        card2.setMaxAge(60);
        //4.发卡,将cookie写入到响应头交给浏览器
        response.addCookie(card1);
        response.addCookie(card2);
        //5.通知Tomcat将【点餐页面】内容写入到响应体交给浏览器(重定向)
        response.sendRedirect("/myWeb/index_2.html");
    }
}
public class TwoServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int jiaozi_money = 30;
        int miaotiao_money = 20;
        int gaifan_money = 15;
        String food,userName = null;
        int money = 0,xiaofei = 0,balance = 0;
        Cookie[] cookieArray = null;
        PrintWriter out = response.getWriter();
        response.setContentType("text/html;charset=utf-8");
        Cookie newCard = null;
        //1.读取请求头参数信息,得到用户点餐食物类型
        food = request.getParameter("food");
        //2.读取请求体中cookie
        cookieArray = request.getCookies();
        //3.刷卡消费
        for(Cookie card:cookieArray){
            String key = card.getName();
            String value = card.getValue();
            if("userName".equals(key)){
                userName = value;
            }else if("money".equals(key)){
                money = Integer.valueOf(value);//将得到的字符串转为int
                if("饺子".equals(food)){
                    if(jiaozi_money > money) {
                        out.print("用户" + userName + "余额不足,请充值");
                    }else{
                        newCard = new Cookie("money",(money - jiaozi_money)+"");//只能存储String类型
                        xiaofei = jiaozi_money;
                        balance = money - jiaozi_money;
                    }
                }else if("面条".equals(food)){
                    if(miaotiao_money > money){
                        out.print("用户" + userName + "余额不足,请充值");
                    }else{
                        newCard = new Cookie("money",(money - miaotiao_money)+"");
                        xiaofei = miaotiao_money;
                        balance = money - miaotiao_money;
                    }
                }else if("盖饭".equals(food)){
                    if(gaifan_money > money){
                        out.print("用户" + userName + "余额不足,请充值");
                    }else{
                        newCard = new Cookie("money",(money - gaifan_money)+"");
                        xiaofei = gaifan_money;
                        balance = money - gaifan_money;
                    }
                }
            }
        }
        //4.将用户会员卡返还给用户
        response.addCookie(newCard);//注意之前的余额变化了,所以需要新建一个cookie返还给浏览器
        //对之前的money那个cookie产生了覆盖
        //5.将消费记录
        out.print("用户" + userName + "本次消费" + xiaofei + "余额:" + balance);
    }
}

   Cookie的销毁时机

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

          销毁掉。

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

          要指定Cookie在硬盘上的存活时间。在存活时间范围内,关闭浏览器、关闭客户端计算机、

          关闭服务器,都不会导致Cookie被销毁。cookie.setMaxAge(存活时间,单位是s);

9.4 HttpSession接口

   HttpSession接口来自于Servlet规范下的一个接口,存在于Tomcat中servlet-api.jar,其实现类由Http服务器提供。Tomcat提供实现类存在于servlet-api.jar。

   如果两个Servlet来自于同一个网站,并且为同一个浏览器/用户提供服务,此时借助于HttpSession对象进行数据共享。

   开发人员习惯将HttpSession接口修饰对象称为会话作用域对象

   (重要)HttpSession和Cookie的区别

        ①存储位置不同。Cookie存放在客户端计算机(浏览器内存/硬盘);HttpSession存放在服务端

          计算机内存。

        ②数据类型不同。Cookie对象存储共享数据类型只能是String;HttpSession对象可以存储任

          意类型的共享数据Object。

        ③存储数据数量不同。一个Cookie对象只能存储一个共享数据;一个HttpSession对象使用

          map集合存储共享数据,所以可以存储任意数量共享数据。

        ④参照物不同。Cookie相当于客户从服务端得到的会员卡;HttpSession相当于客户在服务端

          的私人保险柜。

   命令实现:   同一个网站(myWeb)下OneServlet将数据传递给TwoServlet

        OneServlet{

                public void doGet(HttpServletRequest request,HttpServletResponse response){

                        //1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜

                        HttpSession   session = request.getSession();

                        //2.将数据添加到用户私人储物柜

                        session.setAttribute("key1",共享数据)

                }

        }

        浏览器访问/myWeb中TwoServlet

        TwoServlet{

                public void doGet(HttpServletRequest request,HttpServletResponse response){

                        //1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜

                        HttpSession   session = request.getSession();

                        //2.从会话作用域对象得到OneServlet提供的共享数据

                        Object 共享数据 = session.getAttribute("key1");

                }

        }

   一个代码实例:将商品加入购物车。

public class OneServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String goodsName;
        //1.调用请求对象,读取请求头参数,得到用户选择商品名
        goodsName = request.getParameter("goodsName");
        //2.调用请求对象,向Tomcat索要当前用户在服务端的私人储物柜
        HttpSession session = request.getSession();
        //3.将用户选购商品添加到当前用户私人存储柜
        Integer goodsNum = (Integer)session.getAttribute(goodsName);//查看当前该商品有多少件
        if(goodsNum == null){
            session.setAttribute(goodsName,1);
        }else {
            session.setAttribute(goodsName,goodsNum+1);
        }
    }
}
public class TwoServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //调用请求对象向Tomcat索要当前用户在服务端私人储物柜
        HttpSession session = request.getSession();
        //2.将session中所有的key读取出来,存放一个枚举类型
        Enumeration goodsNames = session.getAttributeNames();//session中存了多个数据,一次性全部取出
        while (goodsNames.hasMoreElements()){
            String goodsName = (String)goodsNames.nextElement();
            int goodsNum = (int)session.getAttribute(goodsName);//此处不会出现空指针异常,可用int
            System.out.println("商品名称:" + goodsName + "商品数量:" + goodsNum);
        }

    }
}

   在不同的浏览器打开网站时,Http服务器是如何识别这是哪个用户的,即Http服务器是如何将用户与HttpSession关联起来的?

        通过Cookie来实现。JSESSIONID。并且这个cookie只能存储在浏览器的缓存中,不能自己

      手动设置。

   getSession()与getSession(false)的区别

        ①getSession():如果当前用户在服务端已经拥有自己的私人储物柜,要求Tomcat将这个私人

          储物柜进行返回;如果当前用户在服务端尚未拥有自己的私人储物柜,要求Tomcat为当前用

          户创建一个全新的私人储物柜。

        ②getSession(false):如果当前用户在服务端已经拥有自己的私人储物柜,要求Tomcat将这

          个私人储物柜进行返回;如果当前用户在服务端尚未拥有自己的私人储物柜,此时Tomcat

          回null

   HttpSession的销毁时机

        ①用户与HttpSession关联时使用的Cookie只能存放在浏览器缓存中.

        ②在浏览器关闭时,意味着用户与他的HttpSession关系被切断

        ③由于Tomcat无法检测浏览器何时关闭,因此在浏览器关闭时并不会导致Tomcat将浏览器关

          联的HttpSession进行销毁

         ④为了解决这个问题,Tomcat为每一个HttpSession对象设置【空闲时间】,这个空闲时间

          认30分钟,如果当前HttpSession对象空闲时间达到30分钟,此时Tomcat认为用户已经放弃

          了自己的HttpSession,此时Tomcat就会销毁掉这个HttpSession

   HttpSession空闲时间手动设置:在当前网站/web/WEB-INF/web.xml

9.5 HttpServletRequest接口

   在同一个网站中,如果两个Servlet之间通过请求转发方式进行调用,彼此之间共享同一个请求协议包,而一个请求协议包只对应一个请求对象,因此Servlet之间共享同一个请求对象,此时可以利用这个请求对象在两个Servlet之间实现数据共享。

   在请求对象实现Servlet之间数据共享功能时,开发人员将请求对象称为请求作用域对象

   命令实现: OneServlet通过请求转发申请调用TwoServlet时,需要给TwoServlet提供共享数据

        OneServlet{

                public void doGet(HttpServletRequest request,HttpServletResponse response){

                        //1.将数据添加到【请求作用域对象】中attribute属性

                        request.setAttribute("key1",数据); //数据类型可以任意类型Object

                        //2.向Tomcat申请调用TwoServlet

                        request.getRequestDispatcher("/two").forward(req,response)

                }

        }

        TwoServlet{

                public void doGet(HttpServletRequest request,HttpServletResponse response){

                        //从当前请求对象得到OneServlet写入到共享数据

                        Object 数据 = request.getAttribute("key1");

                }

        }

public class OneServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.将数据添加到请求作用域对象,作为共享数据
        request.setAttribute("key1","Hello World");
        //2.代替浏览器,向Tomcat索要TwoServlet来完成剩余任务
        request.getRequestDispatcher("/two").forward(request,response);
    }
}
public class TwoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //从同一个请求作用域对象得到OneServlet写入到共享数据
        String value = (String)request.getAttribute("key1");
        System.out.println(value);
    }
}

PS:根据动力节点课程整理,如有侵权,联系删除。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值