Servlet工作原理解析(二)「建议收藏」

Servlet工作原理解析(二)「建议收藏」上一篇文章简单介绍了Servlet容器的启动、初始化的过程,(链接在这里Servlet工作原理解析(一)),接下来介绍Servlet的创建以及实例化。一:创建Servlet对象 如果Servlet的load-on-startup配置项大于0,那么在Context容器启动时就会被实例化。 前面提到的在解析配置文件时会读取默认的globalWebXml,在conf下的web

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

 上一篇文章简单介绍了Servlet容器的启动、初始化的过程,(链接在这里Servlet工作原理解析(一)),接下来介绍Servlet的创建以及实例化。

一:创建Servlet对象

 如果Servlet的load-on-startup配置项大于0,那么在Context容器启动时就会被实例化。

 前面提到的在解析配置文件时会读取默认的globalWebXml,在conf下的web.xml文件中定义了一些默认的配置项,其中定义了两个Servlet

分别是org.apache.catalina.servlets.DefaultServlet和org.apache.jsper.servlet.JspServelt,它们的load-on-startup分别是1和3,也就是

当tomcat启动时这两个servlet就会被启动。

 创建Servlet实例的方式是从Wrapper.loadServlet开始的,loadServlet方法要完成的就是获取servletClass,然后把它交给Instance

Manager去创建一个基于servletClass.class的对象。如果这个Servlet配置了jsp-file,那么这个servletClass就是在conf/web.xml中定义的

org.apache.jasper.servlet.JspServlet。

二:初始化Servlet

 初始化Servlet在StandardWrapper的initServlet方法中,这个方法很简单,就是调用Servlet的init()方法,同时把包装了Standard

Wrapper对象的StandardWrapperFacade作为ServletConfig传给Servlet(这里为什么不直接把StandardWrapper传给servlet,其实是

门面设计模式,避免把不必要的数据过分暴露给目标,这个后面会介绍到)。

 如果该Servlet关联的是一个JSP文件,那么前面初始化的就是JspServlet,接下来会模拟一次简单请求,请求调用这个JSP文件,以便编

译这个JSP文件为类,并初始化这个类。这样Servlet对象的初始化就完成了,事实上Servlet从背web.xml解析到初始化过程非常复杂,中间

有很多过程,包括各种容器发生的状态变化的引起的监听事件的触发、各种访问权限及异常的处理等。

三:Servlet体系结构
 我们知道 Java Web 应用是基于 Servlet 规范运转的,那么 Servlet 本身又是如何运转的呢?为何要设计这样的体系结构。

Servlet工作原理解析(二)「建议收藏」

 从上图可以看出 Servlet 规范就是基于这几个类运转的,与 Servlet 主动关联的是三个类,分别是 ServletConfig、

ServletRequest 和 ServletResponse。这三个类都是通过容器传递给 Servlet 的,其中 ServletConfig 是在 Servlet 初始化

时就传给 Servlet 了,而后两个是在请求达到时调用 Servlet 时传递过来的。我们很清楚 ServletRequest 和 ServletResponse

在 Servlet 运行的意义,但是 ServletConfig 和 ServletContext 对 Servlet 有何价值?仔细查看 ServletConfig 接口中声明

的方法发现,这些方法都是为了获取这个 Servlet 的一些配置属性,而这些配置属性可能在 Servlet 运行时被用到。而 Servlet

Context 又是干什么的呢? Servlet 的运行模式是一个典型的“握手型的交互式”运行模式。所谓“握手型的交互式”就是两

个模块为了交换数据通常都会准备一个交易场景,这个场景一直跟随个这个交易过程直到这个交易完成为止。这个交易场景的

初始化是根据这次交易对象指定的参数来定制的,这些指定参数通常就会是一个配置类。所以对号入座,交易场景就由 Servlet

Context 来描述,而定制的参数集合就由 ServletConfig 来描述。而 ServletRequest 和 ServletResponse 就是要交互的具体

对象了,它们通常都是作为运输工具来传递交互结果。

 ServletConfig 是在 Servlet init 时由容器传过来的,那么 ServletConfig 到底是个什么对象呢?下图是 ServletConfig

和 ServletContext 在 Tomcat 容器中的类关系图。

Servlet工作原理解析(二)「建议收藏」

 上图可以看出 StandardWrapper 和 StandardWrapperFacade 都实现了 ServletConfig 接口,而 StandardWrapper

Facade 是 StandardWrapper 门面类。所以传给 Servlet 的是 StandardWrapperFacade 对象,这个类能够保证从 Standard

Wrapper 中拿到 ServletConfig 所规定的数据,而又不把 ServletConfig 不关心的数据暴露给 Servlet。

 同样 ServletContext 也与 ServletConfig 有类似的结构,Servlet 中能拿到的 ServletContext 的实际对象也是 Applicat

ionContextFacade 对象。ApplicationContextFacade 同样保证 ServletContex 只能从容器中拿到它该拿的数据,它们都起

到对数据的封装作用,它们使用的都是门面设计模式。

 Servlet 中定义的两个 ServletRequest 和 ServletResponse 它们实际的对象又是什么呢?,我们在创建自己的 Servlet

类时通常使用的都是 HttpServletRequest 和 HttpServletResponse,它们继承了 ServletRequest 和 ServletResponse。

四:Servlet如何工作
 
我们已经清楚了 Servlet 是如何被加载的、Servlet 是如何被初始化的,以及 Servlet 的体系结构,现在的问题就是
它是如何被调用的。

 当用户从浏览器向服务器发起一个请求,通常会包含如下信息:http://hostname: port /contextpath/servletpath,

hostname 和 port 是用来与服务器建立 TCP 连接,而后面的 URL 才是用来选择服务器中那个子容器服务用户的请求。

那服务器是如何根据这个 URL 来达到正确的 Servlet 容器中的呢?Tomcat7.0 中这件事很容易解决,因为这种映射工作有专

门一个类来完成的,这个就是 org.apache.tomcat.util.http.mapper,这个类保存了 Tomcat 的 Container 容器中的所有子

容器的信息,当 org.apache.catalina.connector. Request 类在进入 Container 容器之前,mapper 将会根据这次请求的

hostnane 和 contextpath 将 host 和 context 容器设置到 Request 的 mappingData 属性中。

 所以当 Request进入Container 容器之前,它要访问那个子容器这时就已经确定了。可能你有疑问,mapper 中怎么会有容器的完整关系,这要回到Tomcat启动时序图 中 19 步 MapperListener 类的初始化过程,下面是 MapperListener 的 init 方法代码 :

public void init() {   
        findDefaultHost();   
        Engine engine = (Engine) connector.getService().getContainer();   
        engine.addContainerListener(this);   
        Container[] conHosts = engine.findChildren();   
        for (Container conHost : conHosts) {   
            Host host = (Host) conHost;   
            if (!LifecycleState.NEW.equals(host.getState())) {   
                host.addLifecycleListener(this);   
                registerHost(host);   
            }   
        }   
 }  

 这段代码的作用就是将 MapperListener 类作为一个监听者加到整个 Container 容器中的每个子容器中,这样只要任何
一个容器发生变化,MapperListener 都将会被通知,相应的保存容器关系的 MapperListener 的 mapper 属性也会修改。

for 循环中就是将 host 及下面的子容器注册到 mapper 中。
 下图为Requset在容器中的路由图:
  Servlet工作原理解析(二)「建议收藏」

 Request决定好访问哪个容器的哪个Serlvet之后,接下去就要执行 Servlet 的 service 方法了,通常情况下,我们自己定

义的 servlet 并不是直接去实现 javax.servlet.servlet 接口,而是去继承更简单的 HttpServlet 类或者 GenericServlet 类,我

们可以有选择的覆盖相应方法去实现我们要完成的工作。

 Servlet 的确已经能够帮我们完成所有的工作了,但是现在的 web 应用很少有直接将交互全部页面都用 servlet 来实现,

而是采用更加高效的 MVC 框架来实现。这些 MVC 框架基本的原理都是将所有的请求都映射到一个 Servlet,然后去实现 serv

ice 方法,这个方法也就是 MVC 框架的入口(目前非常流行的SpringMVC,以后以后介绍到)。

 当 Servlet 从 Servlet 容器中移除时,也就表明该 Servlet 的生命周期结束了,这时 Servlet 的 destroy 方法将被调用,

做一些扫尾工作。


 本篇文章介绍了Servlet对象的创建以及初始化、servlet的体系结构以及Servlet是如何工作的,关于Servlet还有两个Listener、

Filter两个组件将在下篇文章中介绍。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/186071.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 网络安全:小心MSHTA漏洞为黑客开启远程控制之门

    网络安全:小心MSHTA漏洞为黑客开启远程控制之门这是一个可以让黑客欣喜若狂的新漏洞,一旦该漏洞被激活,就会有大量计算机成为黑客手中的肉鸡,被人远程控制不可避免……  微软的Windows操作系统在进行了短暂的“喘息”后,近日又在攻击爱好者不懈努力下,被成功找出几个高危的系统安全漏洞,而MicrosoftWindowsMSHTA脚本执行漏洞就是其中的重要一员。  安全公告牌  MSHTA即HTA,此处的MS主要用于强调这是微软的

    2022年7月15日
    14
  • chrome浏览器多开_双开软件默认打开软件更改

    chrome浏览器多开_双开软件默认打开软件更改#include<windows.h>#include<stdio.h>intmain(intargc,char*argv[]){//初始化临界区全局原子变量HANDLEMutexHandle=CreateMutex(NULL,FALSE,TEXT(“AAA”));//创建互斥体.信号量为0.有信号的状态.wait可以等待DWORDErrorCode=0;ErrorCode=GetLastError

    2022年10月5日
    0
  • Linux下Redis开机自启(Centos)

    Linux下Redis开机自启(Centos)

    2021年10月27日
    49
  • 视频监控知识

    视频监控知识CIF分辨率CIF分辨率 CIFcommonintermediateformat DCIFdoubleintermediateformat QCIFquartercommonintermediateformat 图象格式 亮度取样的象素个…

    2022年6月28日
    25
  • 电路驱动能力

    电路驱动能力1.在电子电路中为什么有的地方电压会被拉低2,驱动能力是什么意思,如何提高驱动能力在很多资料上看到说驱动能力不够是因为提供的电流太小,为什么不说电压呢?在很多限制的条件都是电流而不是电压,为什么?电压和电流满足欧姆定律,考虑谁不是都一样吗?还有就是,在什么情况下要考虑驱动能力,是不是只有在集成电路输出口要考虑?那你怎么知道这个集成电路驱动能力是不是不够?在平常的电路中(非集成电路I

    2022年5月13日
    52
  • 详述Java中sort排序函数

    详述Java中sort排序函数手写一个排序算法的效率是很慢的,当然这也不利于我们在比赛或者工程中的实战,如今几乎每个语言的标准库中都有排序算法,今天让我来给大家讲解一下Java语言中的sort排序Collections类中的sort方法可以实现List接口的集合进行排序降序排序Java中降序排序有俩种方法(和c++很类似,可以看我这篇博客):c++sort排序实现Comparator接口的复写compare()方法排序原理通常,在看有关算法书籍的时候,会发现都说有关数组的排序算法,而且使用的都是随机访问,但是

    2022年7月12日
    14

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号