深入拆解Tomcat & Jetty
李号双
eBay技术主管
立即订阅
6067 人已学习
课程目录
已完结 44 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | Java程序员如何快速成长?
免费
模块一 必备基础 (4讲)
01 | Web容器学习路径
02 | HTTP协议必知必会
03 | 你应该知道的Servlet规范和Servlet容器
04 | 实战:纯手工打造和运行一个Servlet
模块二 整体架构 (9讲)
05 | Tomcat系统架构(上): 连接器是如何设计的?
06 | Tomcat系统架构(下):聊聊多层容器的设计
07 | Tomcat如何实现一键式启停?
08 | Tomcat的“高层们”都负责做什么?
09 | 比较:Jetty架构特点之Connector组件
10 | 比较:Jetty架构特点之Handler组件
11 | 总结:从Tomcat和Jetty中提炼组件化设计规范
12 | 实战:优化并提高Tomcat启动速度
13 | 热点问题答疑(1):如何学习源码?
模块三 连接器 (9讲)
14 | NioEndpoint组件:Tomcat如何实现非阻塞I/O?
15 | Nio2Endpoint组件:Tomcat如何实现异步I/O?
16 | AprEndpoint组件:Tomcat APR提高I/O性能的秘密
17 | Executor组件:Tomcat如何扩展Java线程池?
18 | 新特性:Tomcat如何支持WebSocket?
19 | 比较:Jetty的线程策略EatWhatYouKill
20 | 总结:Tomcat和Jetty中的对象池技术
21 | 总结:Tomcat和Jetty的高性能、高并发之道
22 | 热点问题答疑(2):内核如何阻塞与唤醒进程?
模块四 容器 (8讲)
23 | Host容器:Tomcat如何实现热部署和热加载?
24 | Context容器(上):Tomcat如何打破双亲委托机制?
25 | Context容器(中):Tomcat如何隔离Web应用?
26 | Context容器(下):Tomcat如何实现Servlet规范?
27 | 新特性:Tomcat如何支持异步Servlet?
28 | 新特性:Spring Boot如何使用内嵌式的Tomcat和Jetty?
29 | 比较:Jetty如何实现具有上下文信息的责任链?
30 | 热点问题答疑(3):Spring框架中的设计模式
模块五 通用组件 (4讲)
31 | Logger组件:Tomcat的日志框架及实战
32 | Manager组件:Tomcat的Session管理机制解析
33 | Cluster组件:Tomcat的集群通信原理
特别放送 | 如何持续保持对学习的兴趣?
模块六 性能优化 (8讲)
34 | JVM GC原理及调优的基本思路
35 | 如何监控Tomcat的性能?
36 | Tomcat I/O和线程池的并发调优
37 | Tomcat内存溢出的原因分析及调优
38 | Tomcat拒绝连接原因分析及网络优化
39 | Tomcat进程占用CPU过高怎么办?
40 | 谈谈Jetty性能调优的思路
41 | 热点问题答疑(4): Tomcat和Jetty有哪些不同?
结束语 (1讲)
结束语 | 静下心来,品味经典
深入拆解Tomcat & Jetty
登录|注册

03 | 你应该知道的Servlet规范和Servlet容器

李号双 2019-05-16
通过专栏上一期的学习我们知道,浏览器发给服务端的是一个 HTTP 格式的请求,HTTP 服务器收到这个请求后,需要调用服务端程序来处理,所谓的服务端程序就是你写的 Java 类,一般来说不同的请求需要由不同的 Java 类来处理。
那么问题来了,HTTP 服务器怎么知道要调用哪个 Java 类的哪个方法呢。最直接的做法是在 HTTP 服务器代码里写一大堆 if else 逻辑判断:如果是 A 请求就调 X 类的 M1 方法,如果是 B 请求就调 Y 类的 M2 方法。但这样做明显有问题,因为 HTTP 服务器的代码跟业务逻辑耦合在一起了,如果新加一个业务方法还要改 HTTP 服务器的代码。
那该怎么解决这个问题呢?我们知道,面向接口编程是解决耦合问题的法宝,于是有一伙人就定义了一个接口,各种业务类都必须实现这个接口,这个接口就叫 Servlet 接口,有时我们也把实现了 Servlet 接口的业务类叫作 Servlet。
但是这里还有一个问题,对于特定的请求,HTTP 服务器如何知道由哪个 Servlet 来处理呢?Servlet 又是由谁来实例化呢?显然 HTTP 服务器不适合做这个工作,否则又和业务类耦合了。
于是,还是那伙人又发明了 Servlet 容器,Servlet 容器用来加载和管理业务类。HTTP 服务器不直接跟业务类打交道,而是把请求交给 Servlet 容器去处理,Servlet 容器会将请求转发到具体的 Servlet,如果这个 Servlet 还没创建,就加载并实例化这个 Servlet,然后调用这个 Servlet 的接口方法。因此 Servlet 接口其实是 Servlet 容器跟具体业务类之间的接口。下面我们通过一张图来加深理解。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Tomcat & Jetty 》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(82)

  • 天琊 置顶
    文章中提到
    1.SpringMVC 容器实在DispatcherServlet中init方法里创建的。
    2.Spring 容器是通过Listener创建的
    a、就是说SpringMVC容器和Spring容器还不一样,那么他们是什么关系?
    b、他们和Servlet容器又是啥关系?

    作者回复: Tomcat&Jetty在启动时给每个Web应用创建一个全局的上下文环境,这个上下文就是ServletContext,其为后面的Spring容器提供宿主环境。

    Tomcat&Jetty在启动过程中触发容器初始化事件,Spring的ContextLoaderListener会监听到这个事件,它的contextInitialized方法会被调用,在这个方法中,Spring会初始化全局的Spring根容器,这个就是Spring的IoC容器,IoC容器初始化完毕后,Spring将其存储到ServletContext中,便于以后来获取。

    Tomcat&Jetty在启动过程中还会扫描Servlet,一个Web应用中的Servlet可以有多个,以SpringMVC中的DispatcherServlet为例,这个Servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个Servlet请求。

    Servlet一般会延迟加载,当第一个请求达到时,Tomcat&Jetty发现DispatcherServlet还没有被实例化,就调用DispatcherServlet的init方法,DispatcherServlet在初始化的时候会建立自己的容器,叫做SpringMVC 容器,用来持有Spring MVC相关的Bean。同时,Spring MVC还会通过ServletContext拿到Spring根容器,并将Spring根容器设为SpringMVC容器的父容器,请注意,Spring MVC容器可以访问父容器中的Bean,但是父容器不能访问子容器的Bean, 也就是说Spring根容器不能访问SpringMVC容器里的Bean。说的通俗点就是,在Controller里可以访问Service对象,但是在Service里不可以访问Controller对象。

    2019-05-16
    6
    151
  • 0.618
    笔记总结:
    1.Servlet规范:Servlet和Servlet容器的一整套规则
    2.Servlet和Servlet的出现是为了解耦http服务器和业务逻辑
    3.ServletRequest和ServletResponse对象是对通信协议的封装
    4.Servlet接口有5个方法,其中包括生命周期函数两个:init和destroy;获取信息的函数两个:getServletConfig和getServletInfo;还有一个就是业务逻辑处理方法:service
    5.一个ServletContext接口对应一个web应用,它持有web应用中的所有servlet,所以可以通过它来实现请求在Servlet之间的转发
    6.Servlet容器的扩展机制:Filter接口和Listener接口,前者是基于过程的,后者是基于状态的
    2019-05-16
    27
  • 仙道
    servlet容器的Filter跟 spring 的intercepter 有啥区别

    作者回复: Filter是Servlet规范的一部分,是Servlet容器Tomcat实现的。Intercepter是Spring发明的。它们的执行顺序是:


    Filter.doFilter();

    HandlerInterceptor.preHandle();

    Controller

    HandlerInterceptor.postHandle();

    DispatcherServlet 渲染视图

    HandlerInterceptor.afterCompletion();

    Filter.doFilter(); Servlet方法返回

    2019-05-20
    26
  • 一路远行
    spring容器只是servlet容器上下文(ServletContext)的一个属性,web容器启动时通过ServletContextListener机制构建出来
    2019-05-16
    19
  • neohope
    Servlet容器,是用于管理Servlet生命周期的。
    Spring容器,是用于管理Spring Bean生命周期的。
    SpringMVC容器,适用于管理SpringMVC Bean生命周期的。

    Tomcat/Jetty启动,对于每个WebApp,依次进行初始化工作:
    1、对每个WebApp,都有一个WebApp ClassLoader,和一个ServletContext
    2、ServletContext启动时,会扫描web.xml配置文件,找到Filter、Listener和Servlet配置

    3、如果Listener中配有spring的ContextLoaderListener
    3.1、ContextLoaderListener就会收到webapp的各种状态信息。
    3.3、在ServletContext初始化时,ContextLoaderListener也就会将Spring IOC容器进行初始化,管理Spring相关的Bean。
    3.4、ContextLoaderListener会将Spring IOC容器存放到ServletContext中

    4、如果Servlet中配有SpringMVC的DispatcherServlet
    4.1、DispatcherServlet初始化时(其一次请求到达)。
    4.2、其中,DispatcherServlet会初始化自己的SpringMVC容器,用来管理Spring MVC相关的Bean。
    4.3、SpringMVC容器可以通过ServletContext获取Spring容器,并将Spring容器设置为自己的根容器。而子容器可以访问父容器,从而在Controller里可以访问Service对象,但是在Service里不可以访问Controller对象。
    4.2、初始化完毕后,DispatcherServlet开始处理MVC中的请求映射关系。

    有一个很坑问题,Servlet默认是单例模式的,Spring的Bean默认是单例模式的,那Spring MVC是如何处理并发请求的呢?

    作者回复: DispatcherServlet中的成员变量都是初始化好后就不会被改变了,所以是线程安全的,那“可见性”怎么保证呢?

    这是由Web容器比如Tomcat来做到的,Tomcat在调用Servlet的init方法时,用了synchronized。

    private synchronized void initServlet(Servlet servlet)
    {...}

    2019-05-19
    1
    15
  • Monday
    基于思考题,我在梦中醒来,觉得servlet容器管理的是servlet(把controller也理解成了servlet),spring容器则是管理service,DAO这类bean。这样理解的话springMVC不就是多余的了吗?但是我们项目中都有使用springMVC,存在即合理,所以我的理解是有误的。于是想老师帮忙给出以下三张图。非常感谢,
    1,恳求老师能给出servlet,spring,springMVC三个容器的关系图。
    2,恳求老师给出初始化三个容器的顺序图
    3,恳求老师给出tomcat在响应客户端请求时,以上3个容器的分工以及各自是在什么时候产生作用的。类似于第2节http必知必会中,用户在浏览器输入url到最后浏览器返回展示的那样的11步的图,并做出每一步的解释。
    PS:本文通读不少于3遍,收获颇丰。提这个问题是手机敲的字,和整理提问思路一起花了半小时。

    作者回复: 本来想自己画一张,但是在网上找了一下,找到这张图,蛮清楚的:

    https://blog.csdn.net/zhanglf02/article/details/89791797

    2019-05-17
    12
  • 老王的老李头
    spring容器中还包含许多的子容器,其中springmvc容器就是其中常用的一个,文中的DispatcherServlet就是springmvc容器中的servlet接口,也是springmvc容器的核心类。spring容器主要用于整个Web应用程序需要共享的一些组件,比如DAO、数据库的ConnectionFactory等,springmvc的容器主要用于和该Servlet相关的一些组件,比如Controller、ViewResovler等。至此就清楚了spring容器内部的关系,那servlet容器跟spring容器又有什么关系呢?有人说spring容器是servlet容器的子容器,但是这个servlet容器到底是tomcat实现的容器呢,还是jetty实现的容器呢?所以我觉得spring容器与servlet容器他们之间并没有直接的血缘关系,可以说spring容器依赖了servlet容器,spring容器的实现遵循了Servlet 规范。不知道这么理解是可以,还请老师给予指导?

    作者回复: 对的,说的很好

    2019-05-16
    1
    12
  • Geek_ebda96
    老师,spring容器指的是spring本身的ioc容器吧,是用来管理所有的bean,servlet本身会把sping的容器设置到上下文中,而spring mvc的容器dispatch servlet相当于是一个具体的servlet的实现,然后会创建一个全局的上下文application context spring的ioc容器会注入到这个上下文中,后面通过上下文getbean,其实是先找到上下文中的ioc容器,然后再从这个容器拿到具体的bean,这是不是对的?

    作者回复: 不太准确哦,首先我们明确一点,Spring和SpringMVC分别有自己的IOC容器或者说上下文。

    为什么要分成两个容器呢?为了职责划分清晰。

    SpringMVC的容器直接管理跟DispatcherServlet相关的Bean,也就是Controller,ViewResolver等,并且SpringMVC容器是在DispacherServlet的init方法里创建的。而Spring容器管理其他的Bean比如Service和DAO。

    并且SpringMVC容器是Spring容器的子容器,所谓的父子关系意味着什么呢,就是你通过子容器去拿某个Bean时,子容器先在自己管理的Bean中去找这个Bean,如果找不到再到父容器中找。但是父容器不能到子容器中去找某个Bean。

    其实这个套路跟JVM的类加载器设计有点像,不同的类加载器也为了隔离,不过加载顺序是反的,子加载器总是先委托父加载器去加载某个类,加载不到再自己来加载。

    2019-05-17
    6
  • 石头狮子
    servlet 容器抽象了网络处理,请求封装等事情,同样提供了可以处理其他非 http 协议的能力。
    spring 容器是依赖注入设计模式的体现,其主要抽象了类初始化,注入,依赖解决,动态代理等功能。
    两者主要解决的问题不同。

    作者回复: 我理解你说的Servlet容器应该是说HTTP服务器+Servlet容器,Servlet容器本身只管Servlet的事,不管HTTP协议的解析

    2019-05-16
    6
  • 刘三通
    servlet容器初始化成功后被spring监听,创建spring容器放入servlet容器中,访问到达,初始化dispatcher servlet时创建springmvc容器,通过servletContext拿到spring容器,并将其作为自己的父容器,spring mvc容器会定义controller相关的bean,spring会定义业务逻辑相关的bean
    2019-05-19
    5
  • QQ怪

    Spring容器是管理service和dao的,

    SpringMVC容器是管理controller对象的,

    Servlet容器是管理servlet对象的。
    2019-05-16
    4
  • allean
    有收获,跟着专栏一步步深入
    2019-05-16
    3
  • jaryoung
    没有Spring boot以前,他们的关系为tomcat抱着Spring的关系,有了Spring boot之后他们关系刚好反过来。

    作者回复: 对的

    2019-08-14
    2
  • 李青
    老师给你个大大的赞,讲课方式是我很喜欢的风格,先抛出问题,再讲思路和解决方案。以后讲课希望一直用这个风格

    作者回复: 😑,谢谢

    2019-05-21
    2
  • -W.LI-
    老师好!我看留言里有同学说,spring上下文负责创建service和dao的bean,MVC负责创建controller的bean。我们平时说的IOC容器是指哪个啊?还有就是controller注解是一个组合注解,我在controller上用service注解一样能注册成功,spring和MVC容器又是怎么区分这个bean是controller还是service,或者是dao,bean的?还是我完全理解错了。

    作者回复: SpringBoot中只有一个Spring上下文:
    org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext

    你可以在FrameworkServlet.initWebApplicationContext方法中下个断点。

    2019-05-18
    2
  • DFighting
    提个建议吧,这些知识以前也都看过,博客,书本等等,老师讲的比较系统,看起来也有不少收获,但是没机会实践验证和加深自己的理解是最难受的,上课的时候也实现过简单是Servlet,但都不成体系,也很难和实际结合起来,希望老师在后面中高级模块解析的时候能不能在一开始准备一个经典的项目,一边实践一遍学习我觉得会好很多。

    作者回复: 完全理解,你可以把Tomcat和Jetty本身当成一个项目,源码跑起来,再结合专栏的讲解,理解Java技术该怎么用

    2019-05-17
    2
  • Berry Wang
    老师好,请问下http服务器指的是什么?跟tomcat什么关系?

    作者回复: 你可以把HTTP服务器理解为Tomcat的一部分。

    2019-05-17
    2
  • 星辰
    1. 一个应用中的多个Servlet共享唯一的一个ServletContext不会有问题嘛?
      老师,求告知这个源码的入口从哪里看啊?

    2.我猜想Spring容器是管理Servlet容器的吧? 一个Spring容器可以被多个Servlet容器共享吗,不会有问题吗?

    李老师,我底子差,可能专栏的文字与音频篇幅有限,
    恳请您也在极客邦的github下建一个仓库,这样后面接下来的章节中如果遇到源代码的讲解,或者类似这种tomcat容器源代码的讲解,或者Spring容器的讲解,可以以代码或者其他文件形式给大家看看嘛~!让我们通过您更多的分享可以理解的更透彻一点~!

    3. 老师,tomcat容器的入口是ServletContext吗? spring容器的入口是dispatcherServlet吗?

    ps:一篇引人思考的技术类文章不应该它写完了,普及度就降低了。应该让后续的人读完之后在这篇文章的引导下能通过自己的努力弄明白它原来是什么样子的。 很多人在看与学的过程中苦于没有人讨论,交流而显得很闭塞。我就是其中之一。 这也可能能增加大家的讨论热度吧~!

    可能我说的太多了, 也可能不多,不过还是要谢谢老师的讲解~!

    作者回复: Zach_你好, 谢谢关注:)
    1.. 由于ServletContext是全局对象,对它的访问不是线程安全的,要加锁, 源码的话你可以看Tomcat中的类ApplicationContext。

    2. Spring容器不会管理Servlet容器,它们的关系你可以看置顶的那个答案。

    3.Tomcat中的Servlet容器的入口叫做Engine,这里后面也会详细讲到的~

    至于你说的github建仓库的事我得跟极客时间商量一下~

    2019-05-16
    2
  • Gdaniel
    感受到老师的真诚和负责,支持买来研读。
    2019-06-21
    1
  • 琦玉
    请问service方法为什么把request和response都当作输入参数,而不是输入参数只有request,response放到返回值里呢?

    作者回复: 方便责任链模式下层层传递

    2019-05-31
    1
收起评论
82
返回
顶部