Servlet学习1:Http状态码、多个Servlet之间调用规则、多个Servlet之间数据共享实现方案

Http状态码

1.介绍:
1)由三位数字组成的一个符号。

2)Http服务器在推送响应包之前,根据本次请求处理情况将Http状态码写入到响应包中【状态行】上

3)如果Http服务器针对本次请求,返回了对应的资源文件。通过Http状态码通知浏览器应该如何处理这个结果。

如果Http服务器针对本次请求,无法返回对应的资源文件通过Http状态码向浏览器解释不能提供服务的原因

2.分类:
1)组成 100---599;分为5个大类

2)1XX :
最有特征 100; 通知浏览器本次返回的资源文件并不是一个独立的资源文件,需要浏览器在接收响应包之后,继续向Http服务器所要依赖的其他资源文件

  1. 2XX:
    最有特征200,通知浏览器本次返回的资源文件是一个完整独立资源文件,浏览器在接收到之后不需要所要其他关联文件

4)3xx:
最有特征302,通知浏览器本次返回的不是一个资源文件内容而是一个资源文件地址,需要浏览器根据这个地址自动发起请求来索要这个资源文件

response.sendRedirect("资源文件地址")写入到响应头中的location中,而这个行为导致Tomcat将302状态码写入到状态行

5)4XX:

404: 通知浏览器,由于在服务端没有定位到被访问的资源文件因此无法提供帮助

405:通知浏览器,在服务端已经定位到被访问的资源文(Servlet)但是这个Servlet对于浏览器采用的请求方式不能处理

6)5xx:

500 : 通知浏览器,在服务端已经定位到被访问的资源文件(Servlet)这个Servlet可以接收浏览器采用请求方式,但是Servlet在处理请求期间,由于Java异常导致处理失败

多个Servlet之间调用规则:

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

提高用户使用感受规则:

无论本次请求涉及到多少个Servlet,用户只需要【手动】通知浏览器发起一次请求即可

多个Servlet之间调用规则:
1)重定向解决方案
2)请求转发解决方案

重定向解决方案

工作原理:
用户第一次通过【手动方式】通知浏览器访问OneServlet。OneServlet工作完毕后,将TwoServlet地址写入到响应头location属性中,导致Tomcat将302状态码写入到状态行。

在浏览器接收到响应包之后,会读取到302状态。此时浏览器自动根据响应头中location属性地址发起第二次请求,访问TwoServlet去完成请求中剩余任务

重定向解决方案原理图.png

实现命令:
response.sendRedirect("请求地址")
将地址写入到响应包中响应头中location属性

特征:

1)请求地址:
既可以把当前网站内部的资源文件地址发送给浏览器 (/网站名/资源文件名)也可以把其他网站资源文件地址发送给浏览器(http://ip地址:端口号/网站名/资源文件名)

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

  1. 请求方式:
    重定向解决方案中,通过地址栏通知浏览器发起下一次请求,因此通过重定向解决方案调用的资源文件接收的请求方式一定是【GET】

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

请求转发解决方案:

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

请求转发解决方案.png

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

//1.通过当前请求对象生成资源文件申请报告对象
RequestDispatcher report = request.getRequestDispatcher("/资源文件名");一定要以"/"为开头
//2.将报告对象发送给Tomcat
report.forward(当前请求对象,当前响应对象)

优点:

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

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

特征:

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

2)请求地址
只能向Tomcat服务器申请调用当前网站下资源文件地址
request.getRequestDispathcer("/资源文件名") ****不要写网站名****

3)请求方式
在请求转发过程中,浏览器只发送一个了个Http请求协议包。
参与本次请求的所有Servlet共享同一个请求协议包,因此这些Servlet接收的请求方式与浏览器发送的请求方式保持一致

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

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

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

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

ServletContext接口

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

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

3)开发人员习惯于将ServletContext对象称为【全局作用域对象】

2.工作原理:

每一个网站都存在一个全局作用域对象。
这个全局作用域对象【相当于】一个Map。
在这个网站中OneServlet可以将一个数据存入到全局作用域对象,当前网站中其他Servlet此时都可以从全局作用域对象得到这个数据进行使用

全局作用域流程图.png

3.全局作用域对象生命周期:

1)在Http服务器启动过程中,自动为当前网站在内存中创建一个全局作用域对象
2)在Http服务器运行期间时,一个网站只有一个全局作用域对象

3)在Http服务器运行期间,全局作用域对象一直处于存活状态

4)在Http服务器准备关闭时,负责将当前网站中全局作用域对象进行销毁处理

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

4.命令实现: 【同一个网站】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");
                   
    }
                 
 }

Cookie

1.介绍:

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

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

  1. Cookie存放当前用户的私人数据,在共享数据过程中提高服务质量

  2. 在现实生活场景中,Cookie相当于用户在服务端得到【会员卡】

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

Cookie工作原理图.png

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

OneServlet{
    public void doGet(HttpServletRequest request,HttpServletResponse resp){
                
        //1.创建一个cookie对象,保存共享数据(当前用户数据)
        Cookie card = new Cookie("key1","abc");
         Cookie card1= new Cookie("key2","efg");
         ****cookie相当于一个map
        ****一个cookie中只能存放一个键值对
         ****这个键值对的key与value只能是String
        ****键值对中key不能是中文
        //2.【发卡】将cookie写入到响应头,交给浏览器
         resp.addCookie(card);
        resp.addCookie(card1)
    }
            
}

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

浏览器向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"
            String value = card.getValue();读取value "abc"
            提供较好的服务。。。。。。。。
             }
     }
 }
             

4.Cookie销毁时机:

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

2.在手动设置情况下,可以要求浏览器将接收的Cookie存放在客户端计算机上硬盘上,同时需要指定Cookie在硬盘上存活时间。在存活时间范围内,关闭浏览器,关闭客户端计算机,关闭服务器,都不会导致Cookie被销毁。在存活时间到达时,Cookie自动从硬盘上被删除

cookie.setMaxAge(60); //cookie在硬盘上存活1分钟

Cookie模拟划卡消费.png

index.html




    
    Title


        
新会员申请开卡
用户名
预存金额

index_2.html




    
    Title


           
点餐页面
食物类型:饺子(30元) 面条(20元) 盖饭(15元)

web.xml



    
        OneServlet
        com.bjpowernode.controller.OneServlet
    
    
        TwoServlet
        com.bjpowernode.controller.TwoServlet
    
    
        TwoServlet
        /two
    
    
        OneServlet
        /one
    

OneServlet.java

package com.bjpowernode.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;

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 card1 = new Cookie("userName", userName);
        Cookie card2 = new Cookie("money",money);
        //3.发卡,将Cookie写入到响应头交给浏览器
        response.addCookie(card1);
        response.addCookie(card2);
        //4.通知Tomcat将【点餐页面】内容写入到响应体交给浏览器(请求转发)
        request.getRequestDispatcher("/index_2.html").forward(request, response);

    }
}

TwoServlet.java

package com.bjpowernode.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 javax.smartcardio.Card;
import java.io.IOException;
import java.io.PrintWriter;

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 {
        int jiaozi_money = 30;
        int gaifan_money = 15;
        int miantiao_money = 20;
        int money = 0, xiaofei = 0, balance = 0;
        String food, userName = null;
        Cookie cookieArray[] = null;
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        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);
                if ("饺子".equals(food)) {
                    if (jiaozi_money > money) {
                        out.print("用户 " + userName + " 余额不足,请充值");
                    } else {
                        newCard = new Cookie("money", (money - jiaozi_money) + "");
                        xiaofei = jiaozi_money;
                        balance = money - jiaozi_money;
                    }
                } else if ("面条".equals(food)) {
                    if (miantiao_money > money) {
                        out.print("用户 " + userName + " 余额不足,请充值");
                    } else {
                        newCard = new Cookie("money", (money - miantiao_money) + "");
                        xiaofei = miantiao_money;
                        balance = money - miantiao_money;
                    }
                } else if ("盖饭".equals(food)) {
                    if (gaifan_money > money) {
                        out.print("用户 " + userName + " 余额不足,请充值");
                    } else {
                        newCard = new Cookie("money", (money - gaifan_money) + "");// 10+"abc"="10abc"
                        xiaofei = gaifan_money;
                        balance = money - gaifan_money;
                    }
                }

            }


        }
        //4.将用户会员卡返还给用户
        response.addCookie(newCard);
        //5.将消费记录写入到响应
        out.print("用户 " + userName + "本次消费 " + xiaofei + " 余额 :" + balance);
    }
}

HttpSession接口:

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

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

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

2.HttpSession 与 Cookie 区别:【面试题】

1)存储位置: 一个在天上,一个在地下

Cookie:存放在客户端计算机(浏览器内存/硬盘)
HttpSession:存放在服务端计算机内存

2)数据类型:
Cookie对象存储共享数据类型只能是String
HttpSession对象可以存储任意类型的共享数据Object

  1. 数据数量:
    一个Cookie对象只能存储一个共享数据
    HttpSession使用map集合存储共享数据,所以可以存储任意数量共享数据

4)参照物:
Cookie相当于客户在服务端的【会员卡】
HttpSession相当于客户在服务端的【私人保险柜】

3.命令实现:
同一个网站(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");
    }
                  
}
HttpSession模拟购物车.png

index.html




    
    Title


          
商品名称 商品单价 供货商 放入购物车
华为笔记本电脑pro13 7000 华为 放入购物车
榴莲 300 泰国 放入购物车
男士内裤 1000 老崔 放入购物车
查看我的购物车

web.xml



    
        OneServlet
        com.bjpowernode.controller.OneServlet
    
    
        TwoServlet
        com.bjpowernode.controller.TwoServlet
    
    
        TwoServlet
        /two
    
    
        OneServlet
        /one
    
    
    
        5
    

OneServlet.java

package com.bjpowernode.controller;

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

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();
           //session.setMaxInactiveInterval(5);
          //3.将用户选购商品添加到当前用户私人储物柜
          Integer  goodsNum = (Integer)session.getAttribute(goodsName);
          if(goodsNum == null){
              session.setAttribute(goodsName, 1);
          }else{
              session.setAttribute(goodsName, goodsNum+1);
          }
    }
}

TwoServlet.java

package com.bjpowernode.controller;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Enumeration;

public class TwoServlet extends HttpServlet {


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

         //1.调用请求对象,向Tomcat索要当前用户在服务端私人储物柜
         HttpSession session = request.getSession();

         //2.将session中所有的key读取出来,存放一个枚举对象
        Enumeration goodsNames =session.getAttributeNames();
        while(goodsNames.hasMoreElements()){
              String goodsName =(String) goodsNames.nextElement();
              int goodsNum = (int)session.getAttribute(goodsName);
            System.out.println("商品名称 "+goodsName+" 商品数量 "+goodsNum);
        }
    }
}

4.Http服务器如何将用户与HttpSession关联起来

                    cookie
HttpSession与用户关联原理图.png

5.getSession() 与 getSession(false)

1)getSession():
如果当前用户在服务端已经拥有了自己的私人储物柜.要求tomcat将这个私人储物柜进行返回

如果当前用户在服务端尚未拥有自己的私人储物柜要求tocmat为当前用户创建一个全新的私人储物柜

2)getSession(false):
如果当前用户在服务端已经拥有了自己的私人储物柜.要求tomcat将这个私人储物柜进行返回

如果当前用户在服务端尚未拥有自己的私人储物柜此时Tomcat将返回null

6.HttpSession销毁时机:

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

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

3)由于Tomcat无法检测浏览器何时关闭,因此在浏览器关闭时并不会导致Tomcat将浏览器关联的HttpSession进行销毁

4)为了解决这个问题,Tomcat为每一个HttpSession对象设置【空闲时间】,这个空闲时间默认30分钟,如果当前HttpSession对象空闲时间达到30分钟,此时Tomcat认为用户已经放弃了自己的HttpSession,此时Tomcat就会销毁掉这个HttpSession

7.HttpSession空闲时间手动设置

在当前网站/web/WEB-INF/web.xml


     5 

HttpServletRequest接口实现数据共享

1.介绍:

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

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

2.命令实现:

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

 OneServlet{
                 
     public void doGet(HttpServletRequest req,HttpServletResponse response){
                   
        //1.将数据添加到【请求作用域对象】中attribute属性
         req.setAttribute("key1",数据); //数据类型可以任意类型Object
               //2.向Tomcat申请调用TwoServlet
               req.getRequestDispatcher("/two").forward(req,response)
    }            
}
 TwoServlet{
    public void doGet(HttpServletRequest req,HttpServletResponse response){
                                            
        //从当前请求对象得到OneServlet写入到共享数据
         Object 数据 = req.getAttribute("key1");
     }
             
}

OneServlet.java

package com.bjpowernode.controller;

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

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.将数据添加到请求作用域对象,作为共享数据
          request.setAttribute("key1", "hello World");
         //2.代替浏览器,向Tomcat索要TwoServlet来完成剩余任务
          request.getRequestDispatcher("/two").forward(request, response);
    }
}

TwoServlet

package com.bjpowernode.controller;

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

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("TwoServlet得到共享数据 "+value);
    }
}

你可能感兴趣的:(Servlet学习1:Http状态码、多个Servlet之间调用规则、多个Servlet之间数据共享实现方案)