【Servlet】3:Servlet 的基本原理、Servlet对象的生命周期

目录

第五章 | 动态资源与Servlet

| 章节概述

| Tomcat与Servlet的 原理、关系

Tomcat的基本构成​编辑

Server处理HTTP请求

Connector内部架构分析

Container内部架构分析

Tomcat的执行流程小结

| Servlet 概述、接口实现

Servlet的基本概述

实现Servlet接口并通过URL访问:四大步骤

IDEA一键生成Servlet实现类

| Servlet对象的 周期与load-on-startup


本文章属于后端全套笔记的第三部分

(更新中)【后端入门到入土!】Java+Servlet+JDBC+SSM+SpringBoot+SpringCloud 基础入门_m0_57265007的博客-CSDN博客一篇文章,后端入门到入土。包含 Java基础+高级、MySQL、JDBC、Servlet、SSM、SpringBoot、SpringCloud、项目 的笔记。https://blog.csdn.net/m0_57265007/article/details/127962617?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22127962617%22%2C%22source%22%3A%22m0_57265007%22%7D

第五章 | 动态资源与Servlet

| 章节概述

本章将学习

  • 通过Tomcat的基本原理,引出Servlet的基本原理(理论基础)

  • 掌握Servlet在IDEA中创建其实现类、注册配置实现类到Tomcat、部署、访问的一系列步骤。同时学会使用IDEA快速生成Servlet类的敲门

  • Servlet对象的生命周期、被创建的时机、load-on-time参数

  • HttpServletRequest 解析HTTP请求并发送给服务器

  • HttpServletResponse 响应HTTP请求

  • 多Servlet间数据共享

  • 多Servlet间调用规则


| Tomcat与Servlet的 原理、关系

Tomcat的基本构成

1、Tomcat中最顶层的容器是Server,代表着整个服务器,一个Server可以包含至少一个Service,用于具体提供服务。

2、Service主要包含两个部分:Connector和Container。 Tomcat 的心脏就是这两个组件,这两个组件的作用:Connector用于处理连接相关的事情,并提供Socket与Request和Response相关的转化;Container用于封装和管理Servlet,以及具体处理Request请求。

3、一个Tomcat中只有一个Server,一个Server可以包含多个Service,一个Service只有一个Container,但是可以有多个Connectors,因为一个服务可以有多个连接,如同时提供Http和Https链接,也可以提供向相同协议不同端口的连接。

4、多个 Connector 和一个 Container 就形成了一个 Service,有了 Service 就可以对外提供服务了,但是 Service 还要一个生存的环境,必须要有人能够给她生命、掌握其生死大权,那就非 Server 莫属了!所以整个 Tomcat 的生命周期由 Server 控制。另外,上述的包含关系或者说是父子关系,都可以在tomcat的conf目录下的server.xml配置文件中看出。

5、Server标签设置的端口号为8005(注意:Server标签的端口号8005用于监听Tomcat的Server接口;而Tomcat端口8080是用于监视来自外部的HTTP请求。两者是不一样的概念!),shutdown=”SHUTDOWN” ,表示在8005端口监听“SHUTDOWN”命令,如果接收到了就会关闭Tomcat。一个Server有一个Service,当然还可以进行配置,一个Service有多个,Service左边的内容都属于Container的,Service下边是Connector。


Server处理HTTP请求

1.用户在浏览器中输入该网址,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得;

2.Connector把该请求交给它所在的Service的Engine(Container)来处理,并等待Engine的回应;

3.Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host;

4.Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机),名为localhost的Host获得请求/test/index.jsp,匹配它所拥有的所有Context。Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为“ ”的Context去处理);

5.path=“/test”的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL Pattern为*.jsp的Servlet,对应于JspServlet类;

6.构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost(),执行业务逻辑、数据存储等;

7.Context把执行完之后的HttpServletResponse对象返回给Host;

8.Host把HttpServletResponse对象返回给Engine;

9.Engine把HttpServletResponse对象返回Connector;

10.Connector把HttpServletResponse对象返回给客户Browser。


Connector内部架构分析

  • Connector用于接受请求并将请求封装成Request和Response,然后交给Container进行处理,Container处理完之后在交给Connector返回给客户端

  • Connector就是使用ProtocolHandler来处理请求的,不同的ProtocolHandler代表不同的连接类型


Container内部架构分析

(1)Engine:引擎,用来管理多个站点,一个Service最多只能有一个Engine;

(2)Host:代表一个站点,也可以叫虚拟主机,通过配置Host就可以添加站点;

(3)Context:代表一个应用程序,对应着平时开发的一套程序,或者一个WEB-INF目录以及下面的web.xml文件;

(4)Wrapper:每一Wrapper封装着一个Servlet;

Context和Host的区别是Context表示一个应用,我们的Tomcat中默认的配置下webapps下的每一个文件夹目录都是一个Context,其中ROOT目录中存放着主应用,其他目录存放着子应用,而整个webapps就是一个Host站点。


Tomcat的执行流程小结

  1. 首先,使用 startup 命令,Server标签的端口号8005监听到命令后,开启Tomcat服务器的服务

  2. 客户端发起请求,Tomcat的8080端口收到请求,开始一系列的处理

  3. 当一个请求发送到Tomcat之后,首先经过Service然后会交给Connector,Connector用于接收请求并将接收的请求封装为Request和Response来具体处理,Request和Response封装完之后再交由Container内的Servlet进行处理,Container处理完请求之后再返回给Connector,最后在由Connector通过Socket将处理的结果返回给客户端,这样整个请求的就处理完了!

  4. Connector最底层使用的是Socket来进行连接的,Request和Response是按照HTTP协议来封装的,所以Connector同时需要实现TCP/IP协议和HTTP协议!

  • 最后总结一下:

    (1)Tomcat中只有一个Server,一个Server可以有多个Service(用于具体提供服务),一个Service可以有多个Connector(因为一个服务可以有多个连 接)和一个Container; (2) Server掌管着整个Tomcat的生死大权; (4)Service 是对外提供服务的; (5)Connector用于接受请求并将请求封装成Request和Response来具体处理; (6)Container用于封装和管理Servlet,以及具体处理request请求;


| Servlet 概述、接口实现

Servlet的基本概述

  • 前面提到了,Servlet 是存在于 Tomcat中的Container中的Wrapper中的一个接口。对于程序员而言,无需深入Tomcat的底层实现。我们只需要知道:Javaweb开发,很大程度上就是在操作Tomcat中的Servlet接口:编写Servlet实现类的代码、在Tomcat的网站核心配置文件 web.xml中配置Servlet实现类对象和URL的映射关系等等……

  • 狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

  • Servlet的作用:

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

    • 在Servlet规范中,指定Http服务器调用动态资源文件规则

    • 在Servlet规范中,指定Http服务器管理动态资源文件实例对象规则

  • Tomcat服务器目录下lib文件有一个servlet-api.jar。这个就是Servlet接口的jar包~

  • Servlet规范中,HTTP服务器(Tomcat)能调用的【动态资源文件】必须是一个Servlet接口实现类


实现Servlet接口并通过URL访问:四大步骤

【前期准备】创建一个web Module

Step1.创建一个普通Java Module

Step2.右键模块,添加WEB框架支持。点击确认,就创建好了一个网站

【Step1】编写一个类,实现HttpServlet接口

  • 一般是继承Servlet接口已经写好的实现类HttpServlet,而不是直接 implements Servlet接口。目的是简化需要重写的方法数量,减少开发难度

  • 若没有导入Servlet类的Jar包,可以Ctrl+Alt+Shift+S  打开 Project Structure - Module - 对应Module。添加 Tomcat目录/lib 下的Servlet.jar

//src/controller/MyServlet.java
public class MyServlet extends HttpServlet {
}

【Step2】根据需要,重写HttpServlet的 doGet( ) 或 doPost( ) 方法

  • IDEA中快捷键:Ctrl+O 选择 doGet 和 doPost

  • 通过浏览器URL发送的请求都是GET请求,这里只重写GET即可(POST请求一般由前端method控制,或者重定向控制

【目录结构同Step1】

//src/controller/MyServlet.java
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //super.doGet(req, resp); 如果你是要彻底覆盖父类的doGet方法,不需要父类提供的功能,就可以删除super.doGet(req,resp);这一句
        System.out.println("这是Servlet的doGet方法");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //super.doPost(req, resp);
    }
}

【Step3】在web.xml配置文件中,把开发好的java类注册到web服务器(Tomcat)

  • web.xml的作用主要是:指定对应Servlet实现类的路径、对象名、以及对象名对应URL的名字

  • Servlet实现类的路径、对象名 写在 <servlet></sevlet> 里面

    Servlet实现类的对象名和URL的映射 写在 <servlet-mapping></servlet-mapping> 里面

    易错:<url-pattern>/web1</url-pattern> 中的别名,一定要以 / 开头!!!!

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    
    <!--在Tomcat目录下的【网站核心配置文件 web.xml】,注册Servlet的实现类-->
    <servlet>
        <servlet-name>MyServletName</servlet-name><!--【Servlet实现类的对象】的名字(动态代理 自动生成)-->
        <servlet-class>controller.MyServlet</servlet-class><!--【Servlet实现类】相对于src的路径-->
    </servlet>
    <!--将刚才注册的Servlet实现类的【对象名】对应网站中【作为url时的别名】-->
    <servlet-mapping>
        <servlet-name>MyServletName</servlet-name>
        <url-pattern>/web1</url-pattern><!--若当URL中有/web1:当Tomcat收到之后,会到web.xml中寻找对应的Servlet实现类对象名,然后动态代理根据其对应的类路径生成对象,执行业务代码-->
    </servlet-mapping>
    
</web-app>

【Step4】把网站部署到web服务器(Tomcat):运行 – 编辑配置 – 部署

部署步骤同 IDEATomcat 静态资源网站访问

然后部署后,进入浏览器访问即可


IDEA一键生成Servlet实现类

  • 在一键生成前,需要确保当前Mudule(Ctrl+Alt+Shift+S 打开Project Structure)导入了Servlet包

右键,选择Servlet即可(注意Servlet的实现类所属包一般都是controller下)

  • 若没有发现有Servlet选项,则还是建议你老老实实自己创建吧……反正也不麻烦。

  • 选项里没有Servlet的解决办法(不推荐使用,会破坏目录结构,仅作参考)参考资料

 

| Servlet对象的 周期与load-on-startup

Servlet对象的生命周期

  1. 网站中所有的Servlet接口实现类的实例对象,只能由Http服务器负责创建。开发人员不能手动创建Servlet接口实现类的实例对象

  2. 在Http服务器运行期间,一个Servlet接口实现类只能被创建出一个实例对象,但是能被多次执行(即被URL访问多次)

  3. 在Http服务器关闭后,自动将网站中所有的Servlet对象进行销毁

Servlet对象的创建时机 & load-on-startup配置参数

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>MyServletName</servlet-name>
        <servlet-class>controller.MyServlet</servlet-class>
        <load-on-startup>0</load-on-startup><!--填写一个大于0的整数即可。Tomcat会在启动后自动创建Servlet实现类对象。数字代表创建优先级-->
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServletName</servlet-name>
        <url-pattern>/web1</url-pattern>
    </servlet-mapping>
</web-app>

  • Servlet对象的创建时机(即初始化的时机)

    • 若没有在web.xml给对应的Servlet对象配置 load-on-startup 参数,则容器一般在第一次响应web请求时创建对象,会先检测该servlet是否初始化,如未初始化,则调用servlet的init()先初始化,初始化成功后,再响应请求。

    • 若配置了 load-on-startup 参数,servlet将在Tomcat启动startup后立即创建对应实现类对象,但只是调用servlet的init()方法,用以初始化该servlet相关的资源。初始化成功后,该servlet可响应web请求

  • load-on-startup参数的作用

    • 标记容器是否在启动的时候就加载这个servlet。

    • 中间的数值必须是个整数

    • >=0时,表示容器在启动时就会初始化这个servlet类。数值越小优先级越高,加载的越早

      < 0时,表示当调用这个servlet类时才会将其实例化

    • 如果我们在web.xml中设置了多个servlet的时候,可以使用load-on-startup来指定servlet的加载顺序,服务器会根据load-on-startup的大小依次对servlet进行初始化。不过即使我们将load-on-startup设置重复也不会出现异常,服务器会自己决定初始化顺序

验证 “Servlet对象只能被创建一次,但是能被多次调用” 和 验证load-on-startup确实能改变Servlet实现类的创建时机

  • init()方法可以理解为 Servlet实现类被创建时候的构造方法

//src/controller/MyServlet.java
public class MyServlet extends HttpServlet {

	//可以重写 init 方法,这个init方法代表对象被创建时候调用初始化。
    @Override
    public void init() throws ServletException {
    	super.init();
        System.out.println("MyServlet对象被创建了");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //...
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--在Tomcat目录下的【网站核心配置文件 web.xml】,注册Servlet的实现类-->
    <servlet>
        <servlet-name>MyServletName</servlet-name><!--【Servlet实现类的对象】的名字(动态代理 自动生成)-->
        <servlet-class>controller.MyServlet</servlet-class><!--【Servlet实现类】相对于src的路径-->
        <load-on-startup>0</load-on-startup><!--填写一个大于0的整数即可。Tomcat会在启动后自动创建Servlet实现类对象。数字代表创建优先级-->
    </servlet>
    <!--将刚才注册的Servlet实现类的【对象名】对应网站中【作为url时的别名】-->
    <servlet-mapping>
        <servlet-name>MyServletName</servlet-name>
        <url-pattern>/web1</url-pattern><!--若当URL中有/web1:当Tomcat收到之后,会到web.xml中寻找对应的Servlet实现类对象名,然后动态代理根据其对应的类路径生成对象,执行业务代码-->
    </servlet-mapping>
</web-app>

验证结果:

  • 若该Servlet的web.xml配置中配置了 load-on-startup 参数为 >=0 的整数

    • 则点击运行Tomcat,发现立即输出了 “MyServlet对象被创建了”

    • 在网页URL中输入 /web1,发现输出了 “doGet中的代码执行结果”

    • 后续再多次在URL中访问 /web1,发现都可以输出doGet的执行结果,但是“MyServlet对象被创建了”再也没出现过

    • 上述现象说明Servlet对象只能被创建一次、但是可以被访问多次

      且还说明了若load-on-startup参数>=0,则Servlet实现类对象会在Tomcat启动时被立即创建

  • 若该Servlet的web.xml配置中没配置 load-on-startup 参数

    • 则点击运行Tomcat,发现什么都没输出(代表Servlet对象还没被初始化,即对象还没被创建)

    • 在网页URL中第一次输入 /web1,发现输出了 “MyServlet对象被创建了” 和 “doGet中的代码执行结果”

    • 上述现象说明Servlet对象若配置了 load-on-startup 参数,则会在Tomcat启动的时候就立即被创建,否则只会等到第一次用到的时候才创建

猜你喜欢

转载自blog.csdn.net/m0_57265007/article/details/128005739