JavaWeb开发的Servlet规范

Servlet 规范

Servlet(Server Applet) ,全称Java Servlet,未有中文译文。是用Java编写的服务器端进程。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。

狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类别,一般情况下,人们将Servlet理解为后者。

Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

最早支持Servlet标准的是JavaSoft的Java Web Server。此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。

Servlet 规范来自与 JavaEE 规范中的一种,其作用是:

  • 在Servlet 规范中,制定了【动态资源文件】的开发步骤

    怎样把一个 Java 文件变成一个动态的资源文件呢?在这个规矩里他会告诉你怎么做,有多少步

  • 指定Http 服务器调用动态资源文件的规则

    Http 服务器是怎么调用动态资源文件的?简单点来说,当 Http 服务器发现浏览器索要的是一个动态资源文件时,由HTTP 服务器创建出这个当前这个类的实例对象,然后调用实例对象的方法来处理请求,然后将处理结果以二进制,通过HTTP服务器放入HTTP 响应包中,交给浏览器

  • 指定 Http 服务器管理动态资源文件实例对象的规则

    当类的对象被创建之后,怎么管理他呢?在Servlet 规范中已经告诉了HTTP 服务器了

Servlet 接口实现类

  • Servlet 接口来自于 Servlet 规范下的一个接口,这个接口存在于HTTP 服务器

  • Tomcat 服务器下 lib 文件夹有一个 servlet-api.jar ,这里存放Servlet 接口(javax.servlet.Servlet)

  • Servlet 规范中认为,HTTP 服务器能调用的动态资源文件必须是一个Servlet 接口的实现类,只有Servlet 的实现类才是我们说的【动态资源文件】

    例子:
    class Student{
        //不是动态资源文件,Tomcat 无权调用
    }
    ​
    class Teacher implements Servlet{
        //合法的动态资源文件,Tomcat 有权调用
        Servlet obj = new Teacher();
        obj.doGet();
    }
    复制代码

Servlet 接口实现类开发步骤

第一步:创建一个 Java 类,继承于 HttpServlet 父类,使之成为一个Servlet 接口的实现类

第二步:重写父类HttpServlet 中的两个方法,doGet或者doPost

第三步:将Servlet 接口实现类信息【注册】到Tomcat 服务器

Servlet 接口实现类开发步骤

第一步∶创建一个Java 类继承 HttpServlet 这个父类,使之成为一个 Servlet 接口的实现类

第二步∶重写 HttpServlet 父类的两个方法。doGet 和 doPost 方法 浏览器使用 get 请求就会调用Servlet 对象的doGet 方法

第三步∶将Servlet 接口的实现类信息【注册】到 Tomcat 服务器 在 web.xml 配置文件中写。 将 Servlet 接口实现类的类路径交给 Tomcat,类路径就是完整的包名。 为了便于访问,可以设置个简短的请求别名 【以后为了方便,【注册阶段】可以直接在创建src下new的时候勾选 servlet 来自动生成】

Servlet 对象的生命周期

第一,网站中所有的 Servlet 接口实现类的实现对象,只能由 Http 服务器负责创建。开发人员不能手动把他们 new 实例对象出来。

第二,在默认的情况下,在 Http 服务器接受到对于当前 Servlet 接口实现类第一次请求时,自动创建new 出实例对象。 但是,在手动配置的情况下,如果要求 Http 服务器在启动时就自动创建某个 Servlet 接口的实现类对象时 要求在【注册】时写上

中间写上大于0的整数

第三,在互联网通信过程,经常会有多个用户来访问同一个 Servlet 接口的情况 在这种情况下,Http 服务器运行期间,一个 Servlet 接口实现类只能被创建出一个实例对象。相当于一个进程对多个线程,用户的请求相当于一个线程。 doGet,doPost可以多次调用,但是对象只能创建一次

第四,销毁时机 在 Http 服务器关闭时, 自动将网站中所有的 Servlet 对象进行销毁。

HttpServletResponse 接口

介绍∶ HttpServletResponse 接口来自于 Servlet 规范中,在 Tomcat 中存在于 servlet-api.jar HttpServletResponse 接口实现类由 Http 服务器负责提供 HttpServletResponse 接口负责将 doGet/doPost 方法执行结果写入【响应体】中,交给浏览器对象 开发人员习惯将 HttpServletResponse 接口修饰的对象称为【响应对象】

主要功能∶

  • 1、将执行结果以二进制写入到响应体
  • 2、设置响应头中的【content-type】属性,从而控制浏览器使用对应的编译器将响应体的二进制数据编译为文字,图片,视频,命令等
  • 3、设置响应头中的【location】属性,将一个请求地址赋值给 location 从而控制浏览器向指定服务器发送请求

1、资源文件里的内容是怎么写到响应体里的呢?

实际上,HTTP服务器 tomcat 里有一个输出流,可以把文件资源写进响应体中。如果我们能拿到这个输出流,那我们也能把资源写进响应体中了

public class OneServlet extends HttpServlet{
    protected void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException,IOException{
        String result = "Hello World !";// 要输出这句话
        //----------响应对象将结果写入响应体中 begin----------
        
            //1、通过响应对象,向Tomcat获取输出流
            PrintWriter out = response.getWriter();
            //2、用过输出流,将执行结果以二进制形式写入响应体中
            out.write(result);
            
            //整合写法是:response.getWriter().writer("Hello World !");
        
            //用完输出流不用关闭,因为不是开发人员创建的输出流
        
        //----------响应对象将结果写入响应体中  end ----------
    }
    //doGet执行完毕后,Tomcat将响应包推送给浏览器
}
复制代码

展示一下 response.getWriter().write("Hello World !"); 中,write方法的弊端

protected void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException,IOException{
    int i = 50;
    PrintWriter out = response.getWriter();
    out.writer(i);
    //浏览器上显示的结果是 2
}
这是为什么呢?这是因为,write()中所传的int类型的参数会转换成ASCII码,2的ASCII码就是50
    这时要用到这个方法:
    print(i);
一般开发中都用这个方法。整合写法:
    response.getWriter().print(50);   //这时浏览器上显示的结果是:50
    
复制代码

2、怎么设置响应头中的【content-type】属性呢?

protected void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException,IOException{
    
    //设置响应头content-type
    //文字信息记得修改字符编码,默认是charset=ISO-8859-1,一个东欧的字符集
    response.setContentType("text/html;charset=utf-8");
    
    //既有文字又有HTML标签命令怎么办?
    //一定要在得到输出流之前,通过响应对象 对响应头中的content-type 属性进行一次重新赋值,用于指定浏览器采用正确的编译器解析
    String result = "Java<br/>MySQL<br/>HTML<br/>"
    
}
复制代码

3、设置响应头中的【location】属性

protected void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException,IOException{
    String result = "http://www.baidu.com";
    
    //通过响应对象,将地址赋值给响应头中的location 属性
    response.sendRedirect(result);
}
/*
    浏览器在接收到响应包之后,如果发现响应头存在location属性
    自动通过地址栏向location指定网站发送请求
    
    sendRedirect方法远程控制浏览器请求行为【请求地址、请求方式、请求参数】
*/
复制代码

===============================================================

doGet方法中的参数是这两个接口的实现类,实现类由 Http 服务器创建,不用我们管 这个接口的实现类里面有io流

//向 Tomcat 索要输出流 response.getWriter()方法返回一个PrintWriter流对象,则

PrintWriter out = response.getWriter(); out.write(参数); 这个会把数字以ASCII码形式 //通过输出流将结果写入响应体中 所以一般用 out.print(真实数据);

然后这个对象会被推入响应包中发给浏览器

注意,修改 IDEA 里面的内容时,通过修改设置可以不用重启。动态或者静态资源文件的内容发生改变,由 IDEA 自动更新到 Tomcat 中 然后在 Debug 中启动

HttpServletRequest 接口

介绍∶ HttpServletRequest 接口来自于 Servlet 规范中,在 Tomcat 中存在于 servlet-api.jar HttpServletRequest 接口实现类由 Http 服务器负责提供 HttpServletRequest 接口负责将 doGet/doPost 方法运行时,读取 Http 请求协议包中的信息 开发人员习惯将 HttpServletRequest 接口修饰的对象称为【请求对象】

主要功能:

  • 可以读取 Http 请求协议包中的【请求行】中的URL,method ,URI 信息
  • 可以读取保存在 Http 请求协议包中【请求头/请求体】中的参数信息
  • 可以代替浏览器向 Http 服务器申请对动态资源文件的调用

1、读取 Http 请求协议包中的【请求行】中的URL,method ,URI

protected void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException,IOException{
    //1、通过请求对象,读取【请求行】中的 URL 信息
    //request。getRequestURL() 返回的是一个StringBuffer,所以转成toString输出到控制台
    String url = request.getRequestURL().toString
        
    //2、通过请求对象,读取【请求行】中的 method 信息
        String method = request.getMethod();
    
    //3、通过请求对象,读取【请求行】中的 URI 信息
    /*
        URI:资源文件精准定位地址,在请求行并没有 URI 这个属性
            实际上URI 是从URL 中截取的一个字符串。这个字符串的格式:/网站名/资源文件名
            URI 用于让HTTP服务器对被访问的资源文件进行定位处理
    */
        String uri = getRequestURI();
    
    //输出
    System.out.println("URL" + url);
    System.out.println("method" + method);
    System.out.println("URI" + uri);
}
复制代码

2、读取保存在 Http 请求协议包中【请求头/请求体】中的参数的 名称 和 值

//请求头
protected void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException,IOException{
    //1、通过请求对象获得【请求头】中的【所有参数名】
    //将所有请求参数名称保存到一个枚举对象进行返回
    Enumeration paramNames = request.getParameterNames();
    
    //while循环遍历
    while(paramNames.hasMoreElements()){
        String paramName = (String)paramNames.nextElement();
        
        //2、通过请求对象读取指定的请求参数的值
        String value = request.getParameter(paramName);
        System.out.println("请求参数名:" + paramName);
        System.out.println("请求参数值:" + value);
    }
}
​
//请求体
protected void doPost(HttpServletRequest request , HttpServletResponse response) throws ServletException,IOException{
    /*
    乱码现象:
        在HTTP请求协议包到达HTTP服务器之后,第一件事就是解码(无论是GET 还是 POST)
        请求头二进制内容由 Tomcat 负责解码,Tomcat9.0默认使用 utf-8 字符集,可以解码所有国家语言
        请求体当前请求对象(request)负责解码,request默认使用ISO-8859-1 字符集
        
        若以POST方式向浏览器发送参数,发送中文,在服务器内会得到一个乱码
        因为默认编码是:charset=ISO-8859-1,一个东欧语系的字符集
        
    解决方案:
        在POST请求方式下,在读取请求体内容之前,应该通知请求对象使用 utf-8 字符集进行解码
    */
    
    //通知请求对象,使用 utf-8 进行解码
    request.setCharacterEncoding("utf-8");
    String value = request.getParameter("password");
    System.out.println("从请求体中得到的参数值" + value);
}
复制代码

3、代替浏览器向 Http 服务器申请对动态资源文件的调用

protected void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException,IOException{
}
复制代码

请求对象和响应对象的生命周期

在HTTP 服务器接受到浏览器发送的【HTTP请求协议包】之后,自动为当前的HTTP请求协议包生成一个【请求对象】和【响应对象】

在HTTP 服务器调用 doGet/doPost 方法时,负责将【请求对象】和【响应对象】作为实参传入方法中,确保doGet/doPost 正确执行

在HTTP 服务器准备推送 HTTP 响应协议包之前,负责将本次请求关联的【请求对象】和【响应对象】销毁。

【请求对象】和【响应对象】生命周期贯穿于一次请求的处理过程中 【请求对象】和【响应对象】相当于用户在服务端的代言人,捎话的

多个 Servlet 之间互相调用的规则

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

提高用户使用感受的规则:无论本次请求涉及到多少个 Servlet,用户只需要手动通知浏览器发起一次请求即可

【重定向】解决方案

工作原理

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

语法格式

response.sendRedirect("请求地址");
//将地址写入响应包中 到响应头里的 location属性
请求地址:写完整的 URI:(/网站名/资源名1/资源名2复制代码

特征

既可以获取本网站的资源,也可以获取外部网站的资源

请求地址:

既可以吧当前网站的内部资源文件地址发送给浏览器(/网站名、资源文件名)

也可以把其他网站资源文件地址发送给浏览器(http://ip地址:端口号/网站名/资源文件名)

请求次数:

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

请求方式:

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

缺点:

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

【请求转发】解决方案

工作原理

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

语法格式

//1、通过当前【请求对象】生成资源文件 申请报告对象
RequestDispatcher report = request.getRequestDispatcher("/资源文件名");//一定要以 “/” 作为开头,不能加上网站名,只能写资源文件名

//2、将 报告对象 发送给Tomcat
report.forward(当前请求对象,当前响应对象);
//report.forward(request,response);
//就是将request,的响应 response 推给了TwoServlet
复制代码

注意一下:记得加斜杠

  • 调用静态资源文件:写资源文件全名
  • 调用动态资源文件:写别名

优点

  • 无论本次请求涉及多少个Servlet,用户只需要手动通过浏览器发送一次请求
  • Servlet 之间的调用发生在服务端计算机上,节省服务端与浏览器之间的往返次数,增加处理服务速度

特征

请求次数:

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

请求地址:

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

    request.getRequestDispatcher("/资源文件名");

    注意:不要写网站名。

请求方式:

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

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

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

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

    1、ServletContext 接口

    2、Cookie 类

    3、HttpSession 接口

    4、HttpServletRequest 接口

ServletContext 接口

介绍:

  • 这是来自于Servlet 规范中的一个接口。在Tomcat 中存在 servlet-api.jar

    在Tomcat中负责提供这个接口的实现类。

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

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

工作原理

每个网站都存在一个全局作用域对象,这个全局作用域对象相当于一个【Map】。

在这个网站中OneServlet 可以将一个数据存入到全局作用域对象。当前网站中其他Servlet 都可以从全局作用域对象得到这个数据并使用

全局作用域对象生命周期

  • 1、在HTTP服务器启动过程中,自动为当前网站在内存中创建一个全局作用域对象
  • 2、在HTTP服务器运行期间,一个网站只有一个全局作用域对象
  • 3、在HTTP服务器运行期间,全局作用域对象一直处于存活状态
  • 4、在HTTP服务器准备关闭时,负责将当前网站中的全局作用域对象进行销毁处理

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

语法格式

public void doGet(HttpServletRequest request , HttpServletResponse response){
    //1、通过【请求对象】向Tomcat 索要当前网站中的【全局作用域对象】
    ServletContext application = request.getServletContext();
    //2、将数据添加到全局作用域对象作为【共享数据】
    application.setAttribute( String key1 , Object 数据);
}
===============
    别的servlet对象获取的话,只需要将第一步重复
    然后第二步是application.getAttribute("key1");
复制代码

Cookie

介绍:

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

    实现类由Http 服务器提供

  • 条件:如果两个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","value1");
        Cookie card2 = new Cookie("xxx","yyy");
        
        /*
        	1、Cookie相当于一个Map
       		2、一个Cookie 中只能存放一个键值对
        	3、这个键值对的key和value 只能是String 类型
        	4、键值对中的“key” 在Tomcat 8 之前不能是中文
        */
        
       //2、【发卡】将Cookie写入到响应头,交给浏览器
        response.addCookie(card1);
        response.addCookie(card2);
    }
}
复制代码

浏览器向myweb 网站发送请求访问TwoServlet

TwoServlet{
    public void doGet(HttpServletRequest request,HttpServletResponse response){
        
        //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 中的 “value1”
           
            从而提供较好的服务
        }
    }
复制代码

最后附上:“ 老崔出轨图 ”

Cookie 的生命周期

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

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

    cookie.setNaxAge(60);//Cookie 在硬盘上存活一分钟
    复制代码

HttpSession 接口

介绍:

  • 这是来自于Servlet 规范中的一个接口。在Tomcat 中存在 servlet-api.jar

    在Tomcat中负责提供这个接口的实现类。

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

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

HttpSession 和 Cookie 的区别

存储位置:

一个在天上,一个在地下。(Session 在天上,即服务端计算机 。 Cookie 在地上,即客户端计算机)

数据类型:

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

数据数量:

  • 一个Cookie 对象只能存储一个共享数据
  • HttpSession 使用Map 集合存储数据,所以可以存储任意数量的共享数据

参照物:

  • Cookie 相当于客户在服务端的【会员卡】
  • HttpSession 相当于客户在服务端的【私人保险柜】

语法格式

同一网站下,OneServlet 将数据传递给TwoServlet

OneServlet{
	public void doGet(HttpServletRequest request,HttpServletResponse response){
        //1、调用请求对象向Tomcat 索要当前童虎在服务端的私人储物柜
        HttpSession session = request.getSession();
        //2、将数据添加到私人储物柜
        seesion.setAttribute(String key , Object value);
    }    
}
复制代码
TwoServlet{
    public void doGet(HttpServletRequest request,HttpServletResponse response){
        //1、调用请求对象向Tomcat 索要当前童虎在服务端的私人储物柜
    	HttpSession session = request.getSession();
        //2、从【会话作用域】对象得到 OneServlet提供的共享数据
        Object value = session.getValue("key");
    }
}	
复制代码

HTTP 服务器如何将用户与HttpSession 关联起来

通过 Cookie

  • session 对象里面有个 id 属性,会把里面的值塞到响应头中 作为Cookie 值,打到浏览器上。响应头里就有了一个 Set-Cookie 属性,这个就是柜子编号

    Set-Cookie:JSESSIONID:xxxxxxxxx

  • 下一次浏览器向HTTP服务器发起请求之后,会将Set-Cookie:JSESSIONID:xxxxxxxxx 。 放入请求头中,tomcat 调用getSession,一看,这个请求头中有JSESSIONID,说明这哥们儿有柜子,再根据这个取得柜子编号

getSession( ) 与 getSession(false)

1、getSession( )

如果当前用户在服务端已经拥有了属于自己的私人储物柜,要求Tomcat 将这个私人储物柜进行返回

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

2、getSession(false)

如果当前用户在服务端已经拥有了自己的私人储物柜,要求Tomcat 将这个私人储物柜返回。

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

HttpSession 销毁时机

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

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

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

  • 4、为了解决这个问题,Tomcat 为每一个HttpSession 对象设置【空闲时间】,这个空闲时间默认是30分钟

    此时Tomcat认为用户

HttpSession 空闲时间 手动设置

当前网站的/web/WEB-INF/web.xml
<seesion-config>
	<seesion-tomeout>5</seesion-tomeout>
	<!--当前网站中每一个seesion最大空闲时间5分钟-->
</seesion-config>
复制代码

HttpServletRequest 接口实现数据共享

介绍:

  • 在同一个网站中,如果两个Servlet 之间通过【请求转发】方式进行调用,彼此之间共享一个请求协议包。

    而一个请求协议包只对应一个请求对象。因此Servlet 之间共享同一个请求对象,此时可以利用这个请求对象在两个Servlet 之间实现数据共享

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

语法格式

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

OneServlet{
    public void doGet(HttpServletRequest request,HttpServletResponse response){
        //1、将数据添加到【请求作用域对象】中的attribute属性
        request.setAttribute(String key , Object value);//value值数据类型可以是任意类型
        //2、向Tomcat 申请调用TwoServlet
        request.getRequestDispatcher("/two").forward(request,response);
    }
}
复制代码

TwoServlet

TwoServlet{
    public void doGet(HttpServletRequest request,HttpServletResponse response){
        //从当前请求对象中得到OneServlet写入的共享数据
        Object value = request.getAttribute("key");
    }
}
复制代码

监听器接口(Listener)

实例:通过监听器接口提高程序运行速度

介绍:

  • 一组来自于Servlet规范下的接口,共有 8 个接口。在Tomcat 中存在于 servlet-api.jar 中
  • 监听器接口需要由开发人员亲自来实现,Http 服务器提供的 jar 包并没有对应的实现类
  • 监听器接口用于监控【作用域对象生命周期变化时刻】以及【作用域对象共享数据变化时刻

作用域对象

  • 在Servlet 规范中,认为在服务端内存中可以在某些条件下为两个Servlet 之间提供数据共享方案的对象,被称为【作用域对象】

  • Servlet 规范下的作用域对象

    1、ServletContext :全局作用域对象

    2、HttpSession :会话作用域对象

    3、HttpServletRequest :请求作用域对象

    注意:Cookie 虽有给两个Servlet 之间提供数据共享的功能,但不属于作用域对象。

    因为Cookie出身不好.Cookie 是存在于客户端计算机中浏览器内存、或者是存在于计算机硬盘中的对象它不在服务端。

    所以在Servlet 规范中,Cookie 并没有作为【作用域对象】来看

    在Servlet 规范中只有三个作用域对象,在JSP 规范中,除了这三个,还多了一个 pageContext

监听器接口实现类开发规范

  • 1、根据监听的实际情况,选择对应的监听器接口进行实现(根据情况选择其中一个进行 implements)
  • 2、重写监听器接口声明【监听事件处理方法】
  • 3、在 web.xml 文件将监听器接口实现类注册到HTTP服务器

ServletContextListener 接口

  • 作用:通过这个接口合法的检测全局作用域对象被初始化的时刻以及被销毁的时刻

  • 监听事件处理方法:

    //在全局作用域对象被HTTP服务器初始化被触发
    public void  contextInitialized(ServletContextEvent sce)
        
    //在全局作用域对象被HTTP服务器销毁的时候触发
    public void contextDestroyed(ServletContextEvent sce);
    复制代码

ServletContextAttributeListener 接口

这接口的名字真特么长

  • 作用:通过这个接口合法的检测全局作用域对象共享数据的变化时刻

  • 监听事件处理方法

    public void contextAdd();	//在全局作用域对象添加共享数据时被触发
    public void contextReplaced();	//在全局作用域对象更改共享数据时被触发
    public void contextRemove();	//在全局作用域对象删除共享数据时被触发
    复制代码

全局作用域对象共享数据变化时刻

    ServletContext application = request.getServletContext();
    application.setAttribute("key1",100);//新增共享数据
    application.setAttribute("key1",200);//更新共享数据
    application.setAttribute("key1");	//删除共享数据
复制代码

过滤器接口(Filter)

Filter 这个技术符合 AOP 编程方式

实例:过滤器防止恶意登陆行为

介绍:

  • 来自于Servlet 规范下的接口,在Tomcat 中存在于 servlet-api.jar
  • Filter 接口的实现类由开发人员负责提供,HTTP服务器不负责提供。
  • Filter 接口在HTTP服务器调用资源文件之前,对HTTP服务器进行拦截

作用

  • 1、拦截HTTP服务器,帮助HTTP服务器检测当前请求的合法性

  • 2、拦截HTTP服务器,对当前请求进行增强操作

    例如,以POST请求调用多个Servlet ,不用每个Servlet 里都写 request.setCharacterEncoding("utf-8");

    在过滤器里写即可

开发步骤

  • 1、创建一个Java 类来 implements Filter 接口
  • 2、重写Filter 接口中的 doFilter 方法
  • 3、将过滤器接口的实现类注册到HTTP服务器( web.xml )
  • doFilter方法中判断,然后用户身份验证成功后

    用 filterChain.doFilter(servletRequest,servletResponse) 来放行

Filter 拦截地址格式

1、命令格式

<filter>
    <filter-name></filter-name>
    <filter-class></filter-class>
</filter>

<filter-mapping>
    <filter-name>oneFilter</filter-name>
    <url-parttern>拦截地址</url-parttern>
</filter-mapping>

<!-- 提示:filter-mapping写的越靠上,越先执行。filter-mapping的顺序决定了过滤器的执行顺序! -->
复制代码

2、不同的命令作用

作用:拦截地址通知Tomcat 在调用何种资源文件之前需要调用 OneFilter 过滤拦截

1、要求Tomcat 在调用某一个具体文件之前,来调用 OneFilter 拦截
<url-parttern>/img/mm.jpg</url-parttern>

2、要求Tomcat 在调用某一个文件夹下的所有资源文件之前,来调用 OneFilter 拦截
<url-parttern>/img/*</url-parttern>

3、要求Tomcat 在调用任意文件夹下某种类型文件,来调用 OneFilter 拦截(这里比如限制调用 .jpg 类型的资源文件)
<url-parttern>*.jpg</url-parttern>

4、要求Tomcat 在调用网站中任意文件时,来调用 OneFilter 拦截
<url-parttern>/*</url-parttern>
复制代码

防止用户恶意登陆

令牌机制

缺点

1、增加开发难度,每写一个Servlet 都要重复写一边这个令牌机制的代码

2、不能对静态资源文件进行保护,因为不能在静态资源文件里面写命令

使用过滤器防止用户恶意登陆

过滤器转发(过滤规则)

请求转发的时候,可能会用上,一般都是 request

<!-- 使用以下标签可以配置过滤器的过滤规则,缺省值是:REQUEST -->
<fliter-mapping>
    <dispatcher>FORWARD</dispatcher>
</fliter-mapping>
<!-- 使用REQUEST相当于没用 -->
复制代码

注意:

  • 如果使用 FORWARD 的话,重定向不经过过滤器
  • 如果使用 REQUEST 的话,重定向,加上先前的那次请求,经过两次过滤器

过滤器优先级

web.xml 的加载顺序是:context-param -> listener -> filter -> servlet

参考地址:filter,listener,context-param,servlet加载顺序_iteye_18800的博客-CSDN博客

猜你喜欢

转载自juejin.im/post/7096719011966091272
今日推荐